def __init__(self, master, columns, column_weights=None, cnf={}, **kw): """ Construct a new multi-column listbox widget. :param master: The widget that should contain the new multi-column listbox. :param columns: Specifies what columns should be included in the new multi-column listbox. If ``columns`` is an integer, the it is the number of columns to include. If it is a list, then its length indicates the number of columns to include; and each element of the list will be used as a label for the corresponding column. :param cnf, kw: Configuration parameters for this widget. Use ``label_*`` to configure all labels; and ``listbox_*`` to configure all listboxes. E.g.: >>> mlb = MultiListbox(master, 5, label_foreground='red') """ # If columns was specified as an int, convert it to a list. if isinstance(columns, int): columns = list(range(columns)) include_labels = False else: include_labels = True if len(columns) == 0: raise ValueError("Expected at least one column") # Instance variables self._column_names = tuple(columns) self._listboxes = [] self._labels = [] # Pick a default value for column_weights, if none was specified. if column_weights is None: column_weights = [1] * len(columns) elif len(column_weights) != len(columns): raise ValueError('Expected one column_weight for each column') self._column_weights = column_weights # Configure our widgets. Frame.__init__(self, master, **self.FRAME_CONFIG) self.grid_rowconfigure(1, weight=1) for i, label in enumerate(self._column_names): self.grid_columnconfigure(i, weight=column_weights[i]) # Create a label for the column if include_labels: l = Label(self, text=label, **self.LABEL_CONFIG) self._labels.append(l) l.grid(column=i, row=0, sticky='news', padx=0, pady=0) l.column_index = i # Create a listbox for the column lb = Listbox(self, **self.LISTBOX_CONFIG) self._listboxes.append(lb) lb.grid(column=i, row=1, sticky='news', padx=0, pady=0) lb.column_index = i # Clicking or dragging selects: lb.bind('<Button-1>', self._select) lb.bind('<B1-Motion>', self._select) # Scroll whell scrolls: lb.bind('<Button-4>', lambda e: self._scroll(-1)) lb.bind('<Button-5>', lambda e: self._scroll(+1)) lb.bind('<MouseWheel>', lambda e: self._scroll(e.delta)) # Button 2 can be used to scan: lb.bind('<Button-2>', lambda e: self.scan_mark(e.x, e.y)) lb.bind('<B2-Motion>', lambda e: self.scan_dragto(e.x, e.y)) # Dragging outside the window has no effect (diable # the default listbox behavior, which scrolls): lb.bind('<B1-Leave>', lambda e: 'break') # Columns can be resized by dragging them: l.bind('<Button-1>', self._resize_column) # Columns can be resized by dragging them. (This binding is # used if they click on the grid between columns:) self.bind('<Button-1>', self._resize_column) # Set up key bindings for the widget: self.bind('<Up>', lambda e: self.select(delta=-1)) self.bind('<Down>', lambda e: self.select(delta=1)) self.bind('<Prior>', lambda e: self.select(delta=-self._pagesize())) self.bind('<Next>', lambda e: self.select(delta=self._pagesize())) # Configuration customizations self.configure(cnf, **kw)
class MainUI(object): def __init__(self, parent, root): self.parent = parent self.root = root self.selectedStatus = False # Widget Initialization self._listbox = Listbox( parent, font="{Segoe UI} 10", height=0, selectmode="extended", state="normal", cursor="hand2", exportselection=False, ) self._listbox_scrollbar = AutoScrollbar(self._listbox) self._lbl_help = Label( parent, font="{Segoe UI Light} 12 bold", text="Hold [Ctrl] to select multiple items", ) self._label_header = Label( parent, font="{Segoe UI} 16 bold", text="Playback items available for removal", ) self._label_actions = Label( parent, font="{Segoe UI} 14 bold", text="Actions", ) self._label_info = Label( parent, font="{Segoe UI} 14 bold", text="Info", ) self._btnRefresh = Button( parent, font="{Segoe UI} 12 bold", text="Refresh", ) self._btnRemoveSelected = Button( parent, font="{Segoe UI} 12 bold", wraplength=175, text="Remove Selected", ) self._btnSelectDeselectAll = Button( parent, font="{Segoe UI} 12 bold", wraplength=175, text="Select / Deselect All", ) self._btnStopCurrentlyPlaying = Button( parent, font="{Segoe UI} 12 bold", # wraplength=80, text="Stop Currently Playing", ) self._btnLogin = Button( parent, font="{Segoe UI} 12 bold", text="Login/Auth", ) self._lbl_ID = Label( parent, font="{Segoe UI Light} 12 bold", text="ID:", ) self._lbl_PausedAt = Label( parent, font="{Segoe UI Light} 12 bold", text="Paused At:", ) self._lbl_Progress = Label( parent, font="{Segoe UI Light} 12 bold", text="Progress:", ) self.lbl_showName = StringVar(value="Show:") self._lbl_Show = Label( parent, font="{Segoe UI Light} 12 bold", textvariable=self.lbl_showName, ) self.lbl_season = StringVar(value="Season:") self._lbl_Season = Label( parent, font="{Segoe UI Light} 12 bold", textvariable=self.lbl_season, ) self.lbl_episode = StringVar(value="Episode:") self._lbl_Episode = Label( parent, font="{Segoe UI Light} 12 bold", textvariable=self.lbl_episode, ) self.lbl_episodeTitle = StringVar(value="Title:") self._lbl_Title = Label( parent, font="{Segoe UI Light} 12 bold", textvariable=self.lbl_episodeTitle, ) self.txt_ID = StringVar() self._txtID = Entry( parent, font="{Segoe UI Light} 12", readonlybackground="#ffffff", relief="flat", state="readonly", textvariable=self.txt_ID, width=0, ) self.txt_paused_at = StringVar() self._txtPausedAt = Entry( parent, font="{Segoe UI Light} 12", readonlybackground="#ffffff", relief="flat", state="readonly", textvariable=self.txt_paused_at, width=0, ) self.txt_progress = StringVar() self._txtProgress = Entry( parent, font="{Segoe UI Light} 12", readonlybackground="#ffffff", relief="flat", state="readonly", textvariable=self.txt_progress, width=0, ) self.txt_showName = StringVar() self._txtShowName = Entry( parent, font="{Segoe UI Light} 12", readonlybackground="#ffffff", relief="flat", state="readonly", textvariable=self.txt_showName, width=0, ) self.txt_season = StringVar() self._txtSeason = Entry( parent, font="{Segoe UI Light} 12", readonlybackground="#ffffff", relief="flat", state="readonly", textvariable=self.txt_season, width=0, ) self.txt_episode = StringVar() self._txtEpisode = Entry( parent, font="{Segoe UI Light} 12", readonlybackground="#ffffff", relief="flat", state="readonly", textvariable=self.txt_episode, width=0, ) self.txt_title = StringVar() self._txtTitle = Entry( parent, font="{Segoe UI Light} 12", readonlybackground="#ffffff", relief="flat", state="readonly", textvariable=self.txt_title, width=0, ) self.lbl_loggedin = StringVar(value="") self._lbl_loggedin = Label( parent, font="{Segoe UI Light} 12 bold", textvariable=self.lbl_loggedin, ) self._lbl_version = Label( parent, font="{Segoe UI Light} 10 bold", text="v%s" % app.__version__, foreground="blue", cursor="hand2", ) # widget commands self._listbox.bind('<<ListboxSelect>>', self._listbox_onselect) self._listbox.config(yscrollcommand=self._listbox_scrollbar.set) self._listbox_scrollbar.config(orient='vertical', command=self._listbox.yview) self._btnRefresh.configure(command=self._btn_refresh_command) self._btnRemoveSelected.configure( command=self._btn_remove_selected_command) self._btnSelectDeselectAll.configure( command=self._btn_toggle_selection_command) self._btnStopCurrentlyPlaying.configure( command=self._btn_stop_currently_playing) self._btnLogin.configure(command=self._btn_login_command) self._lbl_version.bind('<Button-1>', self._open_repo) # Geometry Management self._listbox.grid(in_=parent, column=4, row=2, columnspan=1, ipadx=0, ipady=0, padx=5, pady=5, rowspan=10, sticky="nsew") self._listbox.columnconfigure(0, weight=1) self._listbox.rowconfigure(0, weight=1) self._listbox_scrollbar.grid(column=4, rowspan=10, sticky="ns") self._lbl_help.grid(in_=parent, column=4, row=11, ipadx=0, ipady=0, padx=5, pady=5, sticky="nsew") self._label_header.grid(in_=parent, column=4, row=1, columnspan=1, ipadx=0, ipady=0, padx=0, pady=0, rowspan=1, sticky="nsew") self._label_actions.grid(in_=parent, column=1, row=9, columnspan=3, ipadx=0, ipady=0, padx=0, pady=0, rowspan=1, sticky="nsew") self._label_info.grid(in_=parent, column=1, row=1, columnspan=3, ipadx=0, ipady=0, padx=0, pady=0, rowspan=1, sticky="nsew") self._btnRefresh.grid(in_=parent, column=1, row=10, columnspan=1, ipadx=0, ipady=0, padx=0, pady=0, rowspan=1, sticky="") self._btnRemoveSelected.grid(in_=parent, column=2, row=10, columnspan=1, ipadx=0, ipady=0, padx=0, pady=0, rowspan=1, sticky="") self._btnSelectDeselectAll.grid(in_=parent, column=3, row=10, columnspan=1, ipadx=0, ipady=0, padx=0, pady=0, rowspan=1, sticky="") self._btnStopCurrentlyPlaying.grid(in_=parent, column=2, row=11, columnspan=2, ipadx=0, ipady=0, padx=5, pady=0, rowspan=1, sticky="ne") self._btnLogin.grid(in_=parent, column=2, row=11, columnspan=1, ipadx=0, ipady=0, padx=0, pady=0, rowspan=1, sticky="") # Hide the login button at first self._btnLogin.grid_remove() self._lbl_ID.grid(in_=parent, column=1, row=2, columnspan=1, ipadx=0, ipady=0, padx=0, pady=7, rowspan=1, sticky="nsew") self._lbl_PausedAt.grid(in_=parent, column=1, row=3, columnspan=1, ipadx=0, ipady=0, padx=0, pady=7, rowspan=1, sticky="nsew") self._lbl_Progress.grid(in_=parent, column=1, row=4, columnspan=1, ipadx=0, ipady=0, padx=0, pady=7, rowspan=1, sticky="nsew") self._lbl_Show.grid(in_=parent, column=1, row=5, columnspan=1, ipadx=0, ipady=0, padx=0, pady=7, rowspan=1, sticky="nsew") self._lbl_Season.grid(in_=parent, column=1, row=6, columnspan=1, ipadx=0, ipady=0, padx=0, pady=7, rowspan=1, sticky="nsew") self._lbl_Episode.grid(in_=parent, column=1, row=7, columnspan=1, ipadx=0, ipady=0, padx=0, pady=7, rowspan=1, sticky="nsew") self._lbl_Title.grid(in_=parent, column=1, row=8, columnspan=1, ipadx=0, ipady=0, padx=0, pady=7, rowspan=1, sticky="nsew") self._txtID.grid(in_=parent, column=2, row=2, columnspan=2, ipadx=0, ipady=0, padx=5, pady=7, rowspan=1, sticky="nsew") self._txtPausedAt.grid(in_=parent, column=2, row=3, columnspan=2, ipadx=0, ipady=0, padx=5, pady=7, rowspan=1, sticky="nsew") self._txtProgress.grid(in_=parent, column=2, row=4, columnspan=2, ipadx=0, ipady=0, padx=5, pady=7, rowspan=1, sticky="nsew") self._txtShowName.grid(in_=parent, column=2, row=5, columnspan=2, ipadx=0, ipady=0, padx=5, pady=7, rowspan=1, sticky="nsew") self._txtSeason.grid(in_=parent, column=2, row=6, columnspan=2, ipadx=0, ipady=0, padx=5, pady=7, rowspan=1, sticky="nsew") self._txtEpisode.grid(in_=parent, column=2, row=7, columnspan=2, ipadx=0, ipady=0, padx=5, pady=7, rowspan=1, sticky="nsew") self._txtTitle.grid(in_=parent, column=2, row=8, columnspan=2, ipadx=0, ipady=0, padx=5, pady=7, rowspan=1, sticky="nsew") self._lbl_loggedin.grid(in_=parent, column=1, row=11, columnspan=2, ipadx=0, ipady=0, padx=5, pady=5, rowspan=1, sticky="sw") self._lbl_version.grid(in_=parent, column=1, row=1, columnspan=1, ipadx=0, ipady=0, padx=0, pady=0, rowspan=1, sticky="nw") # Resize Behavior parent.resizable(False, False) parent.grid_rowconfigure(1, weight=0, minsize=30, pad=0) parent.grid_rowconfigure(2, weight=0, minsize=30, pad=0) parent.grid_rowconfigure(3, weight=0, minsize=30, pad=0) parent.grid_rowconfigure(4, weight=0, minsize=30, pad=0) parent.grid_rowconfigure(5, weight=0, minsize=30, pad=0) parent.grid_rowconfigure(6, weight=0, minsize=30, pad=0) parent.grid_rowconfigure(7, weight=0, minsize=30, pad=0) parent.grid_rowconfigure(8, weight=0, minsize=30, pad=0) parent.grid_rowconfigure(9, weight=0, minsize=30, pad=0) parent.grid_rowconfigure(10, weight=0, minsize=60, pad=0) parent.grid_rowconfigure(11, weight=0, minsize=30, pad=5) parent.grid_columnconfigure(1, weight=0, minsize=70, pad=5) parent.grid_columnconfigure(2, weight=0, minsize=175, pad=0) parent.grid_columnconfigure(3, weight=0, minsize=175, pad=0) parent.grid_columnconfigure(4, weight=0, minsize=400, pad=0)