How to set an individual mouse scroll on two different canvases that are connected to separate frames but the frames are one on top of eachother?

43 views Asked by At

I know the title is a bit difficult to understand so let me explain it better here:

I have a class that is inheriting a selection that I've made in a previous window, now that class has a couple of methods(functions) inside it, one of which is a method that creates three frames on a certain part of my root frame. Within that method I'm also creating two instances of two different classes which contain all of the necessary information which I want to place in 2 of the 3 frames described above.

What I'm attempting to achieve is to have 2 frames one of top of another. Those frames will be accordingly called to show on top of eachother per 2 buttons that I have added in my code. Each of those frames contains a canvas that also contains a bunch of tables and I am attempting to scroll through it all in order to be able to better present the tables and the data within those tables.

My problem is that whenever I set the scroll with a "bind_all" it will scroll only on the frame set to show first, even if I click the button that swaps the frame (and it does successfully swap it), it will still scroll the other frame in the background (as per my print statements). However, if I set it to "bind" only I get the results which I'm looking for but the problem is that I cannot scroll on top of all the widgets here, I can only scroll on a thin vertical area on the left side of each of the frames.

Code in question:

import tkinter as tk
from tkinter import Listbox, messagebox, StringVar, ttk
from PIL import Image, ImageTk

class Coupler15(tk.Toplevel):
    def __init__(self, selected_items):
        super().__init__()
        self.configure_window()
        self.create_basics_frame(selected_items)
        self.create_connection_frame()
        self.create_measurement_frame()

    def configure_window(self):
        self.configure(background='light grey')
        screen_width = self.winfo_screenwidth()
        screen_height = self.winfo_screenheight()
        self.geometry(f"{screen_width}x{screen_height}+0+0")
        self.protocol("WM_DELETE_WINDOW", self.on_closing)

    def create_basics_frame(self, selected_items):
        # Basics frame, not necessary info

    def create_connection_frame(self):
        # Connection frame, not necessary info

    def create_measurement_frame(self):
        
        options_frame=tk.Frame(self, relief="raised", bg="light grey", bd=2, height=35, width=208)
        
        button_30kV=tk.Button(options_frame, text='30kV range', font=("Helvetica", 10), command=self.show_30kV_page)
        button_30kV.place(x=0, y=0, width=100)
        button_30kV.configure(background="light grey")
        button_30kV.configure(foreground="black")
        button_30kV.configure(activebackground="dark grey")
        button_30kV.configure(bd=3)
        
        button_6kV=tk.Button(options_frame, text='6kV range', font=("Helvetica", 10), command=self.show_6kV_page)
        button_6kV.place(x=102, y=0, width=100)
        button_6kV.configure(background="light grey")
        button_6kV.configure(foreground="black")
        button_6kV.configure(activebackground="dark grey")
        button_6kV.configure(bd=3)
        
        options_frame.pack(pady=5)
        options_frame.place(x=310, y=5)

        self._6kV_frame = tk.Frame(self, relief="raised", bg="light grey", bd=2, height=750, width=1360)
        self._6kV_frame.pack()
        self._6kV_frame.place(x=310, y=40)

        self._30kV_frame = tk.Frame(self, relief="raised", bg="light grey", bd=2, height=750, width=1360)
        self._30kV_frame.pack()
        self._30kV_frame.place(x=310, y=40)

        for i in [self, self._30kV_frame, self._6kV_frame, options_frame]:
            i.configure(background="light grey")

        self._30kV_page=_30kV_page(parent=self, _30kV_frame=self._30kV_frame)
        self._6kV_page=_6kV_page(parent=self, _6kV_frame=self._6kV_frame)

    def show_30kV_page(self):
        self._30kV_frame.tkraise()
    
    def show_6kV_page(self):
        self._6kV_frame.tkraise()

