Nano Hash - криптовалюты, майнинг, программирование

Как сделать строки ttk.Treeview редактируемыми?

Есть ли способ использовать ttk Treeview с редактируемыми строками?

Я имею в виду, что он должен работать больше как стол. Например, при двойном щелчке по элементу столбец № 0 становится «редактируемым».

Если это невозможно, подойдет любой способ разрешить выбор элемента мышью. Я не нашел упоминания об этом в tkdocs или других документах.

01.09.2013

  • Я разработал способ щелкнуть ячейку в дереве и создать поле поверх выбранной ячейки, чтобы можно было редактировать значение ячейки. Однако один из методов просмотра дерева, который я использовал для этого, работает только на моем Mac, но не на Windows. Что странно, так это то, что технически он даже не должен работать на Mac, и все же он работает. Вы не указали свою платформу, но если вы работаете на Mac (и не будете запускать код в Windows), дайте мне знать, и я опубликую ответ с подробностями. 15.09.2013
  • Я сделал то же самое, и это работает как для Linux, так и для Windows, у меня нет возможности попробовать это на Mac. На самом деле мне не нужно делать текст редактируемым, я сделал виджет Entry доступным только для чтения. Так что, если ваше «решение только для Mac» имеет проблемы с отображением всплывающего окна ввода, возможно, мое решение может вас вдохновить. См. мой ответ на этот вопрос для примера кода. 15.09.2013
  • Я столкнулся с аналогичными ограничениями, в основном используя Treeview для имитации таблицы, поскольку в tkinter/ttk нет табличного виджета. Если вы не используете Treeview как дерево, вы можете попробовать tkintertable (code.google.com/p/ tkintertable). По сути, он позволяет работать с электронными таблицами и относительно актуален, хорошо документирован и довольно многофункционален. 05.10.2013

Ответы:


1

После долгих исследований я не нашел такой функции, так что я думаю, что она есть. Tk — это очень простой интерфейс, который позволяет программисту создавать функции «высокого уровня» из основ. Итак, мое желаемое поведение таким образом.

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)

Это метод внутри класса, который составляет ttk.Treeview как self._tree.

