Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import tkinter as tk
- import tkinter.ttk as ttk
- import tkinter.font as tkfont
- class App(tk.Tk):
- def __init__(self):
- super().__init__()
- def escape(_):
- tags_remove_all('selected', '_selected')
- tags_reset()
- def fixed_map(option):
- return [elm for elm in style.map("Treeview", query_opt=option) if elm[:2] != ("!disabled", "!selected")]
- def button_press(event):
- self.selected = []
- self.anchor_x, self.anchor_y = event.x, event.y
- item = self.anchor_item = self.active_item = tv.identify('item', event.x, event.y)
- if event.state & 1 << 2:
- tags_add(item, ('selected', ))
- if tv.tag_has('odd', item):
- tag_replace(item, 'odd', 'selected_odd')
- elif tv.tag_has('selected_odd', item):
- tag_replace(item, 'selected_odd', 'odd')
- elif tv.tag_has('even', item):
- tag_replace(item, 'even', 'selected_even')
- elif tv.tag_has('selected_even', item):
- tag_replace(item, 'selected_even', 'even')
- else:
- tags_remove_all('selected', '_selected')
- tags_reset()
- tags_add(item, 'selected')
- if tv.tag_has('odd', item):
- tag_replace(item, 'odd', 'selected_odd')
- elif tv.tag_has('even', item):
- tag_replace(item, 'even', 'selected_even')
- dw.geometry('0x0+0+0')
- dw.deiconify()
- self.bind('<Motion>', selection_window)
- def button_release(_):
- dw.withdraw()
- self.unbind('<Motion>')
- tags_replace_all('_selected', 'selected')
- def get_selected(event):
- selected_items = []
- window_y = int(self.geometry().rsplit('+', 1)[-1])
- titlebar_height = tv.winfo_rooty() - window_y
- start = dw.winfo_rooty() - titlebar_height - window_y
- end = start + dw.winfo_height()
- while start < end:
- start += 1
- node = tv.identify('item', event.x, start)
- if not node or node in selected_items:
- continue
- selected_items.append(node)
- return sorted(selected_items)
- def set_row_colors(event):
- self.unbind('<Motion>')
- items = get_selected(event)
- for item in items:
- if tv.tag_has('selected', item):
- if item == self.anchor_item or item == self.active_item:
- continue
- if tv.tag_has('selected_odd', item):
- tag_replace(item, 'selected_odd', 'odd')
- tags_add(item, '_selected')
- elif tv.tag_has('selected_even', item):
- tag_replace(item, 'selected_even', 'even')
- tags_add(item, '_selected')
- # elif event.state & 1 << 2 and tv.tag_has('_selected', item):
- # tags_remove(item, ('selected', '_selected'))
- # print(item, tv.item(item, 'tags'))
- else:
- if tv.tag_has('odd', item):
- tag_replace(item, 'odd', 'selected_odd')
- tags_add(item, '_selected')
- self.active_item = item
- elif tv.tag_has('even', item):
- tag_replace(item, 'even', 'selected_even')
- tags_add(item, '_selected')
- self.active_item = item
- for item in tv.tag_has('_selected'):
- if item not in items:
- tags_remove(item, '_selected')
- if tv.tag_has('odd', item):
- tag_replace(item, 'odd', 'selected_odd')
- elif tv.tag_has('even', item):
- tag_replace(item, 'even', 'selected_even')
- elif tv.tag_has('selected_odd', item):
- tag_replace(item, 'selected_odd', 'odd')
- elif tv.tag_has('selected_even', item):
- tag_replace(item, 'selected_even', 'even')
- self.bind('<Motion>', selection_window)
- def selection_window(event):
- root_x = self.winfo_rootx()
- if event.x < self.anchor_x:
- width = self.anchor_x - event.x
- coord_x = root_x + event.x
- else:
- width = event.x - self.anchor_x
- coord_x = root_x + self.anchor_x
- if coord_x+width > root_x+self.winfo_width():
- width -= (coord_x+width)-(root_x+self.winfo_width())
- elif self.winfo_pointerx() < root_x:
- width -= (root_x - self.winfo_pointerx())
- coord_x = root_x
- root_y = self.winfo_rooty()
- if event.y < self.anchor_y:
- height = self.anchor_y - event.y
- coord_y = root_y + event.y
- else:
- height = event.y - self.anchor_y
- coord_y = root_y + self.anchor_y
- if coord_y+height > root_y+self.winfo_height():
- height -= (coord_y+height)-(root_y+self.winfo_height())
- elif self.winfo_pointery() < root_y + linespace:
- height -= (root_y - self.winfo_pointery() + linespace)
- coord_y = root_y + linespace
- if height < 0:
- height = tv.winfo_rooty() + self.anchor_y
- dw.geometry(f'{width}x{height}+{coord_x}+{coord_y}')
- set_row_colors(event)
- def tag_replace(item, old, new):
- tags_remove(item, old)
- tags_add(item, new)
- def tags_add(item, tags):
- if not item or not tags:
- return
- if isinstance(tags, str):
- tags = (tags,)
- _tags = list(tv.item(item, 'tags'))
- for _tag in tags:
- if _tag not in _tags:
- _tags.append(_tag)
- tv.item(item, tags=_tags)
- def tags_reset(_=None):
- tags_replace_all('selected_odd', 'odd')
- tags_replace_all('selected_even', 'even')
- def tags_remove(item, tags):
- if not item or not tags:
- return
- if isinstance(tags, str):
- tags = (tags,)
- _tags = list(tv.item(item, 'tags'))
- for _tag in tags:
- if _tag in _tags:
- _tags.pop(_tags.index(_tag))
- tv.item(item, tags=_tags)
- def tags_remove_all(*tags):
- def remove(node):
- tags_remove(node, tags)
- for node in tv.get_children(node):
- remove(node)
- for child in tv.get_children():
- remove(child)
- def tags_replace_all(old, new):
- for item in tv.tag_has(old):
- tag_replace(item, old, new)
- dw = tk.Toplevel(self)
- dw.wait_visibility(self)
- dw.withdraw()
- dw.config(bg='#00aaff')
- dw.overrideredirect(True)
- dw.wm_attributes('-alpha', 0.3)
- dw.wm_attributes("-topmost", True)
- style = ttk.Style()
- style.map("Treeview", foreground=fixed_map("foreground"), background=fixed_map("background"))
- 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'
- for idx in range(0, 4):
- # Populating the tree with test data.
- 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}_!{0}'
- tv.insert(f'!{idx}', '0', iid, text=f'Menu {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,))
- tag = 'even' if tag == 'odd' else 'odd'
- tv.insert(iid, 5, f'{iid}_!{5}', text=f'Another Menu {idx+1}', open=1, tags=(tag,))
- iid = f'{iid}_!{5}'
- for i in range(0, 3):
- tag = 'even' if tag == 'odd' else 'odd'
- tv.insert(iid, i, f'{iid}_!{i}', text=f'Sub item {i+1}', tags=(tag,))
- self.title('Treeview Demo')
- self.geometry('275x650+2000+100')
- self.rowconfigure(0, weight=1)
- self.columnconfigure(0, weight=1)
- self.update_idletasks()
- self.active_item = None
- tv.config(selectmode="none")
- tv.grid(sticky='NSEW')
- font = tkfont.nametofont('TkTextFont')
- linespace = font.metrics('linespace') + 5
- 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()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement