我在应用程序中使用 Gtk.IconView 小部件来选择不同类型的元素。 IconView 的工作方式如下:
- 单击即可选择项目
- 再次双击以激活该项目
我总是觉得需要额外双击很令人困惑,而桌面上大多数按钮式小部件只需单击一次即可。现在我刚刚收到一些用户的反馈,他们觉得这很令人困惑(有人认为单击按钮“没有任何反应”是一个错误),所以我决定研究如何改变这种行为。
理想情况下,我希望 IconView 的行为如下:
- 悬停以选择一个项目(可选)
- 单击即可激活该项目
现在我还没有在小部件的属性中找到任何明显的东西来使其表现出这种行为。有人知道如何实现或是否可以实现吗?
答案1
一种解决方案(但仅适用于单击激活)是使用 IconView 的 choice_changed 信号(因为 IconView 选择是基于单击的)。
假设 on_item_activated 信号正常工作的样本如下:
def on_icon_view_selection_changed(self, widget):
self.on_item_activated(widget, widget.get_selected_items()[0])
答案2
GtkIconView 不是将按钮小部件排列成表格。它基本上是 GtkTreeView 的一个特例,其中的项目以网格而不是列表/树的形式排列。要使悬停时的项目突出显示,我相信需要对 GTK+ 进行修补。还需要一个补丁来添加 API 以启用单击而不是双击来激活,但是,可以通过监听小部件button_press_event
上的信号并采取相应措施,在现有小部件 API 之上实现此功能。
答案3
您最近似乎正在探索 Gtk 的局限性 :-)
首先,多贝的回答似乎是正确的。
树形和列表存储是集合的不错选择。大量数据在类型上相同,但在元内容上不同(例如,音乐集合中每首歌曲都有艺术家、专辑、标题,但实际艺术家姓名、专辑名称、标题名称会发生变化)。
这些小部件的优点是它们易于排序,可以选择许多项目(例如在“橡皮筋”模式下),并且只需要相对较少的代码行即可添加数千个类似的项目。
改变 TreeView 或 ListView 的行为方式,使其能够点击/悬停等每个应用程序级别不是一个好主意,因为它会干扰用户预计应用程序的行为。根据您在问题中描述的反应,您自己也发现了这一点。
但是,您的问题在于,用户没有意识到您的小部件是 TreeView / ListView,而是认为它们是一些按钮。根据您的屏幕截图,这似乎很有道理。
按钮用于启动操作(例如停止、播放、暂停)或与程序通信(例如确定、取消),甚至充当指向不同视图的链接(参见 LinkButton)。它们通常没有与之关联的(抽象)对象或项目(例如专辑“Out of my head”中“Movits!”的“Sammy Davis Jr”)。
因此,虽然不可配置的点击行为是 gtk 的一个缺点,但它无论如何都应该只存在于每个用户的全局级别。
答案4
下面我展示了如何让我的 Iconview 响应指针位置以获得悬停效果以及单击左键和右键单击操作。
您必须为小部件激活指针运动通知,然后将指针的 x、y 位置转换为图标视图的路径:
...
self.iconview.add_events(Gdk.EventMask.POINTER_MOTION_MASK)
self.iconview.connect("item-activated", self.iv_icon_activated)
self.iconview.connect("button-press-event", self.on_mouse_click)
self.iconview.connect("motion-notify-event", self.on_pointer_motion)
def on_pointer_motion(self, widget, event):
path= self.iconview.get_path_at_pos(event.x, event.y)
if path !=None:
self.iconview.select_path(path)
#If we're outside of an item, deselect all items (turn off highlighting)
if path == None:
self.iconview.unselect_all()
def on_mouse_click(self,widget, event):
if event.type == Gdk.EventType.BUTTON_PRESS:
path=self.iconview.get_selected_items()[0]
#if right click activate a pop-up menu
if event.button == 3 and path != None:
self.popup.popup(None, None, None, None, event.button, event.time)
#if left click, activate the item to execute
if event.button == 1 and path != None:
self.iv_icon_activated(widget, path)