Ejemplo n.º 1
0
def test_scrollable_frame():
    root = tk.Tk()

    # the row expands
    root.grid_rowconfigure(0, weight=1)
    # the first column expands
    root.grid_columnconfigure(0, weight=1)
    # the second column is fixed (set only for clarity)
    root.grid_columnconfigure(1, weight=0)

    # create the ScrollableFrame, with a set width
    scroll_width = 200
    scroll = ScrollableFrame(root, scroll_width=scroll_width)
    scroll.grid(row=0, column=1, sticky="ns")

    # the main windows is here, this does expand 'ew'
    filler = tk.Frame(root, bg="blue", width=100)
    filler.grid(row=0, column=0, sticky="nsew")

    labels = []
    for i in range(30):
        new_label = tk.Label(
            scroll.scroll_frame,
            text=f"Label created at row {i}",
            background="orange",
        )
        new_label.grid(row=i, column=0, sticky="ew")

        # add bindings for mouse scrolling
        new_label.bind("<4>", scroll.on_list_scroll)
        new_label.bind("<5>", scroll.on_list_scroll)
        new_label.bind("<MouseWheel>", scroll.on_list_scroll)

        labels.append(new_label)

    # if the labels do not cover the entire canvas, some of these might work
    #  scroll.bind("<4>", scroll.on_list_scroll)
    #  scroll.bind("<5>", scroll.on_list_scroll)
    #  scroll.bind("<MouseWheel>", scroll.on_list_scroll)

    #  scroll.scroll_canvas.bind("<4>", scroll.on_list_scroll)
    #  scroll.scroll_canvas.bind("<5>", scroll.on_list_scroll)
    #  scroll.scroll_canvas.bind("<MouseWheel>", scroll.on_list_scroll)

    #  scroll.scroll_frame.bind("<4>", scroll.on_list_scroll)
    #  scroll.scroll_frame.bind("<5>", scroll.on_list_scroll)
    #  scroll.scroll_frame.bind("<MouseWheel>", scroll.on_list_scroll)

    root.mainloop()
Ejemplo n.º 2
0
    def __init__(self, optimizer, parent, controller):
        tk.Frame.__init__(self, parent)
        #prepares player dataframe used throughout frame
        self.player_master = optimizer.player_master.filter(
            ['position', 'name', 'team', 'salary', 'ppg_projection', 'value'])

        #declares scrollable frame for excl and lock buttons
        #borrows from class found online
        player_frame = ScrollableFrame(self, 420, 400)
        player_frame.grid(column=0, row=1, padx=10, pady=(0, 10), rowspan=3)

        #adds excl and lock labels
        tk.Label(self, text='Excl | Lock').grid(column=0,
                                                row=0,
                                                sticky='sw',
                                                padx=4,
                                                pady=(10, 0))

        #creates and places lock and exclusion buttons
        self.excl_buttons = {}
        self.lock_buttons = {}
        self.excl_vars = {}
        self.lock_vars = {}
        for i, player in enumerate(self.player_master.index):
            #excl buttons
            self.excl_vars[player] = tk.IntVar()
            self.excl_vars[player].set(0)
            self.excl_buttons[player] = ttk.Checkbutton(
                player_frame.scrollable_frame,
                variable=self.excl_vars[player],
                command=lambda x=player: self.toggle_excl(x))
            self.excl_buttons[player].grid(row=i, column=0)

            #lock buttons
            self.lock_vars[player] = tk.IntVar()
            self.lock_vars[player].set(0)
            self.lock_buttons[player] = ttk.Checkbutton(
                player_frame.scrollable_frame,
                variable=self.lock_vars[player],
                command=lambda x=player: self.toggle_lock(x))
            self.lock_buttons[player].grid(row=i, column=1)

        #adds labels to scrollframe with player info
        player_labels = {}
        self.player_text = self.player_master.to_string(
            header=False, index=False, justify='right').splitlines()
        for i in range(len(self.player_master.index)):
            player_labels[i] = tk.Label(player_frame.scrollable_frame,
                                        text=self.player_text[i],
                                        anchor='w',
                                        font=('Consolas', 11),
                                        bg='white')
            player_labels[i].grid(column=3, row=i, sticky='w')

        #adds text box for exluded players
        tk.Label(self, text="Excluded:",
                 font=('Calibri', 11)).grid(row=0, column=1, sticky='sw')
        self.excl_text = tk.Text(self, height=10, width=50, state=tk.DISABLED)
        self.excl_text.grid(row=1, column=1, sticky='ns', padx=(0, 10))
        e_scroll = ttk.Scrollbar(self, command=self.excl_text.yview)
        e_scroll.grid(row=1, column=1, sticky='nse', padx=(0, 10))
        self.excl_text['yscrollcommand'] = e_scroll.set

        #adds text box for locked players
        tk.Label(self, text="Locked:", font=('Calibri', 11)).grid(row=2,
                                                                  column=1,
                                                                  sticky='sw')
        self.lock_text = tk.Text(self, height=10, width=50, state=tk.DISABLED)
        self.lock_text.grid(row=3,
                            column=1,
                            sticky='ns',
                            pady=(0, 10),
                            padx=(0, 10))
        l_scroll = ttk.Scrollbar(self, command=self.lock_text.yview)
        l_scroll.grid(row=3,
                      column=1,
                      sticky='nse',
                      pady=(0, 10),
                      padx=(0, 10))
        self.lock_text['yscrollcommand'] = l_scroll.set

        #dataframes to be converted to string in toggle functions
        self.excl_df = pd.DataFrame()
        self.lock_df = pd.DataFrame()
