滚动tkinter树视图时如何移动弹出窗口? [英] How to move popup window when scrolling a tkinter treeview?

查看:81
本文介绍了滚动tkinter树视图时如何移动弹出窗口?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带有垂直滚动条的 tkinter 树视图.为了使其(看起来)可编辑,当用户双击树视图的单元格时,我创建了一个弹出条目.但是,我无法在滚动树视图时使弹出窗口移动.

I have a tkinter treeview with a vertical scrollbar. To make it (look like) editable, I create a popup Entry when the user double-clicks on a cell of the treeview. However, I can't make the popup to move when the treeview is scrolled.

import tkinter  as tk
from tkinter import ttk

class EntryPopup(ttk.Entry):
    def __init__(self, parent, itemId, col, **kw):
        super().__init__(parent, **kw)
        self.tv = parent
        self.iId = itemId
        self.column = col
        self['exportselection'] = False

        self.focus_force()
        self.bind("<Return>", self.onReturn)

    def saveEdit(self):
        self.tv.set(self.iId, column=self.column, value=self.get())
        print("EntryPopup::saveEdit---{}".format(self.iId))

    def onReturn(self, event):
        self.tv.focus_set()        
        self.saveEdit()
        self.destroy()


class EditableDataTable(tk.Frame):
    def __init__(self, parent):
        tk.Frame.__init__(self, parent)

        self.parent = parent
        self.tree = None
        self.entryPopup = None
        columns = ("Col1", "Col2")
        # Create a treeview with vertical scrollbar.
        self.tree = ttk.Treeview(self, columns=columns, show="headings")
        self.tree.grid(column=0, row=0, sticky='news')
        self.tree.heading("#1", text="col1")
        self.tree.heading("#2", text="col2")

        self.vsb = ttk.Scrollbar(self, orient="vertical", command=self.tree.yview)
        self.tree.configure(yscrollcommand=self.vsb.set)
        self.vsb.grid(column=1, row=0, sticky='ns')

        self.grid_columnconfigure(0, weight=1)
        self.grid_rowconfigure(0, weight=1)

        self.entryPopup = None
        self.curSelectedRowId = ""

        col1 = []
        col2 = []
        for r in range(50):
            col1.append("data 1-{}".format(r))
            col2.append("data 2-{}".format(r))

        for i in range(min(len(col1),len(col2))):
            self.tree.insert('', i, values=(col1[i], col2[i]))

        self.tree.bind('<Double-1>', self.onDoubleClick)

    def createPopup(self, row, column):
        x,y,width,height = self.tree.bbox(row, column)

        # y-axis offset
        pady = height // 2
        self.entryPopup = EntryPopup(self.tree, row, column)
        self.entryPopup.place(x=x, y=y+pady, anchor='w', width=width)


    def onDoubleClick(self, event):
        rowid = self.tree.identify_row(event.y)
        column = self.tree.identify_column(event.x)
        self.createPopup(rowid, column)

root = tk.Tk()

for row in range(2):
    root.grid_rowconfigure(row, weight=1)
root.grid_columnconfigure(0, weight=1)

label = tk.Label(root, text="Double-click to edit and press 'Enter'")
label.grid(row=0, column=0, sticky='news', padx=10, pady=5)

dataTable = EditableDataTable(root)
dataTable.grid(row=1, column=0, sticky="news", pady=10, padx=10)

root.geometry("450x300")
root.mainloop()

要重现该问题,请双击树视图.当编辑框打开时,将鼠标指针移动到树状视图上.现在使用鼠标滚轮滚动.树状视图移动但弹出编辑框没有移动.

To reproduce the problem, double-click on the treeview. While the edit box is open, move your mouse pointer to hover over the treeview. Now scroll using the mouse wheel. The treeview moves but the popup edit box does not.

推荐答案

我之前做过类似的事情,通过将一个函数绑定到 mousewheel 并重新计算所有新的 x &y 悬停小部件的位置.

I have done something similar before by binding a function to mousewheel and recalculate all the new x & y location of your hovering widgets.

class EditableDataTable(tk.Frame):
    def __init__(self, parent):
        tk.Frame.__init__(self, parent)

        self.parent = parent
        self.tree = None
        self.entryPopup = None
        self.list_of_entries = []

        ...

        self.tree.bind("<MouseWheel>", self._on_mousewheel)

    def _on_mousewheel(self, event):
        if self.list_of_entries:
            def _move():
                for i in self.list_of_entries:
                    try:
                        iid = i.iId
                        x, y, width, height = self.tree.bbox(iid, column="Col2") #hardcoded to col2
                        i.place(x=x, y=y+height//2, anchor='w', width=width)
                    except ValueError:
                        i.place_forget()
                    except tk.TclError:
                        pass
            self.master.after(5, _move)

    def createPopup(self, row, column):
        x,y,width,height = self.tree.bbox(row, column)
        # y-axis offset
        pady = height // 2
        self.entryPopup = EntryPopup(self.tree, row, column)
        self.list_of_entries.append(self.entryPopup)
        self.entryPopup.place(x=x, y=y+pady, anchor='w', width=width)

请注意,这仅适用于第二列,但对于其余列应该很容易实现.

Note that this only works on the second column, but should be easy enough to implement for the rest.

这篇关于滚动tkinter树视图时如何移动弹出窗口?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