I am writing a simple spreadsheet viewer. What I want is for row 0 to be controls and not scroll, Row 1 to be column headers and scroll horizontally with the data, rows 2 through end -1 to be data and scroll scroll both horizontally and vertically and a scroll bar at the far right, and the end row to be the horizontal scroll bar. I want the program to fill the entire window. What I have now is only the top left quarter of the window is used, horizontal scrolling works but there is no data and no vertical scroll bar.
import tkinter as tk
from tkinter import messagebox
class test:
def __init__(self,root,hxw):
self.hxw=hxw
root.wm_title("Test")
root.configure(bd=2)
root.rowconfigure(0, weight = 1)
root.columnconfigure(0, weight = 1)
screen_width = root.winfo_screenwidth()
screen_height = root.winfo_screenheight()
if not self.hxw:
self.hxw='{0:d}x{1:d}+{2:d}+{3:d}'.format(min(940,screen_width),min(560,screen_height),int(screen_width/3),int(screen_height/3))
root.geometry(self.hxw) #Width x Height
root.update()
self.top = root
self.topFrame = tk.Frame(self.top, height=25, background="blue")
self.topFrame.grid(row=0,column=0, sticky="NEW")
self.topFrame.grid_columnconfigure(0, weight=1)
self.topFrame.grid_rowconfigure(0, weight=1)
tk.Button(self.topFrame, text="Help", command=self.callback4).grid(row=0, column=0, sticky='E')
self.hsFrame = tk.Frame(self.top, background="red")
self.hsFrame.grid(row=1,column=0, sticky="NEWS")
self.hsFrame.grid_columnconfigure(0, weight=1)
self.hsFrame.grid_rowconfigure(1, weight=1)
self.hcanvas = tk.Canvas(self.hsFrame, background="green")
self.hcanvas.grid(row=0, column=0, sticky="NEW")
self.hcanvas.grid_columnconfigure(0, weight=1)
self.hcanvas.grid_rowconfigure(0, weight=1)
self.mFrame = tk.Frame(self.hcanvas)
self.mFrame.grid(row=0, column=0)
self.mFrame.grid_columnconfigure(0, weight=1)
self.mFrame.grid_rowconfigure(0, weight=1)
self.mFrame.bind(
"<Configure>",
lambda e: self.hcanvas.configure(
scrollregion=self.hcanvas.bbox("all")
)
)
self.hcanvas.create_window((0, 0), window=self.mFrame, anchor="nw")
# Create a horizontal scrollbar linked to the canvas.
hsbar = tk.Scrollbar(self.hsFrame, orient=tk.HORIZONTAL, command=self.hcanvas.xview)
hsbar.grid(row=2, column=0, sticky=tk.EW)
self.hcanvas.configure(xscrollcommand=hsbar.set)
self.labelFrame = tk.Frame(self.mFrame, background="grey") #place a frame on the canvas, this frame will hold the child widgets
self.labelFrame.grid(row=0,column=0, sticky="NEWS")
self.labelFrame.grid_rowconfigure(0, weight=1)
self.labelFrame.grid_columnconfigure(0, weight=1)
for col in range(20):
tkl = tk.Label(self.labelFrame, width=20, borderwidth="1", relief="solid", text=("col %d" % (col+1)))
tkl.grid(row=0, column=col, sticky='news')
self.labelFrame.grid_columnconfigure(col,weight=1)
self.vsFrame = tk.Frame(self.mFrame, background="yellow")
self.vsFrame.grid(row=1,column=0, sticky="NEWS")
self.vsFrame.grid_rowconfigure(1, weight=1)
self.vsFrame.grid_columnconfigure(0, weight=1)
self.vcanvas = tk.Canvas(self.vsFrame, background="#ff00ff")
self.vcanvas.grid(row=0,column=0, sticky="NEWS")
self.vcanvas.grid_rowconfigure(0, weight=1)
self.vcanvas.grid_columnconfigure(0, weight=1)
self.botFrame = tk.Frame(self.vcanvas, background="orange") #place a frame on the canvas, this frame will hold the child widgets
self.botFrame.grid(row=0,column=0, sticky="NEWS")
self.botFrame.grid_rowconfigure(0, weight=1)
self.botFrame.grid_columnconfigure(0, weight=1)
self.botFrame.bind(
"<Configure>",
lambda e: self.vcanvas.configure(
scrollregion=self.vcanvas.bbox("all")
)
)
self.vcanvas.create_window((0, 0), window=self.vsFrame, anchor="nw")
## # Create a vertical scrollbar linked to the canvas.
self.vsbar = tk.Scrollbar(self.vsFrame, orient=tk.VERTICAL, command=self.vcanvas.yview)
self.vsbar.grid(row=0, column=1, sticky=tk.NS)
self.vcanvas.configure(yscrollcommand=self.vsbar.set)
#
# Add 50-by-20 labels to the frame
rows = 50
columns = 20
for i in range(0, rows):
for j in range(0, columns):
tkl = tk.Label(self.botFrame, width=10, borderwidth="1", relief="solid", text=("%d,%d" % (i+1, j+1)))
tkl.grid(row=i, column=j, sticky='news')
self.botFrame.grid_columnconfigure(j, weight=1)
def callback4(self):
print('root', root.winfo_geometry())
print('self.topFrame', self.topFrame.winfo_geometry())
print('self.hsFrame', self.hsFrame.winfo_geometry())
print('self.hcanvas', self.hcanvas.winfo_geometry())
print('self.mFrame', self.mFrame.winfo_geometry())
print('self.labelFrame', self.labelFrame.winfo_geometry())
print('self.vsFrame', self.vsFrame.winfo_geometry())
print('self.vcanvas', self.vcanvas.winfo_geometry())
print('self.botFrame', self.botFrame.winfo_geometry())
print('------------------------------')
messagebox.showinfo(
"help",
"This is help"
)
# Launch the GUI
root = tk.Tk()
test(root,None)
root.mainloop()
To make your widgets fill the root
window modify your code as below.
This is taken from your __init__
just after self.hxw=hxw
root.wm_title("Test")
root.configure(bd=2)
root.rowconfigure(0, weight = 1)
root.columnconfigure(0, weight = 1)
row
and column
configure can be applied directly to root
just like any other container.
Ok, now you have a full screen view, the next step is to make your code easier to read so here is another code snippet that will help.
def flexx(o, r = 0, c = 0, rw = 1, cw = 1):
if r != None:
o.rowconfigure(r, weight = rw)
if c != None:
o.columnconfigure(c, weight = cw)
class test:
def __init__(self,root,hxw):
self.hxw = hxw
root.wm_title("Test")
root.configure(bd = 2)
flexx(root)
flexx(root, r = 1)
You should be able to use flexx
on widgets that are currently using grid_rowconfigure
and grid_columnconfigure
. I've already replaced those without any apparent adverse effect. Note the way flexx
is applied to root
, this is pretty much how most other widgets are made flexible.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.