tkinter.Frame.Grid 尺码显示不正确
tkinter.Frame.Grid sizing not displaying correctly
您好,我正在制作一个 table 和一个 header 用于命名列的文本、用于存储数据的单元格和滚动。
我遇到的问题是我的 Table 显示不正确。应该发生的是 Headers 应该显示在上面,下面没有其他 space。 (除了我添加的小填充)单元格正确显示在 headers 的正下方。
滚动适用于 y 方向的单元格。滚动也适用于单元格和 headers 的 x 方向。
将单元格添加到框架的函数只是创建然后使用网格(行,列)添加
header 只有 1 行,所以空白 space 不应该在那里。
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()
这是他们目前的样子。
调整屏幕大小后,这是原来的样子。 headers 就在下面的单元格上方,只有填充 space。
如果我再缩小一点它会导致另一个问题,滚动条和 headers 从视图中消失。
然而,右侧的滚动条永远不会消失。 (我猜这是因为我不能再缩小屏幕了。
这就是 main_frame.grid_rowconfigure(1, weight=1) 发生的情况
它在将大小调整为较小 window 后导致此问题。
Question: Frame
Grid sizing not displaying correctly
你误会了,header_frame
不是 使用 .grid(...)
布局的。
使用 .create_window(...
将小部件添加到固定位置 0, 0, anchor='nw'
的 Canvas
。因此,no "Grid Layout Manager" 魔术,如自动调整大小,发生了。
你为什么得到这个布局?
注: main_frame == 'blue'
, _headerCanvas == 'lightgreen'
, _cellCanvas == 'red'
:
布局:A 布局:B 布局:C 布局: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')
布局:A:
您使用默认值 height
创建了两个 Canvas
。因此,您可以使用 "The Grid Layout Manager" 获得类似的布局。
布局:B:
将项目添加到 Canvas
,这里是单元格 Frame
,不会改变布局中的任何内容。
布局:C:
将 Canvas height
与 header_frame height
结果同步。
使用.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())
使用.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())
还是不是你想要的?
布局:D:
您已经允许 .grid(row=1
通过以下方式尽可能地增长:
main_frame.grid_rowconfigure(1, weight=1)
但是您不允许 Canvas
使用 sticky='ns'
增长。这导致 'blue'
space above/bottom。更改为 sticky='nsew'
。
您好,我正在制作一个 table 和一个 header 用于命名列的文本、用于存储数据的单元格和滚动。
我遇到的问题是我的 Table 显示不正确。应该发生的是 Headers 应该显示在上面,下面没有其他 space。 (除了我添加的小填充)单元格正确显示在 headers 的正下方。
滚动适用于 y 方向的单元格。滚动也适用于单元格和 headers 的 x 方向。
将单元格添加到框架的函数只是创建然后使用网格(行,列)添加 header 只有 1 行,所以空白 space 不应该在那里。
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()
这是他们目前的样子。
调整屏幕大小后,这是原来的样子。 headers 就在下面的单元格上方,只有填充 space。
如果我再缩小一点它会导致另一个问题,滚动条和 headers 从视图中消失。
然而,右侧的滚动条永远不会消失。 (我猜这是因为我不能再缩小屏幕了。
这就是 main_frame.grid_rowconfigure(1, weight=1) 发生的情况
它在将大小调整为较小 window 后导致此问题。
Question:
Frame
Grid sizing not displaying correctly
你误会了,header_frame
不是 使用 .grid(...)
布局的。
使用 .create_window(...
将小部件添加到固定位置 0, 0, anchor='nw'
的 Canvas
。因此,no "Grid Layout Manager" 魔术,如自动调整大小,发生了。
你为什么得到这个布局?
注: main_frame == 'blue'
, _headerCanvas == 'lightgreen'
, _cellCanvas == 'red'
:
布局:A 布局:B 布局:C 布局: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')
布局:A:
您使用默认值 height
创建了两个 Canvas
。因此,您可以使用 "The Grid Layout Manager" 获得类似的布局。
布局:B:
将项目添加到 Canvas
,这里是单元格 Frame
,不会改变布局中的任何内容。
布局:C:
将 Canvas height
与 header_frame height
结果同步。
使用
.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())
使用
.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())
还是不是你想要的?
布局:D:
您已经允许 .grid(row=1
通过以下方式尽可能地增长:
main_frame.grid_rowconfigure(1, weight=1)
但是您不允许 Canvas
使用 sticky='ns'
增长。这导致 'blue'
space above/bottom。更改为 sticky='nsew'
。