Ejemplo n.º 3
0
class SelectionListFrame(ThumbButtonList):
    def __init__(self, parent, name, palette, sidebar_width, *args, **kwargs):
        """Do things in build_selection_list_frame"""
        logg = logging.getLogger(f"c.{__class__.__name__}.init")
        logg.info("Start init")

        self.name = name
        self.palette = palette
        self.sidebar_width = sidebar_width

        # frame background color
        self.back_col = self.palette.get_colors(f"background.{self.name}")

        # header background color
        self.back_col_header = (
            self.palette.get_colors("background.header.selection_list"), )

        # ScrollableFrame colors
        self.back_col_scrollable = self.palette.get_colors(
            "background.scrollable.selection_list")
        self.hover_col_scrollable = self.palette.get_colors(
            "hover.scrollable.selection_list")
        self.slider_col_scrollable = self.palette.get_colors(
            "slider.scrollable.selection_list")

        # ThumbButton colors
        self.back_col_thumbbtn = self.palette.get_colors(
            "background.thumbbtn.selection_list")
        self.hover_back_col_thumbbtn = self.palette.get_colors(
            "hover.thumbbtn.selection_list")
        self.back_col_bis_thumbbtn = self.palette.get_colors(
            "backgroundbis.thumbbtn.selection_list")

        super().__init__(parent, background=self.back_col, *args, **kwargs)

        self.selection_list_frame_header = tk.Label(
            self, text="Selection list:", background=self.back_col_header)

        # ScrollableFrame that holds the ThumbButtons
        self.selection_list_scrollable = ScrollableFrame(
            self,
            scroll_width=self.sidebar_width,
            back_col=self.back_col_scrollable,
            hover_back_col=self.hover_col_scrollable,
            slider_col=self.slider_col_scrollable,
        )

        # setup grid in selection_list_frame
        self.grid_rowconfigure(1, weight=1)
        self.grid_columnconfigure(0, weight=1)

        # grid static elements
        self.selection_list_frame_header.grid(row=0, column=0, sticky="ew")
        self.selection_list_scrollable.grid(row=1, column=0, sticky="nsew")

        # dicts for runtime elements
        self.selection_list_thumbbtn = {}

    def update_selection_list(self, selection_list_info):
        """Receives a dict of PhotoInfo object and creates ThumbButton

        There is also info on whether the pic is still selected
        selection_list_info = { pic : (PhotoInfo, is_selected) }
        """
        logg = logging.getLogger(
            f"c.{__class__.__name__}.update_selection_list")
        #  logg.setLevel("TRACE")
        logg.info("Updating selection_list ThumbButtons")

        for pic in self.selection_list_thumbbtn:
            self.selection_list_thumbbtn[pic].grid_forget()

        for ri, pic in enumerate(selection_list_info):
            # extract values
            photo_info = selection_list_info[pic][0]
            is_selected = selection_list_info[pic][1]

            # create the new ThumbButton
            if pic not in self.selection_list_thumbbtn:
                self.selection_list_thumbbtn[pic] = ThumbButton(
                    self.selection_list_scrollable.scroll_frame,
                    photo_info,
                    back_col=self.back_col_thumbbtn,
                    hover_back_col=self.hover_back_col_thumbbtn,
                    back_col_bis=self.back_col_bis_thumbbtn,
                )

                # bind enter/leave event to highlight
                self.selection_list_thumbbtn[pic].bind("<Enter>",
                                                       self.on_thumbbtn_enter)
                self.selection_list_thumbbtn[pic].bind("<Leave>",
                                                       self.on_thumbbtn_leave)

                # bind scroll function to ThumbButton elements
                self.selection_list_thumbbtn[pic].register_scroll_func(
                    self.selection_list_scrollable.on_list_scroll)

                # add event for doubleclick
                self.selection_list_thumbbtn[pic].bind_doubleclick(
                    self.on_selection_list_doubleclick)

            # set selected photo to FIRST, de-selected to BIS color_mode
            if is_selected:
                self.selection_list_thumbbtn[pic].set_back_col_mode("FIRST")
            else:
                self.selection_list_thumbbtn[pic].set_back_col_mode("BIS")

            self.selection_list_thumbbtn[pic].grid(row=ri,
                                                   column=0,
                                                   sticky="ew")

    def on_selection_list_doubleclick(self, event):
        logg = logging.getLogger(
            f"c.{__class__.__name__}.on_selection_list_doubleclick")
        #  logg.setLevel("TRACE")
        logg.debug("Doublecliked something in selection list")
        logg.trace(
            f"Event {event} fired by {event.widget} master {event.widget.master}"
        )
        self.selection_doubleclicked = event.widget.master.photo_info.photo_name_full
        logg.trace(f"selection_doubleclicked {self.selection_doubleclicked}")
        self.event_generate("<<thumbbtn_selection_doubleclick>>")
