【问题标题】:Handling Double Click and Single Click Events in pygtk在 pygtk 中处理双击和单击事件
【发布时间】:2014-05-17 21:00:00
【问题描述】:

我正在尝试使用glib.timeout_add()glib.source_remove() 将单击事件与双击事件分开。这是我的做法:

class Exchange:

'''

some code

'''

    def __init__(self):

        self.timeoutID_1 = 0
        self.timeoutID_2 = 0

        self.startTime1 = 0.0
        self.stopTime1 = 0.0
        self.startTime2 = 0.0
        self.stopTime2 = 0.0

        '''

        some code

        '''

        ## THE DOUBLE CLICK SIGNAL - item-activated
        iconView1.connect("item-activated", self.on_item_activated_1,upButton1, store1)
        sw1.add(iconView1)

        iconView2.connect("item-activated", self.on_item_activated_2,upButton2, store2)
        sw2.add(iconView2)

        ## THE SINGLE CLICK SIGNAL - selection-changed

        iconView1.connect("selection-changed", self.on_selection_changed_1, copyButton1, cutButton1, pasteButton1, deleteButton1)
       iconView2.connect("selection-changed", self.on_selection_changed_2, copyButton2, cutButton2, pasteButton2, deleteButton2)

    def on_selection_changed_1(self, iconView1, copyButton1, cutButton1, pasteButton1, deleteButton1) :


        self.startTime1 = time.time()

        self.timeoutID_1 = glib.timeout_add(2000, self.selectIcon_1, iconView1, copyButton1, cutButton1, pasteButton1, deleteButton1)


    def on_selection_changed_2(self, iconView2, copyButton2, cutButton2, pasteButton2, deleteButton2) :

        self.startTime2 = time.time()

        self.timeoutID_2 = glib.timeout_add(2000, self.selectIcon_2, iconView2, copyButton2, cutButton2, pasteButton2, deleteButton2)


    def selectIcon_1(self, iconView1, copyButton1, cutButton1, pasteButton1, deleteButton1) :

        copyButton1.set_sensitive(True)
        cutButton1.set_sensitive(True)
        pasteButton1.set_sensitive(True)
        deleteButton1.set_sensitive(True)


    def selectIcon_2(self, iconView2, copyButton2, cutButton2, pasteButton2, deleteButton2) :


        copyButton2.set_sensitive(True)
        cutButton2.set_sensitive(True)
        pasteButton2.set_sensitive(True)
        deleteButton2.set_sensitive(True)

    def on_item_activated_1(self, iconView1, item, upButton1, store1) :

        self.stopTime1 = time.time()

        if self.stopTime1 - self.startTime1 < 1.50 :
            glib.source_remove(self.timeoutID_1)

        '''

        some code

        '''

    def on_item_activated_2(self, iconView2, item, upButton2, store2) :

        self.stopTime2 = time.time()

        if self.stopTime2 - self.startTime2 < 1.50 :
            glib.source_remove(self.timeoutID_2)

        '''

        some code

        '''

尽管 self.stopTime - self.startTime &lt;1.50True(表示有效的双击),但单击事件会执行一次,但每次单击仅执行一次,在 2 秒后。如何完全取消selectIcon 方法的执行以进行有效的双击?

更新

按照 mtwebster 的回答,我尝试使用 button_press_event。可悲的是,尽管我又回到了原点。

def on_button_press_event(self, widget, event) :
    if event.button == 1 :
        data = widget.get_path_at_pos(int(event.x), int(event.y))
        if data :
            if event.type == gtk.gdk._2BUTTON_PRESS :
                print " double click "

            elif event.type == gtk.gdk.BUTTON_PRESS :
                print " single click "

输出 ::

vineet@vineet:~/Documents/Project$ python draft6.py
 single click 
 single click 
 double click 

增加了我的困境三个点击事件正在执行一次双击,两次单击和一次双击!有没有其他我可以使用的计时机制来代替glib.timeout_add(),这样我就不必处理重复调用废话的不确定性了?

【问题讨论】:

  • 您为什么要自己处理所有"button-press/release-event" 信号?把逻辑弄对是很麻烦的。文档清楚地说明"item-activated" 是双击激活的(如果"activate-on-single-click" 属性设置为FALSE 和其他一些foo)并且"selection-changes" 通常是单击激活的(或箭头键乐趣)。你能详细说明你想要实现什么行为吗?
  • @drahnr 我确实使用了这些方法,但是对于 iconView selection-changed 中的每一次单击都会触发。我正在构建一个带有剪切/复制/粘贴/删除实用程序的文件浏览器。因此,每次单击文件/文件夹都会选择剪切/复制等,每次双击文件夹都将帮助我查看该文件夹的内容
  • 我仍然没有看到问题。究竟是什么阻止您使用带有回调的"item-activated" 打开/查看文件夹乐趣和使用"selection-changed" 相应地突出您的选择? button-press/release-events 根本不需要,您的事件是隐式分离的。我错过了什么吗?
  • @drahnr 我的想法太混乱了,因此错过了显而易见的事情。使用item-activatedselection-changed 并成功了。请添加一个答案,我会给你赏金代表。

