Jak*_*ria 5 python treeview scroll tkinter popupwindow
我有一个带有垂直滚动条的 tkinter 树视图。为了使其(看起来)可编辑,当用户双击树视图的单元格时,我创建一个弹出条目。但是,当树视图滚动时,我无法使弹出窗口移动。
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()
Run Code Online (Sandbox Code Playgroud)
要重现该问题,请双击树视图。当编辑框打开时,将鼠标指针悬停在树视图上。现在使用鼠标滚轮滚动。树视图移动,但弹出编辑框不移动。
您需要进行数学计算并在树滚动时移动条目小部件。我已经编辑了您的代码,并且仅对滚动条按钮进行了编程。如果单击该按钮,条目小部件将随树滚动。我没有对鼠标滚轮或拖动滚动条进行编程。你应该能够弄清楚剩下的事情。
import tkinter as tk
import tkinter.font as tkfont
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)
self.vsb.bind('<ButtonPress-1>', self.func)
def func(self, event):
print(self.vsb.identify(event.x, event.y))
if hasattr(self.entryPopup, 'y'):
item = self.vsb.identify(event.x, event.y)
if item == 'uparrow':
self.entryPopup.y += 20
elif item == 'downarrow':
self.entryPopup.y -= 20
self.entryPopup.place(x=self.entryPopup.x, y=self.entryPopup.y, )
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.x = x
self.entryPopup.y = y+pady
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()
Run Code Online (Sandbox Code Playgroud)