Reputation: 1539
I'm writing a small GUI in python3/tkinter. What I want to do is generate a window with a table of data (like a spreadsheet) and have the table be scrollable both horizontally and vertically. Right now I'm just trying to display data, so I'm using a grid of Labels. The data display works fine but I can't get the scroll bars to act correctly. Here is the relevant part of my code; the class that this is in inherits from tk.Toplevel
frame = self.frame = tk.Frame(self)
self.frame.grid(row=1, columnspan=2, padx=2, pady=2, sticky=tk.N+tk.E+tk.S+tk.W)
self.text_area = tk.Canvas(self.frame, background="black", width=400, height=500, scrollregion=(0,0,1200,800))
self.hscroll = tk.Scrollbar(self.frame, orient=tk.HORIZONTAL, command=self.text_area.xview)
self.vscroll = tk.Scrollbar(self.frame, orient=tk.VERTICAL, command=self.text_area.yview)
self.text_area['xscrollcommand'] = self.hscroll.set
self.text_area['yscrollcommand'] = self.vscroll.set
self.text_area.grid(row=0, column=0, sticky=tk.N+tk.S+tk.E+tk.W)
self.hscroll.grid(row=1, column=0, sticky=tk.E+tk.W)
self.vscroll.grid(row=0, column=1, sticky=tk.N+tk.S)
self._widgets = []
for row in range(rows):
current_row = []
for column in range(columns):
label = tk.Label(self.text_area, text="",
borderwidth=0, width=width)
label.grid(row=row, column=column, sticky="nsew", padx=1, pady=1)
current_row.append(label)
self._widgets.append(current_row)
The table displays OK and the scrollbars appear but are not functional:
Any ideas?
Upvotes: 4
Views: 22334
Reputation: 1091
An option I have used is the leave the labels static and changed the data when the scrollbar is used. This is easy for vertical scrolling but if the columns are of different widths does not work for horizontal scrolling - it would require resizing the labels.
Upvotes: 0
Reputation: 386010
You have a couple of problems. First, you can't use grid
to place labels in the canvas and expect them to scroll. When you scroll a canvas, only the widgets added with create_window
will scroll. However, you can use grid to put the labels in a frame, and then use create_window
to add the frame to the canvas. There are several examples of that technique on this site.
Second, you need to tell the canvas how much of the data in the canvas should be scrollable. You use this by setting the scrollregion
attribute of the canvas. There is a method, bbox
which can give you a bounding box of all of the data in the canvas. Usually it's used like this:
canvas.configure(scrollregion=canvas.bbox("all"))
Upvotes: 3