标签: python gtk pygtk glib double-click


【解决方案1】:

我想这不是一个真正有效的答案...但是您是否考虑过仅连接到 IconView 的“按下按钮”信号?

在事件回调中,你可以让 Gdk 通过检查 event->type 来判断是双击事件还是单击事件(参见https://developer.gnome.org/gdk3/stable/gdk3-Event-Structures.html#GdkEventButton)。

【讨论】:

  • 那请尝试升级为真实答案。
  • @mtwebster can't find this signal in the reference manual...item-activated 为我提供了激活图标的路径,这对我正在处理的文件浏览器项目非常有帮助
  • 但我想我可以简单地使用您在当前事件回调中建议的 gdk 部分
  • on-button-press 是一个 GtkWidget 信号(并且由于 IconView 是一个小部件,您可以使用它。在此事件回调中,您可以调用 gtk_icon_view_get_path_at_pos (iconView, event-&gt;x, event-&gt;y) 它将返回一个 GtkTreePath 以找出哪些项目是实际点击了。python中的一个简单示例:github.com/mtwebster/git-monkey/blob/master/usr/lib/git-monkey/…
  • 一个更复杂的例子(C 语言):github.com/linuxmint/nemo/blob/master/src/nemo-list-view.c#L825。注意,这个回调是在TreeView上的,而不是和IconView上的,所以有些方法和参数不同,但原理是一样的。
【解决方案2】:

我不认为删除处理程序是一个好策略。

我曾经做过这种 hack —— 将不同的逻辑附加到单击(即单击以选择)和双击(即单击以执行)到 TreeView 中的一行。此外,您可能希望支持键盘导航和图像。

我设法让它在我当时工作的 pygtk 版本中工作。然而后来一些次要的 gtk 版本和我的代码坏了。事实证明,用相同的代码支持多个版本的 gtk 是不可能的。

最实用的方法是跟踪 2 个项目:

  • 是对已选择对象的点击(在我的例子中为行)
  • 选择此行的时间和时间
    • 默认选择行(显示/切换视图时的第一行)--忽略
    • 行被键盘选中 -- 忽略
    • 选择的行太早了(比如 300 毫秒)--忽略
    • else(点击选中,小于300ms)--执行

【讨论】:

    【解决方案3】:

    您可以将单击事件安排在双击持续时间之后发生,然后如果发生双击,请在处理程序运行之前删除预定的单击事件。例如:

    import pygtk
    pygtk.require('2.0')
    import gtk
    import glib
    class Test:
        def __init__(self):
            # Create a new window
            self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
            self.window.set_title("Test")
    
            # It's a good idea to do this for all windows.
            self.window.connect("destroy", lambda wid: gtk.main_quit())
            self.window.connect("delete_event", lambda a1,a2:gtk.main_quit())
    
            # Sets the border width of the window.
            self.window.set_border_width(20)
    
            # Create a new button
            button = gtk.Button("Click")
            self.click_events = []
    
            # Connect the "clicked" signal of the button to our callback
            button.connect("button-press-event", self.on_button_press_event)
            button.show()
    
            self.window.add(button)
            self.window.show()
    
        def on_button_press_event(self, widget, event):
            if event.button == 1:
                if event.type == gtk.gdk._2BUTTON_PRESS:
                    # Remove all single click events
                    while self.click_events:
                        glib.source_remove(self.click_events.pop()) 
                    glib.idle_add(self.handle_double_click,widget,event)
                elif event.type == gtk.gdk.BUTTON_PRESS:
                    # Schedule after double click can occur
                    self.click_events.append(glib.timeout_add(300,self.handle_single_click,widget,event))
    
    
        def handle_single_click(self,widget,event):
            # TODO: Handle single click
            print "TODO: Handle single click"
    
    
        def handle_double_click(self,widget,event):
            # TODO: Handle double click
            print "TODO: Handle double click"
    
    def main():
        Test()
        gtk.main()
        return 0     
    
    if __name__ == "__main__":
        main()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-26
      • 2011-02-18
      • 2019-07-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多