關於PyGTK.CellRenderer的回調方法中聚焦異常的問題

| Comments

遇到這樣一個問題:

在pygtk.TreeView中,需要在一個Cell的值被修改後做一個校驗,如果不合法,則重新聚焦該Cell並選中其中的內容。

示意代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# pygtk.CellRenderer的edited事件的回調方法
def onCellEdited(self, cell, path, newText, userData):
    store,colNum = userData
    # 使用事件驅動的設計理念,創建一個自定義的事件
    evt = ServerTypeChangedEvent(self, cell, usrData)

    # 事件入隊列
    EventQueue.fireEvent(evt)
    # 處理事件隊列,如果截獲異常,提示並重新聚焦Cell
    try:
        EventQueue.processEvents()
    except Exception,e:
        self.alert(e.message)
        col = self.treeView.get_column(colNum-1)
        # 聚焦Cell,並選中Cell中的內容
        self.treeView.set_cursor_on_cell(path, col, cell, True)

關鍵的代碼在最後一行,通過調用TreeView的set_cursor_on_cell方法聚焦Cell並選中其內容。但就是這一步出了問題,報如下警告:

GtkWarning: _gtk_tree_view_column_start_editing: assertion `tree_column->editable_widget == NULL’ failed

此後整個TreeView的行為表現不正常,表現為可直接修改其它Cell的內容,且原Cell一直處於聚焦狀態。

此問題的原因是:edited事件在Cell的輸入控件被銷毀前就發出了,這時在事件的回調方法中重新聚焦該Cell就導致了這個問題(詳見這裡)。

解決方法是借助glib.idle_add函數,在PyGTK空閒的時候再調用set_cursor_on_cell方法,由於此時原控件已被銷毀,所以不會有問題。

修改後的代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
def onCellEdited(self, cell, path, newText, userData):
    store,colNum = userData
    evt = ServerTypeChangedEvent(self, cell, usrData)

    EventQueue.fireEvent(evt)
    try:
        EventQueue.processEvents()
    except Exception,e:
        self.alert(e.message)
        col = self.treeView.get_column(colNum-1)
        #self.treeView.set_cursor_on_cell(path, col, cell, True)
        import glib
        glib.idle_add(self.treeView.set_cursor_on_cell, path, col, cell, True)

Posted via UltraBlog.vim.

Comments