Python Tkinter使用画布动态创建带有滚动条的窗口 [英] Python tkinter use canvas to create dynamically window with scroll bar

查看:84
本文介绍了Python Tkinter使用画布动态创建带有滚动条的窗口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的目标是解决网格超出窗口的问题(如图1所示)


不要:
删除 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 的使用是无用的,因为这是您要布局此小部件的尺寸.

  • 使用小于 fm_grid.width 的固定 width = 200 ,将始终剪切 fm_grid 内容,也不是动态.

      canvas.configure(scrollregion = canvas.bbox("all"),width = 200,height = 200) 


如何将 Canvas width 与内部 Frame width 进行同步?

  • 您绑定了 fm_grid.bind(< Configure>" ,因此 event.widget fm_grid ,里面的 Frame .
  • 从那里 w.winfo _... 获取 event.widget 的尺寸,并构建一个 bbox 元组以设置滚动区域.
  • 使用 width 设置 canvas.width ,使其与 event.widget.winfo_width()同步./p>

      Class ScrollCanvas(tk.Canvas):def __init __(self,parent,** kwargs):super().__ init __(parent,** kwargs)def create_window(自己,孩子):super().create_window((0,0),window = child,anchor ='nw')child.bind(< Configure>",self.on_configure)def on_configure(自我,事件):w = event.widgetbbox = x,y,宽度,高度= 0、0,w.winfo_width(),w.winfo_height()self.configure(scrollregion = bbox,width = width) 

    使用Python测试:3.5-'TclVersion':8.6'TkVersion':8.6

My objective is to solve the problem of the grid exceeding the window(shown as figure.1)

enter image description here

My program function is creating a grid that number of columns defined by user.

I tried using canvas to solve this problem, but it still doesn't work successfully. It doesn't show the full grid in the canvas.(shown as figure.2) enter image description here

Below is my code, could you please help solve the problems or give me some advice. Thanks a lot.

Code:

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()

解决方案

Question: It doesn't show the full grid in the canvas

You have to sync, the width of the Canvas with the width of the Frame inside.

Note: fm_grid = tk.Frame(canvas, bg='blue') is shown in 'blue'.


Dont's:
Remove fm_grid.pack(), you layout with: canvas.create_window(....
Also, i recommend not to use a offset (4, 4), because you have to calculate with this offset on every canvas.configure(..., width=width + 4. Use (0, 0) instead.

# fm_grid.pack()
...
canvas.create_window((4,4),window=fm_grid,anchor='nw')


Useless, to create dynamically window:

  • Your usage of canvas.bbox is useless, because it's the dimension you want to layout this widget.

  • Using a fixed width=200, smaller than fm_grid.width will allways cut the fm_grid content, it's not dynamically either.

      canvas.configure(scrollregion=canvas.bbox("all"),width=200,height=200)
    


How to sync the width of the Canvas with the width of the Frame inside?

  • You bound fm_grid.bind("<Configure>", therefore the event.widget is fm_grid, the Frame inside.
  • Get the dimensions of the event.widget from there w.winfo_... and build a bbox tuple to set scrollregion.
  • Use width to set canvas.width, to be in sync with the 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)
    

    Tested with Python: 3.5 - 'TclVersion': 8.6 'TkVersion': 8.6

这篇关于Python Tkinter使用画布动态创建带有滚动条的窗口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