class _30kV_page(tk.Frame):
    def __init__(self, parent, _30kV_frame):
        super().__init__(parent)
        
        self._30kV_canvas=tk.Canvas(_30kV_frame, bg="light grey")
        _30kV_scrollbar=ttk.Scrollbar(_30kV_frame, orient="vertical", command=self._30kV_canvas.yview)
        _30kV_scrollable_frame=tk.Frame(self._30kV_canvas, bg="light grey")
        _30kV_scrollable_frame.bind("<Configure>", lambda e: self._30kV_canvas.configure(scrollregion=self._30kV_canvas.bbox("all")))
        self._30kV_canvas.create_window((50,50), window=_30kV_scrollable_frame, anchor="nw")
        self._30kV_canvas.configure(yscrollcommand=_30kV_scrollbar.set)
        self._30kV_canvas.config(height=750, width=1345)
        self._30kV_canvas.bind("<MouseWheel>", self._30kV_mouse_wheel_movement)
        self._30kV_canvas.pack(side="left", fill="both", expand=True)
        _30kV_scrollbar.pack(side="right", fill="y")

        _30kV_frame_label=tk.Label(_30kV_scrollable_frame, text="3. Measurements", bg="light grey", font=("Helvetica", 9))
        _30kV_frame_label.grid(row=0, column=0, sticky="nw", pady=10)

        table_labels=["Index", "Upeak [kV]", "+Upeak/1,41 [kV]", "-Upeak/1,41 [kV]", "f [Hz]", "Temp [°C]", "Uist CC100ref", "Umess Prüfung", "Diff. [%]", "crest factor", "Divider"]

        _15kV=tk.Label(_30kV_scrollable_frame, text="15kV", bg="light grey", font=("Helvetica", 10))
        _15kV.grid(row=1, column=0, sticky="nw", pady=20)
        table_frame_15=tk.Frame(_30kV_scrollable_frame, relief="sunken", bg="light grey", borderwidth=2, height=730, width=1345)
        table_frame_15.grid(row=1, column=0, pady=50)
        table_15 = self.create_table(table_frame_15, 11, 11, table_labels)

        _13kV=tk.Label(_30kV_scrollable_frame, text="13kV", bg="light grey", font=("Helvetica", 10))
        _13kV.grid(row=2, column=0, sticky="nw", pady=10)
        table_frame_13=tk.Frame(_30kV_scrollable_frame, relief="sunken", bg="light grey", borderwidth=2, height=730, width=1345)
        table_frame_13.grid(row=2, column=0, pady= 40)
        table_13 = self.create_table(table_frame_13, 11, 11, table_labels)

        _11kV=tk.Label(_30kV_scrollable_frame, text="11kV", bg="light grey", font=("Helvetica", 10))
        _11kV.grid(row=3, column=0, sticky="nw", pady=10)
        table_frame_11=tk.Frame(_30kV_scrollable_frame, relief="sunken", bg="light grey", borderwidth=2, height=730, width=1345)
        table_frame_11.grid(row=3, column=0, pady=40)
        table_11 = self.create_table(table_frame_11, 11, 11, table_labels)

        _9kV=tk.Label(_30kV_scrollable_frame, text="9kV", bg="light grey", font=("Helvetica", 10))
        _9kV.grid(row=4, column=0, sticky="nw", pady=10)
        table_frame_9=tk.Frame(_30kV_scrollable_frame, relief="sunken", bg="light grey", borderwidth=2, height=730, width=1345)
        table_frame_9.grid(row=4, column=0, pady=40)
        table_9 = self.create_table(table_frame_9, 11, 11, table_labels)

        _7kV=tk.Label(_30kV_scrollable_frame, text="7kV", bg="light grey", font=("Helvetica", 10))
        _7kV.grid(row=5, column=0, sticky="nw", pady=10)
        table_frame_7=tk.Frame(_30kV_scrollable_frame, relief="sunken", bg="light grey", borderwidth=2, height=730, width=1345)
        table_frame_7.grid(row=5, column=0, pady=40)
        table_7 = self.create_table(table_frame_7, 11, 11, table_labels)

        _5kV=tk.Label(_30kV_scrollable_frame, text="5kV", bg="light grey", font=("Helvetica", 10))
        _5kV.grid(row=6, column=0, sticky="nw", pady=10)
        table_frame_5=tk.Frame(_30kV_scrollable_frame, relief="sunken", bg="light grey", borderwidth=2, height=730, width=1345)
        table_frame_5.grid(row=6, column=0, pady=40)
        table_5 = self.create_table(table_frame_5, 11, 11, table_labels)

        _3kV=tk.Label(_30kV_scrollable_frame, text="3kV", bg="light grey", font=("Helvetica", 10))
        _3kV.grid(row=7, column=0, sticky="nw", pady=10)
        table_frame_3=tk.Frame(_30kV_scrollable_frame, relief="sunken", bg="light grey", borderwidth=2, height=730, width=1345)
        table_frame_3.grid(row=7, column=0, pady=40)
        table_3 = self.create_table(table_frame_3, 11, 11, table_labels)

        _1kV=tk.Label(_30kV_scrollable_frame, text="1kV", bg="light grey", font=("Helvetica", 10))
        _1kV.grid(row=8, column=0, sticky="nw", pady=10)
        table_frame_1=tk.Frame(_30kV_scrollable_frame, relief="sunken", bg="light grey", borderwidth=2, height=730, width=1345)
        table_frame_1.grid(row=8, column=0, pady=40)
        table_1 = self.create_table(table_frame_1, 11, 11, table_labels)

        for i in [self, self._30kV_canvas, _30kV_scrollable_frame, _30kV_frame, _30kV_frame_label, _15kV, _13kV, _11kV, _9kV, _7kV, _5kV, _3kV, _1kV]:
            i.configure(background="light grey")
    
    def show_30kV_page(self):
        self._30kV_frame.tkraise()

    def _30kV_mouse_wheel_movement(self, event):
        print("Scrolling on 30kV page")
        self._30kV_canvas.yview_scroll(int(-1*(event.delta/120)), "units")
    
    def create_table(self, root, rows, columns, column_labels=None):
        table = []
        if column_labels:
            label_row = []
            for j, label_text in enumerate(column_labels):
                label = tk.Label(root, text=label_text, bg="light grey", font=("Helvetica", 10))
                label.grid(row=0, column=j, sticky="nsew")
                label_row.append(label)
            table.append(label_row)

        for i in range(1, rows):  # Start from 1 to skip the first row reserved for labels
            row = []
            for j in range(columns):
                cell = tk.Entry(root, width=19, justify="center")
                cell.grid(row=i, column=j)
                cell.insert(tk.END, "0")
                row.append(cell)
            table.append(row)
        return table