Ejemplo n.º 4
0
class PhotoListFrame(ThumbButtonList):
    def __init__(self, parent, name, palette, sidebar_width, *args, **kwargs):
        """Do things in build_photo_list_frame"""
        logg = logging.getLogger(f"c.{__class__.__name__}.init")
        logg.info("Start init")

        self.name = name
        self.palette = palette

        self.back_col = self.palette.get_colors(f"background.{self.name}")

        self.back_col_header = (
            self.palette.get_colors("background.header.photo_list"), )

        self.back_col_scrollable = self.palette.get_colors(
            "background.scrollable.photo_list")
        self.hover_col_scrollable = self.palette.get_colors(
            "hover.scrollable.photo_list")
        self.slider_col_scrollable = self.palette.get_colors(
            "slider.scrollable.photo_list")

        self.back_col_thumbbtn = self.palette.get_colors(
            "background.thumbbtn.photo_list")
        self.hover_back_col_thumbbtn = self.palette.get_colors(
            "hover.thumbbtn.photo_list")
        self.back_col_bis_thumbbtn = self.palette.get_colors(
            "backgroundbis.thumbbtn.photo_list")

        super().__init__(parent, background=self.back_col, *args, **kwargs)

        # save width of sidebar, needed to explicitly set ScrollableFrame
        self.sidebar_width = sidebar_width

        self.photo_list_frame_header = tk.Label(
            self, text="Photo list:", background=self.back_col_header)

        # TODO reimplement the whole thing: manually change the TB you show
        # ask for new PhotoInfo when needed, so that they do not have to be all
        # loaded; bind configure of photo_list_frame to compute how many TB
        # have to be available; bind scroll (from the Scrollbar as well?) to a
        # call in the model to update the list of TB, and show just them
        # this is mainly needed because this frame can only hold a puny 1000ish
        # photo list; that's like one week of vacation.

        # ScrollableFrame that holds the ThumbButtons
        self.photo_list_scrollable = ScrollableFrame(
            self,
            scroll_width=self.sidebar_width,
            back_col=self.back_col_scrollable,
            hover_back_col=self.hover_col_scrollable,
            slider_col=self.slider_col_scrollable,
        )

        # setup grid in photo_list_frame (this widget)
        self.grid_rowconfigure(1, weight=1)
        self.grid_columnconfigure(0, weight=1)

        # grid static elements
        self.photo_list_frame_header.grid(row=0, column=0, sticky="ew")
        self.photo_list_scrollable.grid(row=1, column=0, sticky="nsew")

        # dicts for runtime elements
        self.photo_list_thumbbtn = {}
        self.current_photo_prim = ""

    def update_photo_list(self, photo_list_info):
        """Receives a dict of PhotoInfo object and creates ThumbButton

        photo_list_info = { pic : PhotoInfo }
        """
        logg = logging.getLogger(f"c.{__class__.__name__}.update_photo_list")
        #  logg.setLevel("TRACE")
        logg.info("Updating photo_list ThumbButton")

        for pic in self.photo_list_thumbbtn:
            self.photo_list_thumbbtn[pic].grid_forget()

        for ri, pic in enumerate(photo_list_info):
            # create the new ThumbButton
            if pic not in self.photo_list_thumbbtn:
                self.photo_list_thumbbtn[pic] = ThumbButton(
                    self.photo_list_scrollable.scroll_frame,
                    photo_list_info[pic],
                    back_col=self.back_col_thumbbtn,
                    hover_back_col=self.hover_back_col_thumbbtn,
                    back_col_bis=self.back_col_bis_thumbbtn,
                )

                # bind enter/leave event to highlight
                self.photo_list_thumbbtn[pic].bind("<Enter>",
                                                   self.on_thumbbtn_enter)
                self.photo_list_thumbbtn[pic].bind("<Leave>",
                                                   self.on_thumbbtn_leave)

                # bind scroll function to ThumbButton elements
                self.photo_list_thumbbtn[pic].register_scroll_func(
                    self.photo_list_scrollable.on_list_scroll)

                # add event for doubleclick
                self.photo_list_thumbbtn[pic].bind_doubleclick(
                    self.on_photo_list_doubleclick)

            # highlight current photo primary
            if pic == self.current_photo_prim:
                logg.trace(f"Setting color mode BIS for '{pic}' ThumbButton")
                self.photo_list_thumbbtn[pic].set_back_col_mode("BIS")
            else:
                self.photo_list_thumbbtn[pic].set_back_col_mode("FIRST")

            # grid the ThumbButton
            self.photo_list_thumbbtn[pic].grid(row=ri, column=0, sticky="ew")

        logg.trace(f"Loaded thbtn {self.photo_list_thumbbtn.keys()}")

    def on_photo_list_doubleclick(self, event):
        """Handle double clicks on photo list, go to that pic

        MAYBE better binding of this event in ThumbButton, bind the double
        click to some virtual events raised, then bind the virtual event on the
        ThumbButton top widget, so that the callback can access event.widget
        directly on the ThumbButton, instead of event.widget.master
        """
        logg = logging.getLogger(
            f"c.{__class__.__name__}.on_photo_list_doubleclick")
        #  logg.setLevel("TRACE")
        logg.debug("Doublecliked something")
        logg.trace(
            f"Event {event} fired by {event.widget} master {event.widget.master}"
        )
        self.photo_doubleclicked = event.widget.master.photo_info.photo_name_full
        logg.trace(f"photo_doubleclicked {self.photo_doubleclicked}")
        self.event_generate("<<thumbbtn_photo_doubleclick>>")

    def update_current_photo_prim(self, pic):
        logg = logging.getLogger(
            f"c.{__class__.__name__}.update_current_photo_prim")
        #  logg.setLevel("TRACE")
        logg.trace("Update current_photo_prim")
        if self.current_photo_prim != "":
            self.photo_list_thumbbtn[
                self.current_photo_prim].set_back_col_mode("FIRST")
        self.photo_list_thumbbtn[pic].set_back_col_mode("BIS")
        self.current_photo_prim = pic
