主页 > 开源代码  > 

Open3D解决SceneWidget加入布局中消失的问题

Open3D解决SceneWidget加入布局中消失的问题

Open3D解决SceneWidget加入布局中消失的问题 Open3D解决SceneWidget加入布局中消失的问题1. 问题2. 问题代码3. 解决

Open3D解决SceneWidget加入布局中消失的问题 1. 问题

把SceneWidget加到布局管理其中图形可以展示出来,但是鼠标点击就消失了。

stackoverflow上已经有人提出这个问题了,还是2022年的时候,可是现在好像也没有解决。 stackoverflow /questions/71706506/why-does-open3d-visualization-disappear-when-i-left-click-the-window

2. 问题代码

# ---------------------------------------------------------------------------- # - Open3D: .open3d.org - # ---------------------------------------------------------------------------- # Copyright (c) 2018-2024 .open3d.org # SPDX-License-Identifier: MIT # ---------------------------------------------------------------------------- import open3d as o3d import open3d.visualization.gui as gui import open3d.visualization.rendering as rendering import platform import random import threading import time isMacOS = (platform.system() == "Darwin") # This example shows two methods of adding geometry to an existing scene. # 1) add via a UI callback (in this case a menu, but a button would be similar, # you would call `button.set_on_clicked(self.on_menu_sphere_)` when # configuring the button. See `on_menu_sphere()`. # 2) add asynchronously by polling from another thread. GUI functions must be # called from the UI thread, so use Application.post_to_main_thread(). # See `on_menu_random()`. # Running the example will show a simple window with a Debug menu item with the # two different options. The second method will add random spheres for # 20 seconds, during which time you can be interacting with the scene, rotating, # etc. class SpheresApp: MENU_SPHERE = 1 MENU_RANDOM = 2 MENU_QUIT = 3 def __init__(self): self._id = 0 self.window = gui.Application.instance.create_window( "Add Spheres Example", 800, 600) # The menu is global (because the macOS menu is global), so only create # it once, no matter how many windows are created if gui.Application.instance.menubar is None: if isMacOS: app_menu = gui.Menu() app_menu.add_item("Quit", SpheresApp.MENU_QUIT) debug_menu = gui.Menu() debug_menu.add_item("Add Sphere", SpheresApp.MENU_SPHERE) debug_menu.add_item("Add Random Spheres", SpheresApp.MENU_RANDOM) if not isMacOS: debug_menu.add_separator() debug_menu.add_item("Quit", SpheresApp.MENU_QUIT) menu = gui.Menu() if isMacOS: # macOS will name the first menu item for the running application # (in our case, probably "Python"), regardless of what we call # it. This is the application menu, and it is where the # About..., Preferences..., and Quit menu items typically go. menu.add_menu("Example", app_menu) menu.add_menu("Debug", debug_menu) else: menu.add_menu("Debug", debug_menu) gui.Application.instance.menubar = menu # The menubar is global, but we need to connect the menu items to the # window, so that the window can call the appropriate function when the # menu item is activated. self.window.set_on_menu_item_activated(SpheresApp.MENU_SPHERE, self._on_menu_sphere) self.window.set_on_menu_item_activated(SpheresApp.MENU_RANDOM, self._on_menu_random) self.window.set_on_menu_item_activated(SpheresApp.MENU_QUIT, self._on_menu_quit) self.scene = gui.SceneWidget() self.scene.scene = rendering.Open3DScene(self.window.renderer) self.scene.scene.show_axes(True) mesh = o3d.geometry.TriangleMesh.create_sphere() mesh pute_vertex_normals() material = rendering.MaterialRecord() material.shader = "defaultLit" self.scene.scene.add_geometry("sphere" + str(self._id), mesh, material) em = self.window.theme.font_size self.layout = gui.Horiz(0, gui.Margins(0.25*em,0.25*em,0.25*em,0.254*em)) self.layout.add_child(gui.Label("Model file")) self.layout.add_fixed(0.25 * em) self.window.set_on_layout(self.on_window_layout) self.vlayout = gui.Vert(0, gui.Margins(0.25 * em, 0.25 * em, 0.25 * em, 0.254 * em)) self.vlayout.add_child(self.scene) self.vlayout.add_fixed(0.25 * em) self.window.add_child(self.vlayout) self.window.add_child(self.layout) def on_window_layout(self, layout: gui.LayoutContext) -> None: """ This is called when layout is required for this widgets *immediate children*, like on resize. Only the immediate children are *manually* positioned here, by setting the x, y, width, and height of their frames. The grandchildren are *not* touched here; they're automatically handled after this. """ # This is the area in this widget available to place child widgets in. The *units* here aren't window screen # pixels, like from the width/height here when setting up the window: gui.Application.instance.create_window("Test", width=500, height=600). rect = self.window.content_rect r = self.window.content_rect print(r) print(layout.theme.default_layout_spacing) print(layout.theme.default_margin) print(layout.theme.font_size) # Put the layout (containing the controls) on the left 1/3 and the and scene on the right 2/3. x_division = rect.width // 3 # Set the layout (gui.Vert) on left to 1/3 available width, full height. # gui.Rect(x, y, width, height) # Set the SceneWidget on on right, 2/3 available width, full height self.vlayout.frame = gui.Rect(0, 0, r.width - x_division, r.height) self.layout.frame = gui.Rect(r.width - x_division, 0, x_division, r.height) def add_sphere(self): self._id += 1 mat = rendering.MaterialRecord() mat.base_color = [ random.random(), random.random(), random.random(), 1.0 ] mat.shader = "defaultLit" sphere = o3d.geometry.TriangleMesh.create_sphere(0.5) sphere pute_vertex_normals() sphere.translate([ 10.0 * random.uniform(-1.0, 1.0), 10.0 * random.uniform(-1.0, 1.0), 10.0 * random.uniform(-1.0, 1.0) ]) self.scene.scene.add_geometry("sphere" + str(self._id), sphere, mat) def _on_menu_sphere(self): # GUI callbacks happen on the main thread, so we can do everything # normally here. self.scene.scene.clear_geometry() self.add_sphere() def _on_menu_random(self): # This adds spheres asynchronously. This pattern is useful if you have # data coming in from another source than user interaction. def thread_main(): for _ in range(0, 20): # We can only modify GUI objects on the main thread, so we # need to post the function to call to the main thread. gui.Application.instance.post_to_main_thread( self.window, self.add_sphere) time.sleep(0.5) threading.Thread(target=thread_main).start() def _on_menu_quit(self): gui.Application.instance.quit() def main(): gui.Application.instance.initialize() SpheresApp() gui.Application.instance.run() if __name__ == "__main__": main() 3. 解决

