发布时间:2025-12-09 16:50:03 浏览次数:5
根据控件的使用难度和功能的复杂度,这里挑选出九种最简单,同时使用最为频繁的九种控件
| Label | 文本标签 | |
| TextEdit | 文本输入框 | |
| Button | 按钮 | |
| Checkbox | 单选框 | |
| Combobox | 下拉选框 | |
| Slider | 数字滚动条 | Slider.Type |
| VectorEdit | 向量编辑框 | |
| NumberEdit | 数字编辑框 | |
| ToggleSwitch | 开关 |
其中,大部分控件的输入参数为控件上显示出来的文本,这些控件都可以通过外挂函数的方式来添加交互动作。
Combobox为下拉选框,下拉选框的内容通过add_item来添加。
Slider为滚动条,创建之后,其初始值默认为0,取值范围是负无穷到正无穷,通过set_limits来添加最大值和最小值。
为了集中展示这些控件的功能,将其写入一个字典中,并为每个控件分配一个控件,向命令行输出一些反馈。
import open3d as o3dimport open3d.visualization.gui as guiimport open3d.visualization.rendering as renderingapp = gui.Application.instanceapp.initialize()# 准备演示的九种控件CTRLS = {"label" : gui.Label("label"),"text" : gui.TextEdit(),"button" : gui.Button("button"),"check" : gui.Checkbox("checkbox"),"combo" : gui.Combobox(),"slider" : gui.Slider(gui.Slider.Type(0)),"vector" : gui.VectorEdit(),"number" : gui.NumberEdit(gui.NumberEdit.Type(0)),"toggle" : gui.ToggleSwitch("ToggleSwitch")}# 为combobox添加内容for i in range(5):CTRLS["combo"].add_item(str(i))# 为 slider 添加取值范围CTRLS["slider"].set_limits(0,20)win = app.create_window("Open3d Test", 500, 100)vert = gui.Vert(0, gui.Margins(2,2,2,2))win.add_child(vert) # 将布局加载到窗口for key in CTRLS:vert.add_child(CTRLS[key])app.run()效果如下
这九种控件,除了Label之外,均可注册回调函数,在发生动作时执行
接下来为这些控件分别注册一些函数,其基础函数如下
| TextEdit | set_on_value_changed | 敲击回车 | 控件文本 |
| Button | set_on_clicked | 点击按钮 | 无 |
| Checkbox | 单选框 | 点击 | 单选框状态 |
| Combobox | 下拉选框 | 值发生变动 | 选中的item序号和值 |
| Slider | 数字滚动条 | 位置发生变动 | 当前值 |
| VectorEdit | 向量编辑框 | 敲击回车 | 控件向量 |
| NumberEdit | 数字编辑框 | 值发生变化 | 控件的值 |
| ToggleSwitch | 开关 | 点击 | 开关状态 |
其演示函数如下,可写在app.run()之前。
# TextEdit的测试函数,其输入为改动后的内容def text_test(txt):print(CTRLS["text"].text_value)CTRLS["text"].set_on_value_changed(print)# VectorEdit的测试函数,输入为改动后的向量def vector_test(vec):print(CTRLS["vector"].vector_value)CTRLS["vector"].set_on_value_changed(vector_test)# Slider的测试函数,输入为改动后的值def slider_test(val):print(CTRLS["slider"].int_value)passCTRLS["slider"].set_on_value_changed(slider_test)# val 和 ind 分别为combo选中的位置和选中的值def combo_test(val, ind):print(CTRLS["combo"].selected_index)print(CTRLS["combo"].selected_text)CTRLS["combo"].set_on_selection_changed(combo_test)# Checkbox的测试函数,chk为选中后的值def check_test(chk):print(CTRLS["check"].checked)CTRLS["check"].set_on_checked(check_test)def toggle_test(isOn):# 当打开toggle时,is_on为True,否则为Falseprint(CTRLS["toggle"].is_on) CTRLS["toggle"].set_on_clicked(toggle_test)TreeView是树形图中最为基础的,树的每个节点都只包含一个标签,其基本形式如下
代码如下
import open3d as o3dimport open3d.visualization.gui as guiimport open3d.visualization.rendering as renderingapp = gui.Application.instanceapp.initialize()win = app.create_window("tree view", 500, 200)tree = gui.TreeView()tree.add_text_item(tree.get_root_item(), "uncle")father = tree.add_text_item(tree.get_root_item(), "father")big = tree.add_text_item(father, "big son")tree.add_text_item(big, "grandson 1")tree.add_text_item(big, "grandson 2")tree.add_text_item(big, "grandson 3")little = tree.add_text_item(father, "little son")tree.can_select_items_with_children = Truedef _on_tree(self, item):print(item)tree.set_on_selection_changed(self._on_tree)tree.selected_item = littlewin.add_child(tree)app.run()其中,gui.TreeView用于生成一个树形图,add_text_item用以添加树形图的节点,其输入参数有二,分别是父节点和节点名称。
tree.add_text_item(tree.get_root_item(), "uncle")上面这条代码中,tree.get_root_item()用于获取根节点,整体而言的意思是,在根节点下面添加一个子节点,标签为uncle。
add_text_item函数返回的是新建子节点这个对象,由于uncle节点没有子节点,无需新建一个变量为其标识。而father有三个子节点,为了让他的两个儿子挂载到他这个节点上,需要新建一个变量名。
最后,为树形图添加了一个动作,即当选择的节点发生变化时,执行_on_tree这个函数。
树的成员can_select_items_with_children设为True,说明每个节点都可以被选中,如果设为False,那么当点击节点的标签时,会直接打开或者关闭这一层节点。当然这是官网说的,我其实并没有感觉出来二者有什么不同。
CheckableTextTreeCell
在treeview的节点中,除了朴实无华的标签之外,还可以添加勾选框,只需将add_text_item替换为add_item,就可以添加CheckableTextTreeCell作为节点
效果为
代码如下
app = gui.Application.instanceapp.initialize()win = app.create_window("tree view", 500, 200)check = lambda str : lambda isChecked : print(str, isChecked)tree = gui.TreeView()root = tree.get_root_item()tree.add_item(root, gui.CheckableTextTreeCell("uncle", False, check("uncle")))father = tree.add_item(root, gui.CheckableTextTreeCell("father", False, check("father")))tree.add_item(father, gui.CheckableTextTreeCell("big son", False, check("big son")))tree.add_item(father,gui.CheckableTextTreeCell("little son", False, check("little son")))tree.can_select_items_with_children = Truedef _on_tree(self, item):print(item)tree.set_on_selection_changed(self._on_tree)tree.selected_item = littlewin.add_child(tree)app.run()add_item的输入参数分别是父节点和子节点对应的对象,gui.CheckableTextTreeCell的输入参数有三个,分别是标签字符串,选框是否选中,以及一个回调函数。
考虑到学习open3d的同学一般都是老手,故而这里用了lambda表达式,相当于对每个节点都生成一个专门的回调函数,例如
check("uncle")相当于
# 由于是匿名函数,所以函数名姑且用_表示def _(isChecked):print("uncle", isChecked)ColormapTreeCell
只要学会了CheckableTextTreeCell,那么理解ColormapTreeCell也就毫无难度。
ColormapTreeCell的构造函数中包括四个输入参数,分别是
LUTTreeCell
LUTTreeCell就更加综合了,将选框和颜色都排到了树形图的节点中,故而其构造函数更加复杂,包括
考虑到add_item添加节点的数据类型为gui.Widget,故而绝对不限于这些专门用于树形图的数据类型,这里只是做一个简要的介绍,其实际应用可以更加炫酷。
ImageWidget
作为三维点云工具,Open3D连三维的形状都能画出来,那二维的图像就更不在话下了。ImageWidget是gui中显示图像的控件,和大多数控件不同的是,图像控件提供了多种构造函数
现以第二种为例,创建一个图像控件
import open3d as o3dimport open3d.visualization.gui as guiimport open3d.visualization.rendering as renderingapp = gui.Application.instanceapp.initialize()win = app.create_window("Image")imgFrame = gui.ImageWidget("test.jpg")win.add_child(imgFrame)app.run()效果如下
Image是open3d.geometry中的一种数据类型,其默认的初始化方式是通过矩阵,下面用随机数生成一个矩阵,并装载到图像中
import numpy as npimg_data = (np.random.rand(300, 600)*255).astype(np.uint8)img = o3d.geometry.Image(img_data)imgFrame = gui.ImageWidget(img)效果如下
ImageWidget中提供了update_image的方法,可以更新显示的图像内容,其输入参数同样为Image类型数据,
顾名思义,颜色编辑控件,效果如下
import open3d as o3dimport open3d.visualization.gui as guiimport open3d.visualization.rendering as renderingapp = gui.Application.instanceapp.initialize()win = app.create_window("color edit", 640, 360)clr = gui.ColorEdit()win.add_child(clr)app.run()在gui中,提供了Color类,用于表示颜色,ColorEdit控件绑定的函数输入值,就是这种数据类型。
Color类有四个成员,即RGBA,表示四个通道:红色、绿色、蓝色以及透明度。
def test(c):print(c.red)print(c.blue)print(c.green)print(c.alpha)clr.set_on_value_changed(test)效果为
由于Gif压制的问题,无法表示过于细腻的颜色,故而颜色选择框有些异常,但无碍于理解。