How to make ttk.Treeview's rows editable?

后端 未结 4 830
攒了一身酷
攒了一身酷 2020-12-06 06:44

Is there any way to use ttk Treeview with editable rows?

I mean it should work more like a table. For example on double click on the it

4条回答
  •  小蘑菇
    小蘑菇 (楼主)
    2020-12-06 06:55

    After long research I haven't found such feature so I guess there's any. Tk is very simple interface, which allows programmer to build 'high-level' features from the basics. So my desired behaviour this way.

    def onDoubleClick(self, event):
        ''' Executed, when a row is double-clicked. Opens 
        read-only EntryPopup above the item's column, so it is possible
        to select text '''
    
        # close previous popups
        # self.destroyPopups()
    
        # what row and column was clicked on
        rowid = self._tree.identify_row(event.y)
        column = self._tree.identify_column(event.x)
    
        # get column position info
        x,y,width,height = self._tree.bbox(rowid, column)
    
        # y-axis offset
        # pady = height // 2
        pady = 0
    
        # place Entry popup properly         
        text = self._tree.item(rowid, 'text')
        self.entryPopup = EntryPopup(self._tree, rowid, text)
        self.entryPopup.place( x=0, y=y+pady, anchor=W, relwidth=1)
    

    This is method within a class which composes ttk.Treeview as self._tree

    And EntryPopup is then very simple sub-class of Entry:

    class EntryPopup(Entry):
    
        def __init__(self, parent, iid, text, **kw):
            ''' If relwidth is set, then width is ignored '''
            super().__init__(parent, **kw)
            self.tv = parent
            self.iid = iid
    
            self.insert(0, text) 
            # self['state'] = 'readonly'
            # self['readonlybackground'] = 'white'
            # self['selectbackground'] = '#1BA1E2'
            self['exportselection'] = False
    
            self.focus_force()
            self.bind("", self.on_return)
            self.bind("", self.select_all)
            self.bind("", lambda *ignore: self.destroy())
    
        def on_return(self, event):
            self.tv.item(self.iid, text=self.get())
            self.destroy()
    
        def select_all(self, *ignore):
            ''' Set selection on the whole text '''
            self.selection_range(0, 'end')
    
            # returns 'break' to interrupt default key-bindings
            return 'break'
    

提交回复
热议问题