class _6kV_page(tk.Frame):
    def __init__(self, parent, _6kV_frame):
        super().__init__(parent)

        self._6kV_canvas=tk.Canvas(_6kV_frame, bg="light grey")
        _6kV_scrollbar=ttk.Scrollbar(_6kV_frame, orient="vertical", command=self._6kV_canvas.yview)
        _6kV_scrollable_frame=tk.Frame(self._6kV_canvas, bg="light grey")
        _6kV_scrollable_frame.bind("<Configure>", lambda e: self._6kV_canvas.configure(scrollregion=self._6kV_canvas.bbox("all")))
        self._6kV_canvas.create_window((50,50), window=_6kV_scrollable_frame, anchor="nw")
        self._6kV_canvas.configure(yscrollcommand=_6kV_scrollbar.set)
        self._6kV_canvas.config(height=750, width=1345)
        self._6kV_canvas.bind("<MouseWheel>", self._6kV_mouse_wheel_movement)
        self._6kV_canvas.pack(side="left", fill="both", expand=True)
        _6kV_scrollbar.pack(side="right", fill="y")

        _6kV_frame_label=tk.Label(_6kV_scrollable_frame, text="3. Measurements", bg="light grey", font=("Helvetica", 9))
        _6kV_frame_label.grid(row=0, column=0, sticky="nw", pady=10)

        # THIS NEEDS TO BE REWORKED
        table_labels=["Index", "Upeak [kV]", "+Upeak/1,41 [kV]", "-Upeak/1,41 [kV]", "f [Hz]", "Temp [°C]", "Uist CC100ref", "Umess Prüfung", "Diff. [%]", "crest factor", "Divider"]

        _6kV=tk.Label(_6kV_scrollable_frame, text="6kV", bg="light grey", font=("Helvetica", 10))
        _6kV.grid(row=1, column=0, sticky="nw", pady=20)
        table_frame_6=tk.Frame(_6kV_scrollable_frame, relief="sunken", bg="light grey", borderwidth=2, height=730, width=1345)
        table_frame_6.grid(row=1, column=0, pady=50)
        table_6 = self.create_table(table_frame_6, 11, 11, table_labels)

        _5kV=tk.Label(_6kV_scrollable_frame, text="5kV", bg="light grey", font=("Helvetica", 10))
        _5kV.grid(row=2, column=0, sticky="nw", pady=10)
        table_frame_5=tk.Frame(_6kV_scrollable_frame, relief="sunken", bg="light grey", borderwidth=2, height=730, width=1345)
        table_frame_5.grid(row=2, column=0, pady= 40)
        table_5 = self.create_table(table_frame_5, 11, 11, table_labels)

        _4kV=tk.Label(_6kV_scrollable_frame, text="4kV", bg="light grey", font=("Helvetica", 10))
        _4kV.grid(row=3, column=0, sticky="nw", pady=10)
        table_frame_4=tk.Frame(_6kV_scrollable_frame, relief="sunken", bg="light grey", borderwidth=2, height=730, width=1345)
        table_frame_4.grid(row=3, column=0, pady=40)
        table_4 = self.create_table(table_frame_4, 11, 11, table_labels)

        _3kV=tk.Label(_6kV_scrollable_frame, text="3kV", bg="light grey", font=("Helvetica", 10))
        _3kV.grid(row=4, column=0, sticky="nw", pady=10)
        table_frame_3=tk.Frame(_6kV_scrollable_frame, relief="sunken", bg="light grey", borderwidth=2, height=730, width=1345)
        table_frame_3.grid(row=4, column=0, pady=40)
        table_3 = self.create_table(table_frame_3, 11, 11, table_labels)

        _2kV=tk.Label(_6kV_scrollable_frame, text="2kV", bg="light grey", font=("Helvetica", 10))
        _2kV.grid(row=5, column=0, sticky="nw", pady=10)
        table_frame_2=tk.Frame(_6kV_scrollable_frame, relief="sunken", bg="light grey", borderwidth=2, height=730, width=1345)
        table_frame_2.grid(row=5, column=0, pady=40)
        table_2 = self.create_table(table_frame_2, 11, 11, table_labels)

        _1kV=tk.Label(_6kV_scrollable_frame, text="1kV", bg="light grey", font=("Helvetica", 10))
        _1kV.grid(row=6, column=0, sticky="nw", pady=10)
        table_frame_1=tk.Frame(_6kV_scrollable_frame, relief="sunken", bg="light grey", borderwidth=2, height=730, width=1345)
        table_frame_1.grid(row=6, column=0, pady=40)
        table_1 = self.create_table(table_frame_1, 11, 11, table_labels)

        for i in [self, _6kV_frame, _6kV_frame_label, _6kV, _5kV, _4kV, _3kV, _2kV, _1kV, _6kV_scrollable_frame, self._6kV_canvas]:
            i.configure(background="light grey")


    def _6kV_mouse_wheel_movement(self, event):
        print("Scrolling on 6kV page")
        self._6kV_canvas.yview_scroll(int(-1*(event.delta/120)), "units")
    
    def create_table(self, root, rows, columns, column_labels=None):
        table = []
        if column_labels:
            label_row = []
            for j, label_text in enumerate(column_labels):
                label = tk.Label(root, text=label_text, bg="light grey", font=("Helvetica", 10))
                label.grid(row=0, column=j, sticky="nsew")
                label_row.append(label)
            table.append(label_row)

        for i in range(1, rows):  # Start from 1 to skip the first row reserved for labels
            row = []
            for j in range(columns):
                cell = tk.Entry(root, width=19, justify="center")
                cell.grid(row=i, column=j)
                cell.insert(tk.END, "0")
                row.append(cell)
            table.append(row)
        return table

