I'm trying to use the mouse to select and deselect multiple items. I have it working sort of but there is a problem when the user moves the mouse to fast. When the mouse is moved fast some items are skipped and are not selected at all. I must be going about this the wrong way.
Update 1: I decided to use my own selecting system, but I get the same results as above. Some items are skipped when the mouse is moved to fast and therefore they don't get the correct color tag added and remain unchanged. If the mouse is moved slowly all items get selected correctly. Below is the new code and another Image of the problem.
Update 2: I have solved this issue and posted the working code just for completeness and to help others in the future. I ended up using my own selection selecting system instead of the built in one.
import tkinter as tk
import tkinter.ttk as ttk
class App(tk.Tk):
def __init__(self):
super().__init__()
self.title('Treeview Demo')
self.geometry('300x650')
self.rowconfigure(0, weight=1)
self.columnconfigure(0, weight=1)
tv = self.tv = ttk.Treeview(self)
tv.heading('#0', text='Name')
# Populate tree with test data.
for idx in range(0, 4):
tv.insert('', idx, f'!{idx}', text=f'Item {idx+1}', tags='TkTextFont', open=1)
iid = f'!{idx}_!{idx}'
tv.insert(f'!{idx}', '0', iid, text=f'Python {idx+1}', tags='TkTextFont', open=1)
for i in range(0, 5):
tv.insert(iid, f'{i}', f'{iid}_!{i}', text=f'Sub item {i+1}', tags='TkTextFont')
tv.grid(sticky='NSEW')
self.active_item = None
def motion(_):
x, y = tv.winfo_pointerxy()
item = tv.identify('item', x - tv.winfo_rootx(), y - tv.winfo_rooty())
if not item or item == self.active_item:
return
if not self.active_item:
self.active_item = item
tv.selection_toggle(item)
self.active_item = item
def escape(_):
tv.selection_remove(tv.selection())
def button_press(_):
self.bind('<Motion>', motion)
def button_release(_):
self.unbind('<Motion>')
self.active_item = None
self.bind('<Escape>', escape)
self.bind('<Button-1>', button_press)
self.bind('<ButtonRelease-1>', button_release)
def main():
app = App()
app.mainloop()
if __name__ == '__main__':
main()
Second Try:
import tkinter as tk
import tkinter.ttk as ttk
import tkinter.font as tkfont
class App(tk.Tk):
def __init__(self):
super().__init__()
self.title('Treeview Demo')
self.geometry('700x650')
self.rowconfigure(0, weight=1)
self.columnconfigure(0, weight=1)
tv = self.tv = ttk.Treeview(self)
tv.heading('#0', text='Name')
tv.tag_configure('odd', background='#aaaaaa')
tv.tag_configure('even', background='#ffffff')
tv.tag_configure('selected_odd', background='#25a625')
tv.tag_configure('selected_even', background='#b0eab2')
tag = 'odd'
# Populate tree with test data.
for idx in range(0, 4):
tag = 'even' if tag == 'odd' else 'odd'
tv.insert('', idx, f'!{idx}', text=f'Item {idx+1}', open=1, tags=(tag,))
tag = 'even' if tag == 'odd' else 'odd'
iid = f'!{idx}_!{idx}'
tv.insert(f'!{idx}', '0', iid, text=f'Python {idx+1}', open=1, tags=(tag,))
for i in range(0, 5):
tag = 'even' if tag == 'odd' else 'odd'
tv.insert(iid, i, f'{iid}_!{i}', text=f'Sub item {i+1}', tags=(tag,))
tv.config(selectmode="none")
tv.grid(sticky='NSEW')
dw = tk.Toplevel()
dw.overrideredirect(True)
dw.wait_visibility(self)
dw.wm_attributes('-alpha', 0.2)
dw.wm_attributes("-topmost", True)
dw.config(bg='#00aaff')
dw.withdraw()
self.selected = False
self.active_item = None
def motion(event):
x, y = self.winfo_pointerxy()
width = event.x-self.anchor_x
height = event.y-self.anchor_y
if width < 0:
coord_x = event.x+self.winfo_rootx()
width = self.anchor_x - event.x
else:
coord_x = self.anchor_x+self.winfo_rootx()
if coord_x+width > self.winfo_rootx()+self.winfo_width():
width -= (coord_x+width)-(self.winfo_rootx()+self.winfo_width())
elif x < self.winfo_rootx():
width -= (self.winfo_rootx() - x)
coord_x = self.winfo_rootx()
if height < 0:
coord_y = event.y+self.winfo_rooty()
height = self.anchor_y - event.y
else:
coord_y = self.anchor_y+self.winfo_rooty()
if coord_y+height > self.winfo_rooty()+self.winfo_height():
height -= (coord_y+height)-(self.winfo_rooty()+self.winfo_height())
elif y < self.winfo_rooty():
height -= (self.winfo_rooty() - y)
coord_y = self.winfo_rooty()
dw.geometry(f'{width}x{height}+{coord_x}+{coord_y}')
item = tv.identify('item', coord_x, coord_y-40)
if not item or item == self.active_item:
self.active_item = None
return
self.active_item = item
tags = list(tv.item(item, 'tags'))
if 'odd' in tags:
tags.pop(tags.index('odd'))
tags.append('selected_odd')
if 'even' in tags:
tags.pop(tags.index('even'))
tags.append('selected_even')
tv .item(item, tags=tags)
def escape(_=None):
for item in tv.tag_has('selected_odd'):
tags = list(tv.item(item, 'tags'))
tags.pop(tags.index('selected_odd'))
tags.append('odd')
tv.item(item, tags=tags)
for item in tv.tag_has('selected_even'):
tags = list(tv.item(item, 'tags'))
tags.pop(tags.index('selected_even'))
tags.append('even')
tv.item(item, tags=tags)
def button_press(event):
if self.selected and not event.state & 1 << 2:
escape()
self.selected = False
dw.deiconify()
self.anchor_item = tv.identify('item', event.x, event.y-40)
self.anchor_x, self.anchor_y = event.x, event.y
self.bind('<Motion>', motion)
self.selected = True
def button_release(event):
dw.withdraw()
dw.geometry('0x0+0+0')
self.unbind('<Motion>')
self.bind('<Escape>', escape)
self.bind('<Button-1>', button_press)
self.bind('<ButtonRelease-1>', button_release)
def main():
app = App()
app.mainloop()
if __name__ == '__main__':
main()
所有评论(0)