Python tkinter использует холст для динамического создания окна с полосой прокрутки
Моя цель - решить проблему выхода сетки за окно (показано на рисунке 1).
введите описание изображения здесь
Моя программная функция создает сетку, в которой количество столбцов определяется пользователем.
Я попытался использовать холст для решения этой проблемы, но он все равно не работает. Он не показывает всю сетку на холсте.(Показано на рисунке 2) введите описание изображения здесь
Ниже мой код, не могли бы вы помочь решить проблемы или дать мне совет. Большое спасибо.
Код:
import tkinter as tk
import tkinter.messagebox
import tkinter.filedialog
MainWindow = tk.Tk()
MainWindow.title('Helloworld')
MainWindow.geometry('1000x800')
def btn_generate():
global EntryNamelist
global Entrycoordinatelist
global EntryLabellist
con_num = en_condition_num.get()
if con_num != '':
#### Grid Body
for i in range(1,int(con_num) +1 ):
lb_name = tk.Label(fm_grid, text="Condition" + str(i) )
lb_name.grid(row=i, column=0, padx=2, pady=1, ipadx=20, ipady=5)
En_name = tk.Entry(fm_grid, bd = 2,width = 10,font=('Ubuntu', 10))
En_name.grid(row=i, column=1, padx=2, pady=1, ipadx=35, ipady=5)
En_coor = tk.Entry(fm_grid, bd = 2,width = 10,font=('Ubuntu', 10))
En_coor.grid(row=i, column=2, padx=2, pady=1, ipadx=200, ipady=5)
else:
tk.messagebox.showerror("Error", "Please input a num of conditions")
fm_main = tk.Frame()
fm3 = tk.Frame(fm_main)
lb_condition = tk.Label(fm3,text = 'Please input the number of condition')
lb_condition.pack(side="left")
en_condition_num = tk.Entry(fm3, bd = 2,width = 5)
en_condition_num.pack()
fm3.pack()
btn_generate = tk.Button(fm_main,text="Generate Grid",command=btn_generate)
btn_generate.pack()
lb_en = tk.Label(fm_main,text = '')
lb_en.pack()
def myfunction(event):
canvas.configure(scrollregion=canvas.bbox("all"),width=200,height=200)
canvas=tk.Canvas(fm_main)
fm_grid = tk.Frame(canvas)
fm_grid.pack()
myscrollbar=tk.Scrollbar(fm_main,orient="vertical",command=canvas.yview)
canvas.configure(yscrollcommand=myscrollbar.set)
myscrollbar.pack(side="right",fill="y")
canvas.pack(side="left")
canvas.create_window((4,4),window=fm_grid,anchor='nw')
fm_grid.bind("<Configure>",myfunction)
fm_main.pack()
MainWindow.mainloop()
1 ответ
Вопрос: не отображается вся сетка на холсте
Вы должны синхронизировать width
из Canvas
с width
из Frame
внутри.
Примечание:
fm_grid = tk.Frame(canvas, bg='blue')
показано в'blue'
.
Нельзя:
удалитьfm_grid.pack()
, ваш макет с:canvas.create_window(...
.
Также я рекомендую не использовать смещение(4, 4)
, потому что вы должны рассчитывать это смещение на каждомcanvas.configure(..., width=width + 4
. Использовать(0, 0)
вместо этого.# fm_grid.pack() ... canvas.create_window((4,4),window=fm_grid,anchor='nw')
Бесполезно, чтобы динамически создавать окно:
Ваше использование
canvas.bbox
бесполезен, потому что это размер, в котором вы хотите разместить этот виджет.Используя фиксированный
width=200
, меньше чемfm_grid.width
будет ВСЕГДА вырезатьfm_grid
контент, это тоже не динамически.canvas.configure(scrollregion=canvas.bbox("all"),width=200,height=200)
Как синхронизировать
width
изCanvas
сwidth
изFrame
внутри?
- Вы связаны
fm_grid.bind("<Configure>"
, Следовательноevent.widget
являетсяfm_grid
, тоFrame
внутри. - Получите размеры
event.widget
оттудаw.winfo_...
и построитьbbox
кортеж для установкиscrollregion
. Использовать
width
установитьcanvas.width
, чтобы синхронизироваться сevent.widget.winfo_width()
.class ScrollCanvas(tk.Canvas): def __init__(self, parent, **kwargs): super().__init__(parent, **kwargs) def create_window(self, child): super().create_window((0, 0), window=child, anchor='nw') child.bind("<Configure>", self.on_configure) def on_configure(self, event): w = event.widget bbox = x, y, width, height = 0, 0, w.winfo_width(), w.winfo_height() self.configure(scrollregion=bbox, width=width)
Протестировано с Python: 3.5 - 'TclVersion': 8.6 'TkVersion': 8.6