И EntryPopup является очень простым подклассом 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("<Return>", self.on_return)
        self.bind("<Control-a>", self.select_all)
        self.bind("<Escape>", 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'
15.09.2013
  • Это очень похоже на процесс, который я использую. В моем случае я использую identify_region, чтобы определить, где пользователь щелкнул в древовидной структуре, и отображаю поле ввода только в том случае, если пользователь щелкнул ячейку. Документы, которые я изначально использовал, ничего не говорили об этом методе, работающем только с Tk 8.6 и выше, поэтому я попробовал его. Чудесным образом это сработало... на моем Mac. Только когда он выдал исключение в системе Windows моего клиента, я обнаружил, что модули Python Tkinter и ttk в настоящее время используют Tk 8.5. Почему это работает для меня? Без понятия. Во всяком случае, вы дали мне несколько идей о том, как это исправить. Спасибо! 17.09.2013

  • 2

    Вы также можете открыть окно инструментов с редактируемыми полями, перечисленными с записями, чтобы обновить значения. Этот пример имеет древовидную структуру с тремя столбцами и не использует подклассы.

    Привяжите свой двойной щелчок к этому:

    def OnDoubleClick(self, treeView):
        # First check if a blank space was selected
        entryIndex = treeView.focus()
        if '' == entryIndex: return
    
        # Set up window
        win = Toplevel()
        win.title("Edit Entry")
        win.attributes("-toolwindow", True)
    
        ####
        # Set up the window's other attributes and geometry
        ####
    
        # Grab the entry's values
        for child in treeView.get_children():
            if child == entryIndex:
                values = treeView.item(child)["values"]
                break
    
        col1Lbl = Label(win, text = "Value 1: ")
        col1Ent = Entry(win)
        col1Ent.insert(0, values[0]) # Default is column 1's current value
        col1Lbl.grid(row = 0, column = 0)
        col1Ent.grid(row = 0, column = 1)
    
        col2Lbl = Label(win, text = "Value 2: ")
        col2Ent = Entry(win)
        col2Ent.insert(0, values[1]) # Default is column 2's current value
        col2Lbl.grid(row = 0, column = 2)
        col2Ent.grid(row = 0, column = 3)
    
        col3Lbl = Label(win, text = "Value 3: ")
        col3Ent = Entry(win)
        col3Ent.insert(0, values[2]) # Default is column 3's current value
        col3Lbl.grid(row = 0, column = 4)
        col3Ent.grid(row = 0, column = 5)
    
        def UpdateThenDestroy():
            if ConfirmEntry(treeView, col1Ent.get(), col2Ent.get(), col3Ent.get()):
                win.destroy()
    
        okButt = Button(win, text = "Ok")
        okButt.bind("<Button-1>", lambda e: UpdateThenDestroy())
        okButt.grid(row = 1, column = 4)
    
        canButt = Button(win, text = "Cancel")
        canButt.bind("<Button-1>", lambda c: win.destroy())
        canButt.grid(row = 1, column = 5)
    

    Затем подтвердите изменения:

    def ConfirmEntry(self, treeView, entry1, entry2, entry3):
        ####
        # Whatever validation you need
        ####
    
        # Grab the current index in the tree
        currInd = treeView.index(treeView.focus())
    
        # Remove it from the tree
        DeleteCurrentEntry(treeView)
    
        # Put it back in with the upated values
        treeView.insert('', currInd, values = (entry1, entry2, entry3))
    
        return True
    

    Вот как удалить запись:

    def DeleteCurrentEntry(self, treeView):
        curr = treeView.focus()
    
        if '' == curr: return
    
        treeView.delete(curr)
    
    01.02.2017

    3

    Это просто для создания дерева для указанного пути, заданного в конструкторе. вы можете привязать свое событие к своему элементу в этом дереве. Функция события оставлена ​​таким образом, чтобы предмет можно было использовать по-разному. В этом случае он покажет название элемента при двойном щелчке по нему. Надеюсь, это поможет кому-то.

        import ttk
        from Tkinter import*
        import os*
    
        class Tree(Frame):
    
        def __init__(self, parent):
            Frame.__init__(self, parent)
            self.parent = parent
            path = "/home/...."
            self.initUI(path)
    
        def initUI(self, path):
            self.parent.title("Tree")
            self.tree = ttk.Treeview(self.parent)
            self.tree.bind("<Double-1>", self.itemEvent)
            yScr = ttk.Scrollbar(self.tree, orient = "vertical", command = self.tree.yview)
            xScr = ttk.Scrollbar(self.tree, orient = "horizontal", command = self.tree.xview)
            self.tree.configure(yscroll = yScr.set, xScroll = xScr.set)
            self.tree.heading("#0", text = "My Tree", anchor = 'w')
            yScr.pack(side = RIGHT, fill = Y)
    
            pathy = os.path.abspath(path) 
            rootNode = self.tree.insert('', 'end', text = pathy, open = True)
            self.createTree(rootNode, pathy)
    
            self.tree.pack(side = LEFT, fill = BOTH, expand = 1, padx = 2, pady = 2)
    
            self.pack(fill= BOTH, expand = 1) 
    
        def createTree(self, parent, path)
            for p in os.listdir(path)
                pathy = os.path.join(path, p)
                isdir = os.path.isdir(pathy)
                oid = self.tree.insert(parent, 'end' text = p, open = False)
                if isdir:
                   self.createTree(oid, pathy)
    
        def itemEvent(self, event):
            item = self.tree.selection()[0] # now you got the item on that tree
            print "you clicked on", self.tree.item(item,"text")
    
    
    
        def main():
            root = Tk.Tk()
            app = Tree(root)
            root.mainloop()
    
        if __name__ == '__main__'
           main()
    
    23.07.2014

    4
    from tkinter import ttk
    from tkinter import *
    
    root = Tk()
    columns = ("Items", "Values")
    Treeview = ttk.Treeview(root, height=18, show="headings", columns=columns)  # 
    
    Treeview.column("Items", width=200, anchor='center')
    Treeview.column("Values", width=200, anchor='center')
    
    Treeview.heading("Items", text="Items")
    Treeview.heading("Values", text="Values")
    
    Treeview.pack(side=LEFT, fill=BOTH)
    
    name = ['Item1', 'Item2', 'Item3']
    ipcode = ['10', '25', '163']
    for i in range(min(len(name), len(ipcode))):
        Treeview.insert('', i, values=(name[i], ipcode[i]))
    
    
    def treeview_sort_column(tv, col, reverse):
        l = [(tv.set(k, col), k) for k in tv.get_children('')]
        l.sort(reverse=reverse)
        for index, (val, k) in enumerate(l):
            tv.move(k, '', index)
            tv.heading(col, command=lambda: treeview_sort_column(tv, col, not reverse))
    
    
    def set_cell_value(event):
        for item in Treeview.selection():
            item_text = Treeview.item(item, "values")
            column = Treeview.identify_column(event.x)
            row = Treeview.identify_row(event.y)
        cn = int(str(column).replace('#', ''))
        rn = int(str(row).replace('I', ''))
        entryedit = Text(root, width=10 + (cn - 1) * 16, height=1)
        entryedit.place(x=16 + (cn - 1) * 130, y=6 + rn * 20)
    
        def saveedit():
            Treeview.set(item, column=column, value=entryedit.get(0.0, "end"))
            entryedit.destroy()
            okb.destroy()
    
        okb = ttk.Button(root, text='OK', width=4, command=saveedit)
        okb.place(x=90 + (cn - 1) * 242, y=2 + rn * 20)
    
    
    def newrow():
        name.append('to be named')
        ipcode.append('value')
        Treeview.insert('', len(name) - 1, values=(name[len(name) - 1], ipcode[len(name) - 1]))
        Treeview.update()
        newb.place(x=120, y=(len(name) - 1) * 20 + 45)
        newb.update()
    
    
    Treeview.bind('<Double-1>', set_cell_value)
    newb = ttk.Button(root, text='new item', width=20, command=newrow)
    newb.place(x=120, y=(len(name) - 1) * 20 + 45)
    
    for col in columns:
        Treeview.heading(col, text=col, command=lambda _col=col: treeview_sort_column(Treeview, _col, False))
    
    
    root.mainloop()
    

    После стольких исследований во время выполнения моего проекта я получил этот код, он мне очень помог. Дважды щелкните элемент, который вы хотите отредактировать, внесите необходимые изменения и нажмите кнопку «ОК». Я думаю, это именно то, что вы хотели.

    #python #tkinter #treeview #editablerow

    Новая строка Редактируемая строка

    08.12.2020

    5

    Я не знаю, как сделать строку редактируемой, но чтобы зафиксировать щелчок по строке, вы используете виртуальное событие <<TreeviewSelect>>. Это привязывается к подпрограмме с помощью метода bind(), затем вы используете метод selection() для получения идентификаторов выбранных элементов.

    Это фрагменты из существующей программы, но они показывают основную последовательность вызовов:

    # in Treeview setup routine
        self.tview.tree.bind("<<TreeviewSelect>>", self.TableItemClick)
    
    # in TableItemClick()
        selitems = self.tview.tree.selection()
        if selitems:
            selitem = selitems[0]
            text = self.tview.tree.item(selitem, "text") # get value in col #0
    
    04.09.2013
    Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..