Ejemplo n.º 5
0
class Program(tk.Frame):
    def __init__(self, master, on_run, camera_direction, **kwargs):
        tk.Frame.__init__(self, master, **kwargs)
        self.on_run = on_run
        self.camera_direction = camera_direction
        self.cycles = []
        self.create_widgets()

    def create_widgets(self):
        self.cycles_frame = ScrollableFrame(self, background=BG)
        self.cycles_list = tk.Frame(
            self.cycles_frame.scrollable_frame, background=BG)
        self.cycles_list.grid(row=0, column=0, sticky=tk.E+tk.W)
        self.cycles_list.columnconfigure(0, weight=1)
        cycle = Cycle(self.cycles_list, borderwidth=1, relief='raised')
        self.cycles.append(cycle)
        cycle.grid(row=0, column=0, pady=(0, 16), sticky=tk.E+tk.W)

        cycles_buttons = tk.Frame(
            self.cycles_frame.scrollable_frame, background=BG)
        cycles_buttons.grid(row=1, column=0, pady=(16, 24))
        tk.Button(
            cycles_buttons, text='+ Step', highlightbackground=BG,
            command=self.add_step,
        ).grid(row=0, column=0)
        self.run_button = tk.Button(
            cycles_buttons, text='Run Program', highlightbackground=BG,
            font=tkFont.Font(weight='bold'),
            command=self.run_program)
        self.run_button.grid(row=0, column=1, ipady=6)

        self.cycles_frame.grid(row=0, column=0, sticky=tk.N+tk.E+tk.S+tk.W)
        self.cycles_frame.scrollable_frame.columnconfigure(0, weight=1)

        self.columnconfigure(0, weight=1)
        self.rowconfigure(0, weight=1)

    def add_step(self):
        cycle_index = len(self.cycles)
        cycle = Cycle(
            self.cycles_list, cycle_index, borderwidth=1, relief='raised')
        cycle.grid(row=cycle_index, column=0, pady=(0, 16), sticky=tk.E+tk.W)
        rm = tk.Label(
            cycle, text='✕', foreground='#833', width=2, justify=tk.CENTER)
        rm.place(relx=1, anchor=tk.NE)
        rm.bind('<Button-1>', lambda _: self.remove_step(cycle))
        self.cycles.append(cycle)

    def remove_step(self, cycle):
        self.cycles = [a for a in self.cycles if a is not cycle]
        cycle.destroy()
        for i, cycle in enumerate(self.cycles):
            cycle.grid(row=i, column=0, sticky=tk.E+tk.W)

    def run_program(self):
        program = []
        for cycle in self.cycles:
            for _ in range(int(cycle.cycles_count.get())):
                for a in cycle.actions:
                    n = int(a.action.frames.get())
                    if a.action.name == 'Camera':
                        if self.camera_direction.get() == 'rw':
                            n *= -1
                        program.append((n, 0))
                    else:
                        if a.action.direction.get() == 'rw':
                            n *= -1
                        program.append((0, n))
        self.on_run(program)

    def disable(self):
        self.run_button.config(state=tk.DISABLED, text='Program running...')

    def enable(self):
        self.run_button.config(state=tk.NORMAL, text='Run program')