不能放在布局中就直接手动布局吧, 不加到布局中去。。。

# ---------------------------------------------------------------------------- # - Open3D: .open3d.org - # ---------------------------------------------------------------------------- # Copyright (c) 2018-2024 .open3d.org # SPDX-License-Identifier: MIT # ---------------------------------------------------------------------------- import open3d as o3d import open3d.visualization.gui as gui import open3d.visualization.rendering as rendering import platform import random import threading import time isMacOS = (platform.system() == "Darwin") # This example shows two methods of adding geometry to an existing scene. # 1) add via a UI callback (in this case a menu, but a button would be similar, # you would call `button.set_on_clicked(self.on_menu_sphere_)` when # configuring the button. See `on_menu_sphere()`. # 2) add asynchronously by polling from another thread. GUI functions must be # called from the UI thread, so use Application.post_to_main_thread(). # See `on_menu_random()`. # Running the example will show a simple window with a Debug menu item with the # two different options. The second method will add random spheres for # 20 seconds, during which time you can be interacting with the scene, rotating, # etc. class SpheresApp: MENU_SPHERE = 1 MENU_RANDOM = 2 MENU_QUIT = 3 def __init__(self): self._id = 0 self.window = gui.Application.instance.create_window( "Add Spheres Example", 800, 600) # The menu is global (because the macOS menu is global), so only create # it once, no matter how many windows are created if gui.Application.instance.menubar is None: if isMacOS: app_menu = gui.Menu() app_menu.add_item("Quit", SpheresApp.MENU_QUIT) debug_menu = gui.Menu() debug_menu.add_item("Add Sphere", SpheresApp.MENU_SPHERE) debug_menu.add_item("Add Random Spheres", SpheresApp.MENU_RANDOM) if not isMacOS: debug_menu.add_separator() debug_menu.add_item("Quit", SpheresApp.MENU_QUIT) menu = gui.Menu() if isMacOS: # macOS will name the first menu item for the running application # (in our case, probably "Python"), regardless of what we call # it. This is the application menu, and it is where the # About..., Preferences..., and Quit menu items typically go. menu.add_menu("Example", app_menu) menu.add_menu("Debug", debug_menu) else: menu.add_menu("Debug", debug_menu) gui.Application.instance.menubar = menu # The menubar is global, but we need to connect the menu items to the # window, so that the window can call the appropriate function when the # menu item is activated. self.window.set_on_menu_item_activated(SpheresApp.MENU_SPHERE, self._on_menu_sphere) self.window.set_on_menu_item_activated(SpheresApp.MENU_RANDOM, self._on_menu_random) self.window.set_on_menu_item_activated(SpheresApp.MENU_QUIT, self._on_menu_quit) self.scene = gui.SceneWidget() self.scene.scene = rendering.Open3DScene(self.window.renderer) self.scene.scene.show_axes(True) mesh = o3d.geometry.TriangleMesh.create_sphere() mesh pute_vertex_normals() material = rendering.MaterialRecord() material.shader = "defaultLit" self.scene.scene.add_geometry("sphere" + str(self._id), mesh, material) em = self.window.theme.font_size self.layout = gui.Horiz(0, gui.Margins(0.25*em,0.25*em,0.25*em,0.254*em)) self.layout.add_child(gui.Label("Model file")) self.layout.add_fixed(0.25 * em) self.window.set_on_layout(self.on_window_layout) self.window.add_child(self.scene) self.window.add_child(self.layout) def on_window_layout(self, layout: gui.LayoutContext) -> None: """ This is called when layout is required for this widgets *immediate children*, like on resize. Only the immediate children are *manually* positioned here, by setting the x, y, width, and height of their frames. The grandchildren are *not* touched here; they're automatically handled after this. """ # This is the area in this widget available to place child widgets in. The *units* here aren't window screen # pixels, like from the width/height here when setting up the window: gui.Application.instance.create_window("Test", width=500, height=600). rect = self.window.content_rect r = self.window.content_rect print(r) print(layout.theme.default_layout_spacing) print(layout.theme.default_margin) print(layout.theme.font_size) # Put the layout (containing the controls) on the left 1/3 and the and scene on the right 2/3. x_division = rect.width // 3 # Set the layout (gui.Vert) on left to 1/3 available width, full height. # gui.Rect(x, y, width, height) # Set the SceneWidget on on right, 2/3 available width, full height self.scene.frame = gui.Rect(0, 0, r.width - x_division, r.height) self.layout.frame = gui.Rect(r.width - x_division, 0, x_division, r.height) def add_sphere(self): self._id += 1 mat = rendering.MaterialRecord() mat.base_color = [ random.random(), random.random(), random.random(), 1.0 ] mat.shader = "defaultLit" sphere = o3d.geometry.TriangleMesh.create_sphere(0.5) sphere pute_vertex_normals() sphere.translate([ 10.0 * random.uniform(-1.0, 1.0), 10.0 * random.uniform(-1.0, 1.0), 10.0 * random.uniform(-1.0, 1.0) ]) self.scene.scene.add_geometry("sphere" + str(self._id), sphere, mat) def _on_menu_sphere(self): # GUI callbacks happen on the main thread, so we can do everything # normally here. self.scene.scene.clear_geometry() self.add_sphere() def _on_menu_random(self): # This adds spheres asynchronously. This pattern is useful if you have # data coming in from another source than user interaction. def thread_main(): for _ in range(0, 20): # We can only modify GUI objects on the main thread, so we # need to post the function to call to the main thread. gui.Application.instance.post_to_main_thread( self.window, self.add_sphere) time.sleep(0.5) threading.Thread(target=thread_main).start() def _on_menu_quit(self): gui.Application.instance.quit() def main(): gui.Application.instance.initialize() SpheresApp() gui.Application.instance.run() if __name__ == "__main__": main()
标签:

Open3D解决SceneWidget加入布局中消失的问题由讯客互联开源代码栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“Open3D解决SceneWidget加入布局中消失的问题