问题
Hello I am making a table with a header for text to name the columns, cells to store data, and scrolling.
The problem I'm having is that my Table is not displaying correctly. What should happen is the Headers should display above with no other space below them. (other than the small padding I added) The cells display correctly right below the headers.
The scrolling works for the cells in the y direction. The scrolling also works in the x direction for both the cells and headers.
The function the adds the cells to the frame simply does a create then add using grid(row, column) The header only has 1 row so the blank space should not be there.
import tkinter as tk
import collections
from enum import Enum
window = tk.Tk() # Root (main) window
def main():
window.title('Table')
window.geometry("1024x600")
window.update_idletasks()
table_frame = tk.Frame(window, background='black')
table_frame.pack(fill='x')
table = Table(table_frame, 30, 15)
print(id(table))
window.mainloop()
class Table:
def __init__(self, frame, rowCount, columnCount):
self._rowCount = rowCount
self._columnCount = columnCount
main_frame = tk.Frame(frame, bg='blue')
main_frame.pack(fill='both')
self._headerCanvas = tk.Canvas(main_frame)
self._headerCanvas.grid(row=0, column=0, pady=1, sticky='ew')
self._cellCanvas = tk.Canvas(main_frame)
self._cellCanvas.grid(row=1, column=0, sticky='ew')
scroll_bar_y = tk.Scrollbar(main_frame, orient=tk.VERTICAL, command=self._cellCanvas.yview)
scroll_bar_y.grid(row=1, column=1, padx=1, sticky='ns')
scroll_bar_x = tk.Scrollbar(main_frame, orient=tk.HORIZONTAL, command=self.xViewScroll)
scroll_bar_x.grid(row=2, column=0, pady=1, sticky='ew')
main_frame.grid_columnconfigure(0, weight=1)
main_frame.grid_rowconfigure(1, weight=1)
self._cellCanvas.configure(xscrollcommand=scroll_bar_x.set, yscrollcommand=scroll_bar_y.set) #, width=(main_frame.winfo_width()-scroll_bar_y.winfo_width()))
header_frame = tk.Frame(self._headerCanvas)
self._headers = Table.ColumnHeaders(header_frame, self._columnCount)
cell_frame = tk.Frame(self._cellCanvas)
self._cells = Table.Cells(cell_frame, self._rowCount, self._columnCount)
self._headerCanvas.create_window(0, 0, window=header_frame, anchor='nw')
self._headerCanvas.update_idletasks()
self._cellCanvas.create_window(0, 0, window=cell_frame, anchor='nw')
self._cellCanvas.update_idletasks()
self._headerCanvas.configure(scrollregion=self._cellCanvas.bbox("all"))
self._cellCanvas.configure(scrollregion=self._cellCanvas.bbox("all"))
def xViewScroll(self, *args):
self._headerCanvas.xview(*args)
self._cellCanvas.xview(*args)
class Cells:
class Types(Enum):
Entry = 0
Button = 1
class Cell:
def __init__(self, widget, text=''):
self._text = text
self._widget = widget
def getWidget(self):
return self._widget
def setWidget(self, widget):
self._widget = widget
widget = property(getWidget, setWidget, "Get and set the widget of a cell.")
def __init__(self, frame, rows, columns, cellTypes=Types.Entry):
self._cells = [[],[]]
for r in range(rows):
self._cells.append([])
for c in range(columns):
self._cells[r].append(c)
if cellTypes == Table.Cells.Types.Entry:
self._cells[r][c] = Table.Cells.Cell(tk.Entry(frame, width=15))
elif cellTypes == Table.Cells.Types.Button:
self._cells[r][c] = Table.Cells.Cell(tk.Button(frame, width=12))
self._cells[r][c].widget.grid(row=r, column=c)
def getCell(self, row, column):
return self._cells[row][column]
def setCell(self, row, column, cell):
self._cells[row][column] = cell
cells = property(getCell, setCell, "Get and set a cell in the table.")
class ColumnHeaders:
def __init__(self, widget, columnCount):
self._widget = widget
self._columnCount = columnCount
self._headers = Table.Cells(self._widget, 1, self._columnCount, cellTypes=Table.Cells.Types.Button)
main()
This is how they are currently showing up.
After re sizing the screen this is what the original should look like. With the headers just above the cells below with only the padding space.
If I shrink it a little more it causes another problem the scrollbar and the headers disappear from view. The scrollbar on the right never disappears however. ( I'm guessing this is because I can't shrink the screen anymore.
This is what happens with main_frame.grid_rowconfigure(1, weight=1) It causes this after resizes to a smaller window.
回答1:
Question:
Frame
Grid sizing not displaying correctly
You are misguided, the header_frame
is not layouted using .grid(...)
.
Using .create_window(...
add the widget to the Canvas
at the fixed position 0, 0, anchor='nw'
. Therefore, no "Grid Layout Manager" magic, like auto resizing, happens.
Why do you get this Layout?
Note: main_frame == 'blue'
, _headerCanvas == 'lightgreen'
, _cellCanvas == 'red'
:
Layout: A Layout: B Layout: C Layout: D
self._headerCanvas = tk.Canvas(main_frame, bg='lightgreen')
self._headerCanvas.grid(row=0, column=0, pady=1, sticky='ew')
main_frame.grid_rowconfigure(1, weight=1)
self._cellCanvas = tk.Canvas(main_frame, bg='red')
self._cellCanvas.grid(row=1, column=0, sticky='ew')
Layout: A:
You create both Canvas
with the default height
. Therefore you get a similar layout using "The Grid Layout Manager".
Layout: B:
Adding itmes to a Canvas
, here the Cells Frame
, does not change anything at the Layout.
Layout: C:
Sync the Canvas height
with the header_frame height
results in.
Using
.bind('<Configure>'
header_frame = tk.Frame(self._headerCanvas) header_frame.bind('<Configure>', self.on_configure) def on_configure(self, event): # Sync _headerCanvas height with header_frame height w = event.widget self._headerCanvas.configure(height=w.winfo_height())
Using
.update_idletask()
header_frame = tk.Frame(self._headerCanvas) self._headers = Table.ColumnHeaders(header_frame, self._columnCount) root.update_idletasks() self._headerCanvas.configure(height=header_frame.winfo_height())
Still not what you want?
Layout: D:
You have allowed the .grid(row=1
to grow as much as possible by doing:
main_frame.grid_rowconfigure(1, weight=1)
But you don't allow the Canvas
to grow using sticky='ns'
. This result in the 'blue'
space above/bottom. Change to sticky='nsew'
.
来源:https://stackoverflow.com/questions/59295469/tkinter-frame-grid-sizing-not-displaying-correctly