def create_separator_frame(widget_style, style, orient): frame = ttk.Frame(root, padding=5) # title title = ttk.Label(master=frame, text=orient.title() + ' Separator', anchor=tk.CENTER) title.pack(padx=5, pady=2, fill=tk.BOTH) ttk.Separator(frame).pack(padx=5, pady=5, fill=tk.X) # default sep = ttk.Separator(frame, orient=orient) if orient == tk.HORIZONTAL: sep.pack(padx=5, pady=5, fill=tk.BOTH) else: sep.pack(padx=5, pady=5, fill=tk.BOTH, side=tk.LEFT) # colored for i, color in enumerate(style.colors): ttk.Label(frame, text=color).pack(fill=tk.X) sep = ttk.Separator(master=frame, bootstyle=color, orient=orient) if orient == tk.HORIZONTAL: sep.pack(padx=5, pady=5, fill=tk.BOTH) else: sep.pack(padx=5, pady=5, fill=tk.BOTH, side=tk.LEFT) return frame
def create_checkbutton_test(bootstyle, style, name): frame = ttk.Frame(padding=10) # title title = ttk.Label(frame, text=name, anchor=tk.CENTER) title.pack(padx=5, pady=2, fill=tk.BOTH) ttk.Separator(frame).pack(padx=5, pady=5, fill=tk.X) # default style cb = ttk.Checkbutton(frame, text='default', bootstyle=bootstyle) cb.pack(padx=5, pady=5, fill=tk.BOTH) cb.invoke() # color styles for color in style.theme.colors: cb = ttk.Checkbutton( master=frame, text=color, bootstyle=color + bootstyle, width=15 ) cb.pack(padx=5, pady=5, fill=tk.BOTH) cb.invoke() # disabled style cb = ttk.Checkbutton( master=frame, text='disabled', bootstyle=bootstyle, state=tk.DISABLED ) cb.pack(padx=5, pady=5, fill=tk.BOTH) cb.invoke() return frame
def create_spinbox_test(bootstyle, style): frame = ttk.Frame(padding=10) # title title = ttk.Label(frame, text='Spinbox', anchor=tk.CENTER) title.pack(padx=5, pady=2, fill=tk.BOTH) ttk.Separator(frame).pack(padx=5, pady=5, fill=tk.X) # default spinbox = ttk.Spinbox(frame) spinbox.pack(padx=5, pady=5, fill=tk.BOTH) spinbox.insert(tk.END, 'default') # color for color in style.theme.colors: spinbox = ttk.Spinbox(frame, bootstyle=color) spinbox.pack(padx=5, pady=5, fill=tk.BOTH) spinbox.insert(tk.END, color) # disabled spinbox = ttk.Spinbox(frame) spinbox.insert(tk.END, 'disabled') spinbox.configure(state=tk.DISABLED) spinbox.pack(padx=5, pady=5, fill=tk.BOTH) # readonly spinbox = ttk.Spinbox(frame) spinbox.insert(tk.END, 'readonly') spinbox.configure(state='readonly') spinbox.pack(padx=5, pady=5, fill=tk.BOTH) return frame
def create_entry_test(style): frame = ttk.Frame(padding=10) # title title = ttk.Label(frame, text='DateEntry', anchor=tk.CENTER) title.pack(padx=5, pady=2, fill=tk.BOTH) ttk.Separator(frame).pack(padx=5, pady=5, fill=tk.X) # default ttk.Label(frame, text='default').pack() entry = ttk.DateEntry(frame) entry.pack(padx=5, pady=5, fill=tk.BOTH) # color for color in style.theme.colors: ttk.Label(frame, text=color).pack() entry = ttk.DateEntry(frame, bootstyle=color) entry.pack(padx=5, pady=5, fill=tk.BOTH) ttk.Label(frame, text='disabled').pack() entry = ttk.DateEntry(frame) entry.configure(state=tk.DISABLED) entry.pack(padx=5, pady=5, fill=tk.BOTH) ttk.Label(frame, text='readonly').pack() entry = ttk.DateEntry(frame) entry.configure(state='readonly') entry.pack(padx=5, pady=5, fill=tk.BOTH) return frame
def create_entry_test(bootstyle, style): frame = ttk.Frame(padding=10) # title title = ttk.Label(frame, text='Entry', anchor=tk.CENTER) title.pack(padx=5, pady=2, fill=tk.BOTH) ttk.Separator(frame).pack(padx=5, pady=5, fill=tk.X) # default entry = ttk.Entry(frame, bootstyle=bootstyle) entry.pack(padx=5, pady=5, fill=tk.BOTH) entry.insert(tk.END, 'default') # color for color in style.theme.colors: entry = ttk.Entry(frame, bootstyle=color) entry.pack(padx=5, pady=5, fill=tk.BOTH) entry.insert(tk.END, color) # readonly entry = ttk.Entry(frame, bootstyle=bootstyle) entry.insert(tk.END, 'readonly') entry.configure(state=READONLY) entry.pack(padx=5, pady=5, fill=tk.BOTH) # disabled entry = ttk.Entry(frame, bootstyle=bootstyle) entry.insert(tk.END, 'disabled') entry.configure(state=DISABLED) entry.pack(padx=5, pady=5, fill=tk.BOTH) return frame
def create_scale_frame(widget_style, style, orient): frame = ttk.Frame(root, padding=5) # title title = ttk.Label(frame, text=orient.title() + ' Scale', anchor=tk.CENTER) title.pack(padx=5, pady=2, fill=tk.BOTH) ttk.Separator(frame).pack(padx=5, pady=5, fill=tk.X) # default pb = ttk.Scale(master=frame, orient=orient, value=0.2) if orient == tk.HORIZONTAL: pb.pack(padx=5, pady=5, fill=tk.BOTH) else: pb.pack(padx=5, pady=5, fill=tk.BOTH, side=tk.LEFT) # colored for color in style.colors: ttk.Label(frame, text=color).pack(fill=tk.X) pb = ttk.Scale(master=frame, value=0.2, bootstyle=color, orient=orient) if orient == tk.HORIZONTAL: pb.pack(padx=5, pady=5, fill=tk.BOTH) else: pb.pack(padx=5, pady=5, fill=tk.BOTH, side=tk.LEFT) return frame
def button_style_frame(bootstyle, style, widget_name): frame = ttk.Frame(root, padding=5) title = ttk.Label( master=frame, text=widget_name, anchor=tk.CENTER ) title.pack(padx=5, pady=2, fill=tk.BOTH) ttk.Separator(frame).pack(padx=5, pady=5, fill=tk.X) ttk.Button( master=frame, text='default', bootstyle=bootstyle ).pack(padx=5, pady=5) for color in style.colors: ttk.Button( master=frame, text=color, bootstyle=f'{color}-{bootstyle}' ).pack(padx=5, pady=5) ttk.Button( master=frame, text='disabled', state=tk.DISABLED, bootstyle=bootstyle ).pack(padx=5, pady=5) return frame
def create_labelframe_style(bootstyle, style): frame = ttk.Frame(root, padding=5) # title title = ttk.Label(frame, text='Labelframe', anchor=tk.CENTER) title.pack(padx=5, pady=2, fill=tk.BOTH) ttk.Separator(frame).pack(padx=5, pady=5, fill=tk.X) # default lbl = ttk.Labelframe(master=frame, text='default', bootstyle=bootstyle, width=150, height=75) lbl.pack(padx=5, pady=5, fill=tk.BOTH) # colored for color in style.colors: lbl = ttk.Labelframe(master=frame, text=color, bootstyle=color, width=150, height=75) lbl.pack(padx=5, pady=5, fill=tk.BOTH) return frame
def create_label_style(bootstyle, style, test_name): frame = ttk.Frame(root, padding=5) # title title = ttk.Label(frame, text=test_name, anchor=tk.CENTER) title.pack(padx=5, pady=2, fill=tk.BOTH) ttk.Separator(frame).pack(padx=5, pady=5, fill=tk.X) # default lbl = ttk.Label(frame, text='default', bootstyle=bootstyle) lbl.pack(padx=5, pady=5, fill=tk.BOTH) # colored for color in style.colors: lbl = ttk.Label(frame, text=color, bootstyle=(color, bootstyle)) lbl.pack(padx=5, pady=5, fill=tk.BOTH) return frame
def create_combobox_test(bootstyle, style, test_name): frame = ttk.Frame(padding=10) # title title = ttk.Label( master=frame, text=test_name, anchor=tk.CENTER ) title.pack(padx=5, pady=2, fill=tk.BOTH) ttk.Separator(frame).pack(padx=5, pady=5, fill=tk.X) # default cbo = ttk.Combobox( master=frame, values=['default', 'other'], bootstyle=bootstyle ) cbo.pack(padx=5, pady=5, fill=tk.BOTH) cbo.current(0) # color for color in style.theme.colors: cbo = ttk.Combobox( master=frame, values=[color, 'other'], bootstyle=(color, bootstyle) ) cbo.pack(padx=5, pady=5, fill=tk.BOTH) cbo.current(0) # disabled cbo = ttk.Combobox( master=frame, values=[bootstyle,'other'], bootstyle=bootstyle, state=tk.DISABLED ) cbo.pack(padx=5, pady=5, fill=tk.BOTH) cbo.current(0) return frame
def create_notebook_frame(widget_style, style): frame = ttk.Frame(root, padding=5) # title title = ttk.Label(frame, text=widget_style, anchor=tk.CENTER) title.pack(padx=5, pady=2, fill=tk.BOTH) ttk.Separator(frame).pack(padx=5, pady=5, fill=tk.X) # default nb = ttk.Notebook(frame, height=50, width=100) nb.pack(padx=5, pady=5, fill=tk.BOTH) for i, _ in enumerate(style.colors): nb.add(ttk.Frame(nb), text=f'Tab {i+1}') # other colors for color in style.colors: nb = ttk.Notebook(frame, bootstyle=color, height=50, width=100) nb.pack(padx=5, pady=5, fill=tk.BOTH) for i, _ in enumerate(style.colors): nb.add(ttk.Frame(nb), text=f'Tab {i+1}') return frame
def create_panedwindow_frame(widget_style, style): frame = ttk.Frame(root, padding=5) # title title = ttk.Label(frame, text=widget_style, anchor=tk.CENTER) title.pack(padx=5, pady=2, fill=tk.BOTH) ttk.Separator(frame).pack(padx=5, pady=5, fill=tk.X) # default pw = ttk.Panedwindow(frame) pw.pack(padx=5, pady=5, fill=tk.BOTH) pw.add(ttk.Frame(pw, width=100, height=50, bootstyle='info')) pw.add(ttk.Frame(pw, width=100, height=50, bootstyle='success')) for color in style.colors: # default pw = ttk.Panedwindow(frame, bootstyle=color) pw.pack(padx=5, pady=5, fill=tk.BOTH) pw.add(ttk.Frame(pw, width=100, height=50)) pw.add(ttk.Frame(pw, width=100, height=50)) return frame
def create_progressbar_frame(bootstyle, style, orient, testname): frame = ttk.Frame(root, padding=5) # title title = ttk.Label(frame, text=testname, anchor=tk.CENTER) title.pack(padx=5, pady=2, fill=tk.BOTH) ttk.Separator(frame).pack(padx=5, pady=5, fill=tk.X) # colored for i, color in enumerate(style.colors): ttk.Label(frame, text=color).pack(fill=tk.X) pb = ttk.Progressbar(master=frame, value=25 + ((i - 1) * 10), bootstyle=(color, bootstyle), orient=orient) if orient == 'h': pb.pack(padx=5, pady=5, fill=tk.X) else: pb.pack(padx=5, pady=5, fill=tk.Y) pb.start() return frame
def create_frame_test(bootstyle, style): frame = ttk.Frame(padding=10) # title title = ttk.Label(frame, text='Frame', anchor=tk.CENTER) title.pack(padx=5, pady=2, fill=tk.BOTH) ttk.Separator(frame).pack(padx=5, pady=5, fill=tk.X) # default frm = ttk.Frame(frame, style=bootstyle, width=150, height=100) frm.pack(padx=5, pady=5) frm.pack_propagate(0) ttk.Label(frm, text='default').pack(fill=tk.BOTH) # color for color in style.theme.colors: frm = ttk.Frame(frame, bootstyle=color, width=150, height=100) frm.pack(padx=5, pady=5) frm.pack_propagate(0) ttk.Label(master=frm, text=color, bootstyle=(color, 'inverse')).pack(fill=tk.BOTH) return frame
def create_treeview_style(_, style): frame = ttk.Frame(root, padding=5) # title title = ttk.Label(frame, text='Treeview', anchor=tk.CENTER) title.pack(padx=5, pady=2, fill=tk.BOTH) ttk.Separator(frame).pack(padx=5, pady=5, fill=tk.X) # default ttk.Label(frame, text='default').pack(fill=tk.X) tv = ttk.Treeview(frame, columns=[0, 1], height=2) tv.heading('#0', text='Column') for x in range(2): tv.heading(x, text=f'Column {x}') tv.insert('', 'end', text=f'Item {x}', values=[f'Row {x}', f'Row {x+1}']) tv.pack(padx=5, pady=5, fill=tk.BOTH) # colored for color in style.colors: ttk.Label(frame, text=color).pack(fill=tk.X) tv = ttk.Treeview(master=frame, bootstyle=color, columns=[0, 1], height=2) tv.heading('#0', text='Column') for x in range(2): tv.heading(x, text=f'Column {x}') tv.insert('', 'end', text=f'Item {x}', values=[f'Row {x}', f'Row {x+1}']) tv.pack(padx=5, pady=5, fill=tk.BOTH) return frame
def create_menubutton_frame(bootstyle, style, testname): frame = ttk.Frame(root, padding=5) title = ttk.Label(master=frame, text=testname, anchor=tk.CENTER) title.pack(padx=5, pady=2, fill=tk.BOTH) ttk.Separator(frame).pack(padx=5, pady=5, fill=tk.X) btn = ttk.Menubutton(master=frame, text='default', bootstyle=bootstyle) btn.pack(padx=5, pady=5, fill=tk.BOTH) for color in style.colors: btn = ttk.Menubutton(master=frame, text=color, bootstyle=(color, bootstyle)) btn.pack(padx=5, pady=5, fill=tk.BOTH) btn = ttk.Menubutton(master=frame, text='disabled', state=tk.DISABLED, bootstyle=bootstyle) btn.pack(padx=5, pady=5, fill=tk.BOTH) return frame
def create_radiobutton_test(bootstyle, style, testname): frame = ttk.Frame(padding=10) var = tk.Variable() # title title = ttk.Label(frame, text=testname, anchor=tk.CENTER) title.pack(padx=5, pady=2, fill=tk.BOTH) ttk.Separator(frame).pack(padx=5, pady=5, fill=tk.X) # default style cb = ttk.Radiobutton(frame, text='default', bootstyle=bootstyle, value=0) cb.configure(variable=var) cb.pack(padx=5, pady=5, fill=tk.BOTH) cb.invoke() # color styles for i, color in enumerate(style.colors): cb = ttk.Radiobutton(frame, text=color, bootstyle=f'{color}-{bootstyle}') cb.configure(variable=var, value=i + 1) cb.pack(padx=5, pady=5, fill=tk.BOTH) cb.invoke() # disabled style cb = ttk.Radiobutton(master=frame, text=bootstyle, bootstyle=bootstyle, state=tk.DISABLED, variable=var, value=i + 1) cb.pack(padx=5, pady=5, fill=tk.BOTH) cb.invoke() return frame
def create_sizegrip_style(bootstyle, style): frame = ttk.Frame(root, padding=5) # title title = ttk.Label( master=frame, text='Sizegrip', anchor=tk.CENTER ) title.pack(padx=5, pady=2, fill=tk.BOTH) ttk.Separator(frame).pack(padx=5, pady=5, fill=tk.X) # default ttk.Label(frame, text=bootstyle).pack(fill=tk.X) sg = ttk.Sizegrip(frame) sg.pack(padx=5, pady=5, fill=tk.BOTH, expand=True) # colored for color in style.colors: ttk.Label(frame, text=color).pack(fill=tk.X) sg = ttk.Sizegrip(frame, bootstyle=(color, bootstyle)) sg.pack(padx=5, pady=5, fill=tk.BOTH, expand=True) return frame
import tkinter as tk import ttkbootstrap as ttk from ttkbootstrap import utility utility.enable_high_dpi_awareness() root = tk.Tk() style = ttk.Style() frame = ttk.Frame(padding=5) frame.pack(padx=5, pady=5, fill=tk.X) top_frame = ttk.Frame(frame) bot_frame = ttk.Frame(frame) top_frame.pack(fill=tk.X) bot_frame.pack(fill=tk.X) for i, color in enumerate(['default', *style.colors]): if i < 5: f = ttk.Frame(top_frame) else: f = ttk.Frame(bot_frame) ttk.Label(f, text=color, width=20).pack(side=tk.TOP) a = ttk.Separator(f, bootstyle=color) a.pack(fill=tk.X) f.pack(side=tk.LEFT, padx=3, pady=10, fill=tk.X) root.mainloop()
def setup_demo(master): ZEN = """Beautiful is better than ugly. Explicit is better than implicit. Simple is better than complex. Complex is better than complicated. Flat is better than nested. Sparse is better than dense. Readability counts. Special cases aren't special enough to break the rules. Although practicality beats purity. Errors should never pass silently. Unless explicitly silenced. In the face of ambiguity, refuse the temptation to guess. There should be one-- and preferably only one --obvious way to do it. Although that way may not be obvious at first unless you're Dutch. Now is better than never. Although never is often better than *right* now. If the implementation is hard to explain, it's a bad idea. If the implementation is easy to explain, it may be a good idea. Namespaces are one honking great idea -- let's do more of those!""" root = ttk.Frame(master, padding=10) style = ttk.Style() theme_names = style.theme_names() theme_selection = ttk.Frame(root, padding=(10, 10, 10, 0)) theme_selection.pack(fill=X, expand=YES) theme_selected = ttk.Label(master=theme_selection, text="litera", font="-size 24 -weight bold") theme_selected.pack(side=LEFT) lbl = ttk.Label(theme_selection, text="Select a theme:") theme_cbo = ttk.Combobox( master=theme_selection, text=style.theme.name, values=theme_names, ) theme_cbo.pack(padx=10, side=RIGHT) theme_cbo.current(theme_names.index(style.theme.name)) lbl.pack(side=RIGHT) ttk.Separator(root).pack(fill=X, pady=10, padx=10) def change_theme(e): t = cbo.get() style.theme_use(t) theme_selected.configure(text=t) theme_cbo.selection_clear() default.focus_set() theme_cbo.bind("<<ComboboxSelected>>", change_theme) lframe = ttk.Frame(root, padding=5) lframe.pack(side=LEFT, fill=BOTH, expand=YES) rframe = ttk.Frame(root, padding=5) rframe.pack(side=RIGHT, fill=BOTH, expand=YES) color_group = ttk.Labelframe(master=lframe, text="Theme color options", padding=10) color_group.pack(fill=X, side=TOP) for color in style.colors: cb = ttk.Button(color_group, text=color, bootstyle=color) cb.pack(side=LEFT, expand=YES, padx=5, fill=X) rb_group = ttk.Labelframe(lframe, text="Checkbuttons & radiobuttons", padding=10) rb_group.pack(fill=X, pady=10, side=TOP) check1 = ttk.Checkbutton(rb_group, text="selected") check1.pack(side=LEFT, expand=YES, padx=5) check1.invoke() check2 = ttk.Checkbutton(rb_group, text="alternate") check2.pack(side=LEFT, expand=YES, padx=5) check4 = ttk.Checkbutton(rb_group, text="deselected") check4.pack(side=LEFT, expand=YES, padx=5) check4.invoke() check4.invoke() check3 = ttk.Checkbutton(rb_group, text="disabled", state=DISABLED) check3.pack(side=LEFT, expand=YES, padx=5) radio1 = ttk.Radiobutton(rb_group, text="selected", value=1) radio1.pack(side=LEFT, expand=YES, padx=5) radio1.invoke() radio2 = ttk.Radiobutton(rb_group, text="deselected", value=2) radio2.pack(side=LEFT, expand=YES, padx=5) radio3 = ttk.Radiobutton(master=rb_group, text="disabled", value=3, state=DISABLED) radio3.pack(side=LEFT, expand=YES, padx=5) ttframe = ttk.Frame(lframe) ttframe.pack(pady=5, fill=X, side=TOP) table_data = [ ("South Island, New Zealand", 1), ("Paris", 2), ("Bora Bora", 3), ("Maui", 4), ("Tahiti", 5), ] tv = ttk.Treeview(master=ttframe, columns=[0, 1], show=HEADINGS, height=5) for row in table_data: tv.insert("", END, values=row) tv.selection_set("I001") tv.heading(0, text="City") tv.heading(1, text="Rank") tv.column(0, width=300) tv.column(1, width=70, anchor=CENTER) tv.pack(side=LEFT, anchor=NE, fill=X) # # notebook with table and text tabs nb = ttk.Notebook(ttframe) nb.pack(side=LEFT, padx=(10, 0), expand=YES, fill=BOTH) nb_text = "This is a notebook tab.\nYou can put any widget you want here." nb.add(ttk.Label(nb, text=nb_text), text="Tab 1", sticky=NW) nb.add(child=ttk.Label(nb, text="A notebook tab."), text="Tab 2", sticky=NW) nb.add(ttk.Frame(nb), text="Tab 3") nb.add(ttk.Frame(nb), text="Tab 4") nb.add(ttk.Frame(nb), text="Tab 5") # text widget txt = ScrolledText(master=lframe, height=5, width=50, autohide=True) txt.insert(END, ZEN) txt.pack(side=LEFT, anchor=NW, pady=5, fill=BOTH, expand=YES) lframe_inner = ttk.Frame(lframe) lframe_inner.pack(fill=BOTH, expand=YES, padx=10) s1 = ttk.Scale(master=lframe_inner, orient=HORIZONTAL, value=75, from_=100, to=0) s1.pack(fill=X, pady=5, expand=YES) ttk.Progressbar( master=lframe_inner, orient=HORIZONTAL, value=50, ).pack(fill=X, pady=5, expand=YES) ttk.Progressbar( master=lframe_inner, orient=HORIZONTAL, value=75, bootstyle=(SUCCESS, STRIPED), ).pack(fill=X, pady=5, expand=YES) m = ttk.Meter( master=lframe_inner, metersize=150, amountused=45, subtext="meter widget", bootstyle=INFO, interactive=True, ) m.pack(pady=10) sb = ttk.Scrollbar( master=lframe_inner, orient=HORIZONTAL, ) sb.set(0.1, 0.9) sb.pack(fill=X, pady=5, expand=YES) sb = ttk.Scrollbar(master=lframe_inner, orient=HORIZONTAL, bootstyle=(DANGER, ROUND)) sb.set(0.1, 0.9) sb.pack(fill=X, pady=5, expand=YES) btn_group = ttk.Labelframe(master=rframe, text="Buttons", padding=(10, 5)) btn_group.pack(fill=X) menu = ttk.Menu(root) for i, t in enumerate(style.theme_names()): menu.add_radiobutton(label=t, value=i) default = ttk.Button(master=btn_group, text="solid button") default.pack(fill=X, pady=5) default.focus_set() mb = ttk.Menubutton( master=btn_group, text="solid menubutton", bootstyle=SECONDARY, menu=menu, ) mb.pack(fill=X, pady=5) cb = ttk.Checkbutton( master=btn_group, text="solid toolbutton", bootstyle=(SUCCESS, TOOLBUTTON), ) cb.invoke() cb.pack(fill=X, pady=5) ob = ttk.Button( master=btn_group, text="outline button", bootstyle=(INFO, OUTLINE), command=lambda: Messagebox.ok("You pushed an outline button"), ) ob.pack(fill=X, pady=5) mb = ttk.Menubutton( master=btn_group, text="outline menubutton", bootstyle=(WARNING, OUTLINE), menu=menu, ) mb.pack(fill=X, pady=5) cb = ttk.Checkbutton( master=btn_group, text="outline toolbutton", bootstyle=(SUCCESS, OUTLINE, TOOLBUTTON), ) cb.pack(fill=X, pady=5) lb = ttk.Button(master=btn_group, text="link button", bootstyle=LINK) lb.pack(fill=X, pady=5) cb1 = ttk.Checkbutton( master=btn_group, text="rounded toggle", bootstyle=(SUCCESS, ROUND, TOGGLE), ) cb1.invoke() cb1.pack(fill=X, pady=5) cb2 = ttk.Checkbutton(master=btn_group, text="squared toggle", bootstyle=(SQUARE, TOGGLE)) cb2.pack(fill=X, pady=5) cb2.invoke() input_group = ttk.Labelframe(master=rframe, text="Other input widgets", padding=10) input_group.pack(fill=BOTH, pady=(10, 5), expand=YES) entry = ttk.Entry(input_group) entry.pack(fill=X) entry.insert(END, "entry widget") password = ttk.Entry(master=input_group, show="•") password.pack(fill=X, pady=5) password.insert(END, "password") spinbox = ttk.Spinbox(master=input_group, from_=0, to=100) spinbox.pack(fill=X) spinbox.set(45) cbo = ttk.Combobox( master=input_group, text=style.theme.name, values=theme_names, exportselection=False, ) cbo.pack(fill=X, pady=5) cbo.current(theme_names.index(style.theme.name)) de = ttk.DateEntry(input_group) de.pack(fill=X) return root
def __init__(self, tk_parent, linkedin_conn): self.parent = tk_parent self.linkedin_conn = linkedin_conn self.search_results_df = pd.DataFrame() self.search_thread = None self.quick_search = True # Paned Window self.search_paned_window = ttk.PanedWindow(tk_parent, orient='horizontal') self.search_paned_window.pack(side='top', fill="both", expand=True, padx=10) ## Search fields Canvas/ScrolledFrame search_fields_canvas = ttk.Canvas(self.search_paned_window) search_fields_frame = ScrolledFrame(search_fields_canvas) search_fields_frame.pack(side='top', fill='both', expand=True, padx=5) search_fields_frame.hide_scrollbars() ### Load/Save search load_save_btn_frame = ttk.Frame(search_fields_frame) load_save_btn_frame.pack(pady=5, side='top', fill="x") load_search_btn = ttk.Button(load_save_btn_frame, text="Load param.") load_search_btn.pack(side='left') load_search_btn['command'] = self.load_search_config save_search_btn = ttk.Button(load_save_btn_frame, text="Save param.") save_search_btn.pack(side='right', padx=10) save_search_btn['command'] = self.save_search_config ### Connections conn_frame = ttk.Frame(search_fields_frame) conn_frame.pack(pady=10, side='top', fill='x') conn_lbl = ttk.Label(conn_frame, text="Connections") conn_lbl.pack(side='left', expand=False) ToolTip(conn_lbl, text=f"Degree of Connection with the logged in user.") first_con = ttk.BooleanVar() second_con = ttk.BooleanVar() third_con = ttk.BooleanVar() self.con_dict_list = [{ 'bool_val': first_con, 'name': 'F' }, { 'bool_val': second_con, 'name': 'S' }, { 'bool_val': third_con, 'name': 'O' }] ttk.Checkbutton(conn_frame, text="1st", variable=first_con, bootstyle="primary").pack(side='left', padx=10) ttk.Checkbutton(conn_frame, text="2nd", variable=second_con, bootstyle="primary").pack(side='left', padx=10) ttk.Checkbutton(conn_frame, text="3rd+", variable=third_con, bootstyle="primary").pack(side='left', padx=10) ttk.Separator(search_fields_frame, orient='horizontal').pack(side='top', fill='x', pady=5) ### Connection of self.conn_of_frame = SearchFrame( search_fields_frame, title='Connection of', single_choice=True, fetch_fct=lambda x: utils.extract_urn_dict_from_query_results( linkedin_conn[0].get_contact_urn_ids, x)) self.conn_of_frame.pack(side='top', fill="x") ttk.Separator(search_fields_frame, orient='horizontal').pack(side='top', fill='x', pady=5) ### Location Frame self.loc_frame = SearchFrame( search_fields_frame, title='Location', fetch_fct=lambda x: utils.extract_urn_dict_from_query_results( linkedin_conn[0].get_geo_urn_ids, x)) self.loc_frame.pack(side='top', fill="x") ttk.Separator(search_fields_frame, orient='horizontal').pack(side='top', fill='x', pady=5) ### Current Company frame self.current_comp_frame = SearchFrame( search_fields_frame, title='Current Company', fetch_fct=lambda x: utils.extract_urn_dict_from_query_results( linkedin_conn[0].get_company_urn_ids, x)) self.current_comp_frame.pack(side='top', fill="x") ttk.Separator(search_fields_frame, orient='horizontal').pack(side='top', fill='x', pady=5) ### Past Company frame self.past_comp_frame = SearchFrame( search_fields_frame, title='Past Company', fetch_fct=lambda x: utils.extract_urn_dict_from_query_results( linkedin_conn[0].get_company_urn_ids, x)) self.past_comp_frame.pack(side='top', fill="x", pady=5) ttk.Separator(search_fields_frame, orient='horizontal').pack(side='top', fill='x', pady=5) ### School frame self.school_frame = SearchFrame( search_fields_frame, title='School', fetch_fct=lambda x: utils.extract_urn_dict_from_query_results( linkedin_conn[0].get_school_urn_ids, x)) self.school_frame.pack(side='top', fill="x", pady=5) ttk.Separator(search_fields_frame, orient='horizontal').pack(side='top', fill='x', pady=5) ### Industry frame self.industry_frame = SearchFrame( search_fields_frame, title='Industry', fetch_fct=lambda x: utils.extract_urn_dict_from_query_results( linkedin_conn[0].get_industry_urn_ids, x)) self.industry_frame.pack(side='top', fill="x", pady=5) ### KW-Header kw_header_frame = ttk.Frame(search_fields_frame) kw_header_frame.pack(pady=5, side='top', fill="x") ttk.Label(kw_header_frame, text="Keywords").pack(side='left') ttk.Separator(kw_header_frame, orient='horizontal').pack(side='left', fill='x', expand=True) ### KW-Frame kw_frame = ttk.Frame(search_fields_frame) kw_frame.pack(pady=5, side='top', fill="x") kw_frame.grid_columnconfigure(0, weight=1) kw_frame.grid_columnconfigure(1, weight=1) kw_frame.grid_rowconfigure(0, weight=1) kw_frame.grid_rowconfigure(1, weight=1) kw_frame.grid_rowconfigure(2, weight=1) #### General self.entry_keywords = PlaceholderEntry(kw_frame, 'General') self.entry_keywords.grid(row=0, column=0, sticky='nwse', padx=5, pady=4) #### First Name self.entry_keywords_first_name = PlaceholderEntry( kw_frame, 'First Name') self.entry_keywords_first_name.grid(row=0, column=1, sticky='nwse', padx=5, pady=4) #### Last Name self.entry_keywords_last_name = PlaceholderEntry(kw_frame, 'Last Name') self.entry_keywords_last_name.grid(row=1, column=0, sticky='nwse', padx=5, pady=4) #### Title self.entry_keywords_title = PlaceholderEntry(kw_frame, 'Title') self.entry_keywords_title.grid(row=1, column=1, sticky='nwse', padx=5, pady=4) #### Company self.entry_keywords_company = PlaceholderEntry(kw_frame, 'Company') self.entry_keywords_company.grid(row=2, column=0, sticky='nwse', padx=5, pady=4) #### School self.entry_keywords_school = PlaceholderEntry(kw_frame, 'School') self.entry_keywords_school.grid(row=2, column=1, sticky='nwse', padx=5, pady=4) self.search_paned_window.add(search_fields_canvas) ## Table frame self.table_main_frame = ttk.Frame(tk_parent) # pandastable self.table_frame = ttk.Frame(self.table_main_frame, bootstyle="secondary", borderwidth=2) self.table_frame.pack(side="top", fill="both", expand=True) self.table = Table(self.table_frame, dataframe=pd.DataFrame(), showtoolbar=False, showstatusbar=True) utils.fit_table_style_to_theme(self.table, ttk.Style()) self.table.unbind_all("<Tab>") self.table.unbind_all("<Return>") self.table.show() self.search_paned_window.add(self.table_main_frame) # Buttons frame btn_frame = ttk.Frame(tk_parent) btn_frame.pack(padx=10, pady=10, side='top', fill="x") quick_search_btn = ttk.Button(btn_frame, text="Quick search") quick_search_btn.pack(side='left', padx=10) quick_search_btn['command'] = self.start_quick_search ToolTip( quick_search_btn, "This is a single request that will yield the same results as in the linkedin search bar. \ \nIt doesn't contain any personal details (only public IDs) \ \nYou're not likely to reach any search limit using this mode.") btn_sub_frame = ttk.Frame(btn_frame) btn_sub_frame.pack(side="left", fill="none", expand=True) start_search_btn = ttk.Button(btn_sub_frame, text="Deep Search", bootstyle='danger') start_search_btn.pack(side='left', padx=10) start_search_btn['command'] = self.start_deep_search ToolTip( start_search_btn, "Each search result will be fetched for additional information. \ \nDepending on the number of results and search frequency, this can trigger the linkedin limit \ after which you'll only be able to get 3 results per search until the end of the month." ) self.get_skills = ttk.BooleanVar() skills_chk_btn = ttk.Checkbutton(btn_sub_frame, text="Fetch skills", variable=self.get_skills, bootstyle="danger") skills_chk_btn.pack(side='left', padx=10) ToolTip( skills_chk_btn, text=f"Fetch skills by running one additional request per result.") self.get_contact_info = ttk.BooleanVar() contact_info_chk_btn = ttk.Checkbutton(btn_sub_frame, text="Fetch contact info", variable=self.get_contact_info, bootstyle="danger") contact_info_chk_btn.pack(side='left', padx=10) ToolTip( contact_info_chk_btn, text= f"Fetch contact info by running one additional request per result." ) self.export_to_file_btn = ttk.Button(btn_frame, text="Export to File", state="disabled") self.export_to_file_btn.pack(side='left', padx=10) self.export_to_file_btn[ 'command'] = self.prepare_dataframe_and_save_to_xsl # Status frame self.status_frame = ttk.Frame(tk_parent) self.status_frame.pack(padx=10, pady=2, side='bottom', expand=False, fill="x") self.status_str = ttk.StringVar(value="") ttk.Label(self.status_frame, textvariable=self.status_str).pack(side='left', expand=False) ttk.Separator(tk_parent, orient='horizontal').pack(side='bottom', fill='x')
def __init__(self, tk_parent, linkedin_conn): self.parent = tk_parent self.linkedin_conn = linkedin_conn self.search_results_df = pd.DataFrame() self.search_thread = None self.quick_search = True # Paned Window self.search_paned_window = ttk.PanedWindow(tk_parent, orient='horizontal') self.search_paned_window.pack(side='top', fill="both", expand=True, padx=10) ## Search fields Canvas/ScrolledFrame search_fields_canvas = ttk.Canvas(self.search_paned_window) search_fields_frame = ScrolledFrame(search_fields_canvas) search_fields_frame.pack(side='top', fill='both', expand=True, padx=5) search_fields_frame.hide_scrollbars() ### Load/Save search load_save_btn_frame = ttk.Frame(search_fields_frame) load_save_btn_frame.pack(pady=5, side='top', fill="x") load_search_btn = ttk.Button(load_save_btn_frame, text="Load param.") load_search_btn.pack(side='left') load_search_btn['command'] = self.load_search_config save_search_btn = ttk.Button(load_save_btn_frame, text="Save param.") save_search_btn.pack(side='right', padx=10) save_search_btn['command'] = self.save_search_config ### KW-Frame kw_frame = ttk.Frame(search_fields_frame) kw_frame.pack(pady=5, side='top', fill="x") ttk.Label(kw_frame, text="Keywords").pack(side='left') self.entry_keywords = ttk.Entry(kw_frame) self.entry_keywords.pack(side='left', padx=10, fill='x', expand=True) ttk.Separator(search_fields_frame, orient='horizontal').pack(side='top', fill='x', pady=5) ### Radio Frame radio_frame = ttk.Frame(search_fields_frame) radio_frame.pack(side='top', fill="x", pady=5, expand=True) radio_frame.grid_columnconfigure(0,weight=0) radio_frame.grid_columnconfigure(1,weight=0) radio_frame.grid_columnconfigure(2,weight=1) #### Sort by ttk.Label(radio_frame, text="Sort by").grid(row=0, column=0, sticky='nwse') self.sort_by = ttk.StringVar(value="R") ttk.Radiobutton(radio_frame, text='Most recent', variable=self.sort_by, value="DD").grid(row=0, column=1, padx=10, sticky='nwse') ttk.Radiobutton(radio_frame, text='Most relevant', variable=self.sort_by, value="R").grid(row=0, column=2, padx=10, sticky='nwse') ttk.Separator(radio_frame, orient='horizontal').grid(row=1, columnspan=3, pady=5, sticky='nwse') #### Date Posted ttk.Label(radio_frame, text="Date Posted").grid(row=2, column=0, sticky='nwse', pady=5) self.date_posted = ttk.IntVar(value=365) # Days since job was posted ttk.Radiobutton(radio_frame, text='Past 24h', variable=self.date_posted, value=1).grid(row=3, column=1, padx=10, pady=4, sticky='nwse') ttk.Radiobutton(radio_frame, text='Past Week', variable=self.date_posted, value=7).grid(row=3, column=2, padx=10, pady=4, sticky='nwse') ttk.Radiobutton(radio_frame, text='Past Month', variable=self.date_posted, value=30).grid(row=4, column=1, padx=10, pady=4, sticky='nwse') ttk.Radiobutton(radio_frame, text='Any Time', variable=self.date_posted, value=365).grid(row=4, column=2, padx=10, pady=4, sticky='nwse') ttk.Separator(search_fields_frame, orient='horizontal').pack(side='top', fill='x', pady=5) ### Experience exp_frame = ttk.Frame(search_fields_frame) exp_frame.pack(side='top', fill="x") exp_frame.grid_columnconfigure(0,weight=0) exp_frame.grid_columnconfigure(1,weight=0) exp_frame.grid_columnconfigure(2,weight=1) ttk.Label(exp_frame, text="Experience").grid(row=0, column=0, pady=4, sticky='nwse') intern_lvl_bool = ttk.BooleanVar() entry_lvl_bool = ttk.BooleanVar() associate_bool = ttk.BooleanVar() mid_senior_bool = ttk.BooleanVar() director_bool = ttk.BooleanVar() executive_bool = ttk.BooleanVar() self.exp_dict_list = [ {'bool_val': intern_lvl_bool, 'name': '1'}, {'bool_val': entry_lvl_bool, 'name': '2'}, {'bool_val': associate_bool, 'name': '3'}, {'bool_val': mid_senior_bool, 'name': '4'}, {'bool_val': director_bool, 'name': '5'}, {'bool_val': executive_bool, 'name': '6'}, ] ttk.Checkbutton(exp_frame, text="Internship", variable=intern_lvl_bool).grid(row=1, column=0, padx=5, pady=4, sticky='nwse') ttk.Checkbutton(exp_frame, text="Entry level", variable=entry_lvl_bool).grid(row=1, column=1, padx=5, pady=4, sticky='nwse') ttk.Checkbutton(exp_frame, text="Associate", variable=associate_bool).grid(row=1, column=2, padx=5, pady=4, sticky='nwse') ttk.Checkbutton(exp_frame, text="Mid-Senior level", variable=mid_senior_bool).grid(row=2, column=0, padx=5, pady=4, sticky='nwse') ttk.Checkbutton(exp_frame, text="Director", variable=director_bool).grid(row=2, column=1, padx=5, pady=4, sticky='nwse') ttk.Checkbutton(exp_frame, text="Executive", variable=executive_bool).grid(row=2, column=2, padx=5, pady=4, sticky='nwse') ttk.Separator(search_fields_frame, orient='horizontal').pack(side='top', fill='x', pady=5) ### Company frame self.comp_frame = SearchFrame(search_fields_frame, title='Company', fetch_fct=lambda x: utils.extract_urn_dict_from_query_results(linkedin_conn[0].get_company_urn_ids, x)) self.comp_frame.pack(side='top', fill="x") ttk.Separator(search_fields_frame, orient='horizontal').pack(side='top', fill='x', pady=5) ### Job Type job_type_frame = ttk.Frame(search_fields_frame) job_type_frame.pack(side='top', fill="x") job_type_frame.grid_columnconfigure(0,weight=0) job_type_frame.grid_columnconfigure(1,weight=0) job_type_frame.grid_columnconfigure(2,weight=1) ttk.Label(job_type_frame, text="Job Type").grid(row=0, column=0, pady=4, sticky='nwse') full_time_bool = ttk.BooleanVar() part_time_bool = ttk.BooleanVar() temporary_bool = ttk.BooleanVar() contract_bool = ttk.BooleanVar() volunteer_bool = ttk.BooleanVar() intern_type_bool = ttk.BooleanVar() other_type_bool = ttk.BooleanVar() self.job_type_dict_list = [ {'bool_val': full_time_bool, 'name': 'F'}, {'bool_val': part_time_bool, 'name': 'P'}, {'bool_val': temporary_bool, 'name': 'T'}, {'bool_val': contract_bool, 'name': 'C'}, {'bool_val': volunteer_bool, 'name': 'V'}, {'bool_val': intern_type_bool, 'name': 'I'}, {'bool_val': other_type_bool, 'name': 'O'}, ] ttk.Checkbutton(job_type_frame, text="Other", variable=other_type_bool).grid(row=0, column=2, padx=10, pady=4, sticky='nwse') ttk.Checkbutton(job_type_frame, text="Full-time", variable=full_time_bool).grid(row=1, column=0, padx=10, pady=4, sticky='nwse') ttk.Checkbutton(job_type_frame, text="Part-time", variable=part_time_bool).grid(row=1, column=1, padx=10, pady=4, sticky='nwse') ttk.Checkbutton(job_type_frame, text="Temporary", variable=temporary_bool).grid(row=1, column=2, padx=10, pady=4, sticky='nwse') ttk.Checkbutton(job_type_frame, text="Contract", variable=contract_bool).grid(row=2, column=0, padx=10, pady=4, sticky='nwse') ttk.Checkbutton(job_type_frame, text="Volunteer", variable=volunteer_bool).grid(row=2, column=1, padx=10, pady=4, sticky='nwse') ttk.Checkbutton(job_type_frame, text="Internship", variable=intern_type_bool).grid(row=2, column=2, padx=10, pady=4, sticky='nwse') ttk.Separator(search_fields_frame, orient='horizontal').pack(side='top', fill='x', pady=5) ### Location Fallback self.loc_fallback_frame = SearchFrame(search_fields_frame, title='General Location', single_choice=True, fetch_fct=lambda x: utils.extract_urn_dict_from_query_results(linkedin_conn[0].get_geo_urn_ids, x), tooltip="Restrict the geographical area of the results. In the browser, your location will be recognized automatically and shown at the top of the search page close to the keyword field.") self.loc_fallback_frame.pack(side='top', fill="x") ### Location Frame self.loc_frame = SearchFrame(search_fields_frame, title='Location', fetch_fct=lambda x: utils.extract_urn_dict_from_query_results(linkedin_conn[0].get_geo_urn_ids, x)) self.loc_frame.pack(side='top', fill="x") ttk.Separator(search_fields_frame, orient='horizontal').pack(side='top', fill='x', pady=5) ### Industry frame self.industry_frame = SearchFrame(search_fields_frame, title='Industry', fetch_fct=lambda x: utils.extract_urn_dict_from_query_results(linkedin_conn[0].get_industry_urn_ids, x)) self.industry_frame.pack(side='top', fill="x", pady=5) self.search_paned_window.add(search_fields_canvas) ## Table frame self.table_main_frame = ttk.Frame(tk_parent) # pandastable self.table_frame = ttk.Frame(self.table_main_frame, bootstyle="secondary", borderwidth=2) self.table_frame.pack(side="top", fill="both", expand=True) self.table = Table(self.table_frame, dataframe=pd.DataFrame(), showtoolbar=False, showstatusbar=True) utils.fit_table_style_to_theme(self.table, ttk.Style()) self.table.unbind_all("<Tab>") self.table.unbind_all("<Return>") self.table.show() self.search_paned_window.add(self.table_main_frame) # Buttons frame btn_frame = ttk.Frame(tk_parent) btn_frame.pack(padx=10, pady=10, side='top', fill="x") quick_search_btn = ttk.Button(btn_frame, text="Quick search") quick_search_btn.pack(side='left', padx=10) quick_search_btn['command'] = self.start_quick_search ToolTip(quick_search_btn, "This is a single request that will yield the same results as in the linkedin search bar. \ \nIt doesn't contain any personal details (only public IDs) \ \nYou're not likely to reach any search limit using this mode.") btn_sub_frame = ttk.Frame(btn_frame) btn_sub_frame.pack(side="left", fill="none", expand=True) start_search_btn = ttk.Button(btn_sub_frame, text="Deep Search", bootstyle='danger') start_search_btn.pack(side='left', padx=10) start_search_btn['command'] = self.start_deep_search ToolTip(start_search_btn, "Each search result will be fetched for additional information. \ \nDepending on the number of results and search frequency, this can trigger the linkedin limit \ after which you'll only be able to get 3 results per search until the end of the month.") # self.get_contact_info = ttk.BooleanVar() # contact_info_chk_btn = ttk.Checkbutton(btn_sub_frame, text="Fetch contact info", # variable=self.get_contact_info, bootstyle="danger") # contact_info_chk_btn.pack(side='left', padx=10) # ToolTip(contact_info_chk_btn, text=f"Fetch contact info by running one additional request per result.") self.export_to_file_btn = ttk.Button(btn_frame, text="Export to File", state="disabled") self.export_to_file_btn.pack(side='left', padx=10) self.export_to_file_btn['command'] = self.prepare_dataframe_and_save_to_xsl # Status frame self.status_frame = ttk.Frame(tk_parent) self.status_frame.pack(padx=10, pady=2, side='bottom', expand=False, fill="x") self.status_str = ttk.StringVar(value="") ttk.Label(self.status_frame, textvariable=self.status_str).pack(side='left', expand=False) ttk.Separator(tk_parent, orient='horizontal').pack(side='bottom', fill='x')
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.pack(fill=BOTH, expand=YES) image_files = { 'properties-dark': 'icons8_settings_24px.png', 'properties-light': 'icons8_settings_24px_2.png', 'add-to-backup-dark': 'icons8_add_folder_24px.png', 'add-to-backup-light': 'icons8_add_book_24px.png', 'stop-backup-dark': 'icons8_cancel_24px.png', 'stop-backup-light': 'icons8_cancel_24px_1.png', 'play': 'icons8_play_24px_1.png', 'refresh': 'icons8_refresh_24px_1.png', 'stop-dark': 'icons8_stop_24px.png', 'stop-light': 'icons8_stop_24px_1.png', 'opened-folder': 'icons8_opened_folder_24px.png', 'logo': 'backup.png' } self.photoimages = [] imgpath = Path(__file__).parent / 'assets' for key, val in image_files.items(): _path = imgpath / val self.photoimages.append(ttk.PhotoImage(name=key, file=_path)) # buttonbar buttonbar = ttk.Frame(self, style='primary.TFrame') buttonbar.pack(fill=X, pady=1, side=TOP) ## new backup _func = lambda: Messagebox.ok(message='Adding new backup') btn = ttk.Button(master=buttonbar, text='New backup set', image='add-to-backup-light', compound=LEFT, command=_func) btn.pack(side=LEFT, ipadx=5, ipady=5, padx=(1, 0), pady=1) ## backup _func = lambda: Messagebox.ok(message='Backing up...') btn = ttk.Button(master=buttonbar, text='Backup', image='play', compound=LEFT, command=_func) btn.pack(side=LEFT, ipadx=5, ipady=5, padx=0, pady=1) ## refresh _func = lambda: Messagebox.ok(message='Refreshing...') btn = ttk.Button(master=buttonbar, text='Refresh', image='refresh', compound=LEFT, command=_func) btn.pack(side=LEFT, ipadx=5, ipady=5, padx=0, pady=1) ## stop _func = lambda: Messagebox.ok(message='Stopping backup.') btn = ttk.Button(master=buttonbar, text='Stop', image='stop-light', compound=LEFT, command=_func) btn.pack(side=LEFT, ipadx=5, ipady=5, padx=0, pady=1) ## settings _func = lambda: Messagebox.ok(message='Changing settings') btn = ttk.Button(master=buttonbar, text='Settings', image='properties-light', compound=LEFT, command=_func) btn.pack(side=LEFT, ipadx=5, ipady=5, padx=0, pady=1) # left panel left_panel = ttk.Frame(self, style='bg.TFrame') left_panel.pack(side=LEFT, fill=Y) ## backup summary (collapsible) bus_cf = CollapsingFrame(left_panel) bus_cf.pack(fill=X, pady=1) ## container bus_frm = ttk.Frame(bus_cf, padding=5) bus_frm.columnconfigure(1, weight=1) bus_cf.add(child=bus_frm, title='Backup Summary', bootstyle=SECONDARY) ## destination lbl = ttk.Label(bus_frm, text='Destination:') lbl.grid(row=0, column=0, sticky=W, pady=2) lbl = ttk.Label(bus_frm, textvariable='destination') lbl.grid(row=0, column=1, sticky=EW, padx=5, pady=2) self.setvar('destination', 'd:/test/') ## last run lbl = ttk.Label(bus_frm, text='Last Run:') lbl.grid(row=1, column=0, sticky=W, pady=2) lbl = ttk.Label(bus_frm, textvariable='lastrun') lbl.grid(row=1, column=1, sticky=EW, padx=5, pady=2) self.setvar('lastrun', '14.06.2021 19:34:43') ## files Identical lbl = ttk.Label(bus_frm, text='Files Identical:') lbl.grid(row=2, column=0, sticky=W, pady=2) lbl = ttk.Label(bus_frm, textvariable='filesidentical') lbl.grid(row=2, column=1, sticky=EW, padx=5, pady=2) self.setvar('filesidentical', '15%') ## section separator sep = ttk.Separator(bus_frm, bootstyle=SECONDARY) sep.grid(row=3, column=0, columnspan=2, pady=10, sticky=EW) ## properties button _func = lambda: Messagebox.ok(message='Changing properties') bus_prop_btn = ttk.Button(master=bus_frm, text='Properties', image='properties-dark', compound=LEFT, command=_func, bootstyle=LINK) bus_prop_btn.grid(row=4, column=0, columnspan=2, sticky=W) ## add to backup button _func = lambda: Messagebox.ok(message='Adding to backup') add_btn = ttk.Button(master=bus_frm, text='Add to backup', image='add-to-backup-dark', compound=LEFT, command=_func, bootstyle=LINK) add_btn.grid(row=5, column=0, columnspan=2, sticky=W) # backup status (collapsible) status_cf = CollapsingFrame(left_panel) status_cf.pack(fill=BOTH, pady=1) ## container status_frm = ttk.Frame(status_cf, padding=10) status_frm.columnconfigure(1, weight=1) status_cf.add(child=status_frm, title='Backup Status', bootstyle=SECONDARY) ## progress message lbl = ttk.Label(master=status_frm, textvariable='prog-message', font='Helvetica 10 bold') lbl.grid(row=0, column=0, columnspan=2, sticky=W) self.setvar('prog-message', 'Backing up...') ## progress bar pb = ttk.Progressbar(master=status_frm, variable='prog-value', bootstyle=SUCCESS) pb.grid(row=1, column=0, columnspan=2, sticky=EW, pady=(10, 5)) self.setvar('prog-value', 71) ## time started lbl = ttk.Label(status_frm, textvariable='prog-time-started') lbl.grid(row=2, column=0, columnspan=2, sticky=EW, pady=2) self.setvar('prog-time-started', 'Started at: 14.06.2021 19:34:56') ## time elapsed lbl = ttk.Label(status_frm, textvariable='prog-time-elapsed') lbl.grid(row=3, column=0, columnspan=2, sticky=EW, pady=2) self.setvar('prog-time-elapsed', 'Elapsed: 1 sec') ## time remaining lbl = ttk.Label(status_frm, textvariable='prog-time-left') lbl.grid(row=4, column=0, columnspan=2, sticky=EW, pady=2) self.setvar('prog-time-left', 'Left: 0 sec') ## section separator sep = ttk.Separator(status_frm, bootstyle=SECONDARY) sep.grid(row=5, column=0, columnspan=2, pady=10, sticky=EW) ## stop button _func = lambda: Messagebox.ok(message='Stopping backup') btn = ttk.Button(master=status_frm, text='Stop', image='stop-backup-dark', compound=LEFT, command=_func, bootstyle=LINK) btn.grid(row=6, column=0, columnspan=2, sticky=W) ## section separator sep = ttk.Separator(status_frm, bootstyle=SECONDARY) sep.grid(row=7, column=0, columnspan=2, pady=10, sticky=EW) # current file message lbl = ttk.Label(status_frm, textvariable='current-file-msg') lbl.grid(row=8, column=0, columnspan=2, pady=2, sticky=EW) self.setvar('current-file-msg', 'Uploading: d:/test/settings.txt') # logo lbl = ttk.Label(left_panel, image='logo', style='bg.TLabel') lbl.pack(side='bottom') # right panel right_panel = ttk.Frame(self, padding=(2, 1)) right_panel.pack(side=RIGHT, fill=BOTH, expand=YES) ## file input browse_frm = ttk.Frame(right_panel) browse_frm.pack(side=TOP, fill=X, padx=2, pady=1) file_entry = ttk.Entry(browse_frm, textvariable='folder-path') file_entry.pack(side=LEFT, fill=X, expand=YES) btn = ttk.Button(master=browse_frm, image='opened-folder', bootstyle=(LINK, SECONDARY), command=self.get_directory) btn.pack(side=RIGHT) ## Treeview tv = ttk.Treeview(right_panel, show='headings', height=5) tv.configure(columns=('name', 'state', 'last-modified', 'last-run-time', 'size')) tv.column('name', width=150, stretch=True) for col in ['last-modified', 'last-run-time', 'size']: tv.column(col, stretch=False) for col in tv['columns']: tv.heading(col, text=col.title(), anchor=W) tv.pack(fill=X, pady=1) ## scrolling text output scroll_cf = CollapsingFrame(right_panel) scroll_cf.pack(fill=BOTH, expand=YES) output_container = ttk.Frame(scroll_cf, padding=1) _value = 'Log: Backing up... [Uploading file: D:/sample_file_35.txt]' self.setvar('scroll-message', _value) st = ScrolledText(output_container) st.pack(fill=BOTH, expand=YES) scroll_cf.add(output_container, textvariable='scroll-message') # seed with some sample data ## starting sample directory file_entry.insert(END, 'D:/text/myfiles/top-secret/samples/') ## treeview and backup logs for x in range(20, 35): result = choices(['Backup Up', 'Missed in Destination'])[0] st.insert(END, f'19:34:{x}\t\t Uploading: D:/file_{x}.txt\n') st.insert(END, f'19:34:{x}\t\t Upload {result}.\n') timestamp = datetime.now().strftime('%d.%m.%Y %H:%M:%S') tv.insert('', END, x, values=(f'sample_file_{x}.txt', result, timestamp, timestamp, f'{int(x // 3)} MB')) tv.selection_set(20)