enter image description here

Any help is much appreciated.

1

There are 1 answers

1
acw1668 On BEST ANSWER

Since bind_all() will override previous binding, so only the last binding is effective.

You need to call bind_all() on the raised frame:

class Coupler15(tk.Toplevel):
    ...

    def create_measurement_frame(self):
        ...

        # need to raise one of the frame to activate the binding
        self.show_30kV_page()

    def show_30kV_page(self):
        self._30kV_frame.tkraise()
        self._30kV_page.setup_binding() # activate the binding

    def show_6kV_page(self):
        self._6kV_frame.tkraise()
        self._6kV_page.setup_binding() # activate the binding

class _30kV_page(tk.Frame):
    def __init__(self, parent, _30kV_frame):
        ...
        # don't call bind_all() here
        #self._30kV_canvas.bind_all("<MouseWheel>", self._30kV_mouse_wheel_movement)
        ...

    # new function to activate the binding
    def setup_binding(self):
        self._30kV_canvas.bind_all("<MouseWheel>", self._30kV_mouse_wheel_movement)

    ...

class _6kV_page(tk.Frame):
    def __init__(self, parent, _6kV_frame):
        ...
        # don't call bind_all() here
        #self._6kV_canvas.bind_all("<MouseWheel>", self._6kV_mouse_wheel_movement)
        ...

    # new function to activate the binding
    def setup_binding(self):
        self._6kV_canvas.bind_all("<MouseWheel>", self._6kV_mouse_wheel_movement)

    ...