In my UI I need two canvases, each with their own horizontal scroll bar, but with a single scroll bar controlling the vertical movement of both canvases.
The following code creates two canvases, each with their own horizontal and vertical scrollbars. How can I get rid of one of the vertical scrollbars? Apologies for the length of code, it's as canonical as I could make it.
from tkinter import *
from tkinter import ttk
class MainUI:
def __init__(self, root):
mainframe = Frame(root)
mainframe.grid(column=0, row=0, sticky=(N,W,E,S))
# set up the first canvas, with large red triangle
canvas1 = Canvas(mainframe, background="turquoise")
canvas1.grid(column=1, row=1, sticky=(N,S,W,E))
canvas1_hscroller = Scrollbar(mainframe, orient="horizontal",command=canvas1.xview)
canvas1_hscroller.grid(column=1, row=2, sticky=(W,E))
canvas1.configure(xscrollcommand=canvas1_hscroller.set)
canvas1_vscroller = Scrollbar(mainframe, orient="vertical",command=canvas1.yview)
canvas1_vscroller.grid(column=2, row=1, sticky=(N,S))
canvas1.configure(yscrollcommand=canvas1_vscroller.set)
points = [0,0,1000,800,800,1000]
triangle = canvas1.create_polygon(points,fill="red")
canvas1.configure(scrollregion=canvas1.bbox("all"))
# set up the second canvas, with large green triangle
canvas2 = Canvas(mainframe, background="orange")
canvas2.grid(column=3, row=1, sticky=(N,S,W,E))
canvas2_hscroller = Scrollbar(mainframe, orient="horizontal",command=canvas2.xview)
canvas2_hscroller.grid(column=3, row=2, sticky=(W,E))
canvas2.configure(xscrollcommand=canvas2_hscroller.set)
canvas2_vscroller = Scrollbar(mainframe, orient="vertical",command=canvas2.yview)
canvas2_vscroller.grid(column=4, row=1, sticky=(N,S))
canvas2.configure(yscrollcommand=canvas2_vscroller.set)
points = [0,0,1000,800,800,1000]
triangle = canvas2.create_polygon(points,fill="green")
canvas2.configure(scrollregion=canvas2.bbox("all"))
root = Tk()
ui = MainUI(root)
root.mainloop()
CodePudding user response:
First make the canvases attributes of the instance:
...
self.canvas1 = Canvas(mainframe, background="turquoise")
...
self.canvas2 = Canvas(mainframe, background="orange")
and use the self.
prefix everywhere where you reference previously canvas1
and canvas2
Then define a new method
def v_scroll(self, *args):
self.canvas1.yview(*args)
self.canvas2.yview(*args)
Then just set the scrollbar command
to that method:
canvas_vscroller = Scrollbar(..., command=self.v_scroll)
Additionally, don't use from tkinter import *
, it is bad practice to use *
when importing modules. Import only what you need. For example in this case
from tkinter import Tk, Frame, Canvas, Scrollbar
Complete example (using import tkinter as tk
which is even better):
import tkinter as tk
class MainWindow(tk.Tk):
def __init__(self):
super().__init__()
# set up the first canvas, with large red triangle
self.canvas1 = tk.Canvas(self, background="turquoise")
self.canvas1.grid(column=0, row=0, sticky='news')
self.canvas1_hscroller = tk.Scrollbar(self, orient="horizontal", command=self.canvas1.xview)
self.canvas1_hscroller.grid(column=0, row=1, sticky='we')
self.canvas1.configure(xscrollcommand=self.canvas1_hscroller.set)
points = [0, 0, 1000, 800, 800, 1000]
self.canvas1.create_polygon(points, fill="red")
self.canvas1.configure(scrollregion=self.canvas1.bbox("all"))
# set up the second canvas, with large green triangle
self.canvas2 = tk.Canvas(self, background="orange")
self.canvas2.grid(column=1, row=0, sticky='news')
self.canvas2_hscroller = tk.Scrollbar(self, orient="horizontal", command=self.canvas2.xview)
self.canvas2_hscroller.grid(column=1, row=1, sticky='we')
self.canvas2.configure(xscrollcommand=self.canvas2_hscroller.set)
points = [0, 0, 1000, 800, 800, 1000]
self.canvas2.create_polygon(points, fill="green")
self.canvas2.configure(scrollregion=self.canvas2.bbox("all"))
self.v_scroller = tk.Scrollbar(self, orient='vertical', command=self.v_scroll)
self.v_scroller.grid(column=2, row=0, sticky='ns')
self.canvas1.config(yscrollcommand=self.v_scroller.set)
def v_scroll(self, *args):
self.canvas1.yview(*args)
self.canvas2.yview(*args)
root = MainWindow()
root.mainloop()
And btw, rows and columns start from 0
, so first row and column would be row=0
, column=0
accordingly