为什么当我左键单击 window 时 Open3d Visualization 消失了?

Why does Open3d Visualization disappear when I left click the window?

我尝试在 python 中编写一个简单的应用程序,它在右侧查看 3d 网格,并在单个 window.

中在左侧显示一些用户输入

我使用 SceneWidget 可视化网格并将其添加到水平 gui 元素。我还向该 gui 元素添加了一个文件选择器,然后将 gui 元素添加到 window。 到目前为止一切顺利,它似乎按预期工作,但只要我在 window 内单击鼠标左键,可视化就会消失,没有任何错误消息。 有谁知道为什么并且可以帮助我吗?

代码如下:

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()

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

注意 - 如果我将 SceneWidget 直接添加到 window 它可以工作,但是我不能在左边有 gui。

有人对此有解决方案吗?

最后我找到了解决办法: 将 Scenewidget 添加到 gui 容器似乎不起作用。但是将它封装在一个框架内并将其移动到右侧并直接将其添加到 window 工作。 _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)