为什么当我左键单击窗口时 Open3d Visualization 消失?

Jos*_*chi 4 python user-interface open3d

我尝试用 python 编写一个简单的应用程序,该应用程序在右侧查看 3d 网格,并在单个窗口的左侧显示一些用户输入。

我使用 SceneWidget 来可视化网格并将其添加到水平 gui 元素。我还将文件选择器添加到该 gui 元素,然后将 gui 元素添加到窗口。到目前为止,它似乎按预期工作,但是一旦我在窗口内单击左键,可视化就会消失,并且没有错误消息。有谁知道为什么并且可以帮助我吗? 应用程序的短视频 - 左键单击即可停止可视化

这是代码:

import os.path
import sys

import open3d as o3d
import open3d.visualization.gui as gui
import open3d.visualization.rendering as rendering

print("Project")
print("python version", sys.version)
print("open3d version", o3d.__version__)

class WindowApp:

    def __init__(self):
        self.window = gui.Application.instance.create_window("Project", 1400, 900)
        w = self.window

        # member variables
        self.model_dir = ""
        self.model_name = ""
        
        em = w.theme.font_size
        layout = gui.Horiz(0, gui.Margins(0.5 * em, 0.5 * em, 0.5 * em, 0.5 * em))
        # 3D Widget
        _widget3d = gui.SceneWidget()
        _widget3d.scene = rendering.Open3DScene(w.renderer)
        _widget3d.set_view_controls(gui.SceneWidget.Controls.ROTATE_CAMERA)
        mesh = o3d.geometry.TriangleMesh.create_sphere()
        mesh.compute_vertex_normals()
        material = rendering.MaterialRecord()
        material.shader = "defaultLit"
        _widget3d.scene.add_geometry('mesh', mesh, material)
        _widget3d.scene.set_background([200, 0, 0, 200]) # not working?!
        _widget3d.scene.camera.look_at([0, 0, 0], [1, 1, 1], [0, 0, 1])
        _widget3d.set_on_mouse(self._on_mouse_widget3d)

        # gui layout
        gui_layout = gui.Vert(0, gui.Margins(0.5 * em, 0.5 * em, 0.5 * em, 0.5 * em))
        # File-chooser widget
        self._fileedit = gui.TextEdit()
        filedlgbutton = gui.Button("...")
        filedlgbutton.horizontal_padding_em = 0.5
        filedlgbutton.vertical_padding_em = 0
        filedlgbutton.set_on_clicked(self._on_filedlg_button)

        fileedit_layout = gui.Horiz()
        fileedit_layout.add_child(gui.Label("Model file"))
        fileedit_layout.add_child(self._fileedit)
        fileedit_layout.add_fixed(0.25 * em)
        fileedit_layout.add_child(filedlgbutton)
        # add to the top-level (vertical) layout
        gui_layout.add_child(fileedit_layout)

        layout.add_child(gui_layout)
        layout.add_child(_widget3d)
        w.add_child(layout)

    def _on_mouse_widget3d(self, event):
        print(event.type)
        return gui.Widget.EventCallbackResult.IGNORED

    def _on_filedlg_button(self):
        filedlg = gui.FileDialog(gui.FileDialog.OPEN, "Select file",
                                 self.window.theme)
        filedlg.add_filter(".obj .ply .stl", "Triangle mesh (.obj, .ply, .stl)")
        filedlg.add_filter("", "All files")
        filedlg.set_on_cancel(self._on_filedlg_cancel)
        filedlg.set_on_done(self._on_filedlg_done)
        self.window.show_dialog(filedlg)

    def _on_filedlg_cancel(self):
        self.window.close_dialog()

    def _on_filedlg_done(self, path):
        self._fileedit.text_value = path
        self.model_dir = os.path.normpath(path)
        # load model
        self.window.close_dialog()

def main():
    gui.Application.instance.initialize()
    w = WindowApp()
    gui.Application.instance.run()

if __name__ == "__main__":
    main()
Run Code Online (Sandbox Code Playgroud)

我使用open3d库版本0.15.1和python3.9。

注意 - 如果我将 SceneWidget 直接添加到窗口中,它可以工作,但是我不能将 gui 放在左侧。

有人有解决办法吗?

Jos*_*chi 5

最后我找到了一个解决方案:将 Scenewidget 添加到 gui 容器似乎不起作用。但是将其封装在框架内并将其移动到右侧并将其直接添加到窗口中是可行的。 _widget3d.frame = gui.Rect(500, w.content_rect.y, 900, w.content_rect.height) 以类似的方式创建 GUI 框架也是可能的。

这是任何感兴趣的人的工作代码:

class WindowApp:

    def __init__(self):
        self.window = gui.Application.instance.create_window("Spinnables", 1400, 900)
        w = self.window

        # member variables
        self.model_dir = ""
        self.model_name = ""

        em = w.theme.font_size
        # 3D Widget
        _widget3d = gui.SceneWidget()
        _widget3d.scene = rendering.Open3DScene(w.renderer)
        _widget3d.set_view_controls(gui.SceneWidget.Controls.ROTATE_CAMERA)
        # create a frame that encapsulates the Scenewidget
        _widget3d.frame = gui.Rect(500, w.content_rect.y,
                                        900, w.content_rect.height)
        mesh = o3d.geometry.TriangleMesh.create_sphere()
        mesh.compute_vertex_normals()
        material = rendering.MaterialRecord()
        material.shader = "defaultLit"
        _widget3d.scene.add_geometry('mesh', mesh, material)
        _widget3d.scene.set_background([200, 0, 0, 200]) # not working?!
        _widget3d.scene.camera.look_at([0, 0, 0], [1, 1, 1], [0, 0, 1])
        _widget3d.set_on_mouse(self._on_mouse_widget3d)

        # gui layout
        gui_layout = gui.Vert(0, gui.Margins(0.5 * em, 0.5 * em, 0.5 * em, 0.5 * em))
        # create frame that encapsulates the gui
        gui_layout.frame = gui.Rect(w.content_rect.x, w.content_rect.y,
                                    500, w.content_rect.height)
        # File-chooser widget
        self._fileedit = gui.TextEdit()
        filedlgbutton = gui.Button("...")
        filedlgbutton.horizontal_padding_em = 0.5
        filedlgbutton.vertical_padding_em = 0
        filedlgbutton.set_on_clicked(self._on_filedlg_button)

        fileedit_layout = gui.Horiz()
        fileedit_layout.add_child(gui.Label("Model file"))
        fileedit_layout.add_child(self._fileedit)
        fileedit_layout.add_fixed(0.25 * em)
        fileedit_layout.add_child(filedlgbutton)
        # add to the top-level (vertical) layout
        gui_layout.add_child(fileedit_layout)

        w.add_child(gui_layout)
        w.add_child(_widget3d)
Run Code Online (Sandbox Code Playgroud)