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 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:
- if tag_has('odd', item):
- tag_replace('odd', 'selected_odd', item)
- elif tag_has('even', item):
- tag_replace('even', 'selected_even', item)
- elif tag_has('selected_odd', item):
- tag_replace('selected_odd', 'odd', item)
- tag_add('selected', item)
- elif tag_has('selected_even', item):
- tag_replace('selected_even', 'even', item)
- tag_add('selected', item)
- else:
- tags_reset()
- if tag_has('odd', item):
- tag_replace('odd', 'selected_odd', item)
- elif tag_has('even', item):
- tag_replace('even', 'selected_even', item)
- dw.geometry('0x0+0+0')
- dw.deiconify()
- self.bind('<Motion>', selection_window)
- def button_release(_):
- dw.withdraw()
- self.unbind('<Motion>')
- for item in tag_has('_selected'):
- if not tag_has('selected', item):
- tag_replace('_selected', 'selected', item)
- for item in self.selected_items:
- if tag_has('selected') and tag_has('_selected') and item != self.anchor_item:
- tag_remove(('selected', '_selected'), item)
- 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):
- items = self.selected_items = get_selected(event)
- for item in items:
- if tag_has('selected', item):
- if item == self.anchor_item:
- continue
- if tag_has('selected_odd', item):
- tag_replace('selected_odd', 'odd', item)
- tag_add('_selected', item)
- elif tag_has('selected_even', item):
- tag_replace('selected_even', 'even', item)
- tag_add('_selected', item)
- elif tag_has('odd', item):
- tag_replace('odd', 'selected_odd', item)
- tag_add('_selected', item)
- elif tag_has('even', item):
- tag_replace('even', 'selected_even', item)
- tag_add('_selected', item)
- for item in tag_has('_selected'):
- if item not in items:
- tag_remove('_selected', item)
- if tag_has('odd', item):
- tag_replace('odd', 'selected_odd', item)
- elif tag_has('even', item):
- tag_replace('even', 'selected_even', item)
- elif tag_has('selected_odd', item):
- tag_replace('selected_odd', 'odd', item)
- elif tag_has('selected_even', item):
- tag_replace('selected_even', 'even', item)
- 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_has(tag, item=None):
- return tv.tag_has(tag, item)
- def tag_add(tags, item):
- tags_update('add', tags, item)
- def tag_remove(tags, item=None):
- tags_update('remove', tags, item)
- def tag_replace(old, new, item=None):
- for item in (item,) if item else tag_has(old):
- tags_update('add', new, item)
- tags_update('remove', old, item)
- def tags_reset(_=None):
- tag_remove(('selected', '_selected'))
- tag_replace('selected_odd', 'odd')
- tag_replace('selected_even', 'even')
- def tags_update(opt, tags, item):
- def get_items(node):
- items.append(node)
- for node in tv.get_children(node):
- get_items(node)
- if not tags:
- return
- elif isinstance(tags, str):
- tags = (tags,)
- if not item:
- items = []
- for child in tv.get_children():
- get_items(child)
- else:
- items = [item]
- for item in items:
- _tags = list(tv.item(item, 'tags'))
- for _tag in tags:
- if opt == 'add':
- if _tag not in _tags:
- _tags.append(_tag)
- elif opt == 'remove':
- if _tag in _tags:
- _tags.pop(_tags.index(_tag))
- tv.item(item, tags=_tags)
- 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')
- color_tag = 'odd'
- for idx in range(0, 4):
- # Populating the tree with test data.
- color_tag = 'even' if color_tag == 'odd' else 'odd'
- tv.insert('', idx, f'!{idx}', text=f'Item {idx+1}', open=1, tags=(color_tag,))
- color_tag = 'even' if color_tag == 'odd' else 'odd'
- iid = f'!{idx}_!{0}'
- tv.insert(f'!{idx}', '0', iid, text=f'Menu {idx+1}', open=1, tags=(color_tag,))
- for i in range(0, 5):
- color_tag = 'even' if color_tag == 'odd' else 'odd'
- tv.insert(iid, i, f'{iid}_!{i}', text=f'Sub item {i+1}', tags=(color_tag,))
- color_tag = 'even' if color_tag == 'odd' else 'odd'
- tv.insert(iid, 5, f'{iid}_!{5}', text=f'Another Menu {idx+1}', open=1, tags=(color_tag,))
- iid = f'{iid}_!{5}'
- for i in range(0, 3):
- color_tag = 'even' if color_tag == 'odd' else 'odd'
- tv.insert(iid, i, f'{iid}_!{i}', text=f'Sub item {i+1}', tags=(color_tag,))
- self.title('Treeview Demo')
- self.geometry('275x650+3000+250')
- 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>', tags_reset)
- 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