Python tkinter框架画布调整大小

时间:2017-11-04 21:12:26

标签: python canvas tkinter resize scrollbar

我尝试调整画布大小,以便当用户使用“点击并拖动”来调整窗口大小时,画布会填满整个窗口。在窗口边缘,但我没有成功。

我看过以下其他问题:

问题#1(之前发布,但没有帮助)

这个发送给我的是我认为正确的方向,因为我在画布上绑定了一个Configure。但是,我得到一个错误" '画布'没有在FrameWidth中定义。"

Tkinter: How to get frame in canvas window to expand to the size of the canvas?

如果我修改了函数调用和函数,那么我得到错误" TypeError:FrameWidth()缺少1个必需的位置参数:' canvas' "修改是

canvas.bind('<Configure>', self.FrameWidth(canvas))

def FrameWidth(self, event, canvas):

问题#2(之前发布,但没有帮助)

我也看了这个问题:

Python Tkinter Scrollbar Shaky Scrolling

但是这个问题正在解决一个不正常行为的滚动条。

问题#3(之前发布,但没有帮助)

我也看过这些问题并加权= 1,但这没有帮助:

Python TKinter: frame and canvas will expand horizontally, but not vertically, when window is resized

任何建议都将受到赞赏。

这是我的MWE:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Fri Nov  3 04:39:43 2017

@author: davidc
"""

import tkinter as tk


class Selections(tk.Frame): 
    def __init__(self, *args, **kwargs):
        tk.Frame.__init__(self, *args, **kwargs)

        self.FifthLabelLeft = tk.Label(self,
                         text="""Riding""",
                         justify = tk.CENTER,
                         width=20,
                         padx = 10).grid(row=4, column = 0, pady=5)

        self.FifthLabelCenter = tk.Label(self,
                         text="""Winning Candidate""",
                         justify = tk.CENTER,
                         width=20,
                         padx = 10).grid(row=4, column = 1, pady=5)

        self.FifthLabelRight = tk.Label(self,
                         text="""Percent of Vote""",
                         justify = tk.CENTER,
                         width=10,
                         padx = 10).grid(row=4, column = 2, pady=5)

        mybox = tk.LabelFrame(self, padx=5, pady=4)
        mybox.grid(row=5, column=0, columnspan=3)

        canvas = tk.Canvas(mybox, borderwidth=5, background="#70ff33")
        frame = tk.Frame(canvas, background="#33f4ff")
        vsb = tk.Scrollbar(mybox, orient="vertical", command=canvas.yview)
        canvas.configure(yscrollcommand=vsb.set, width=450, heigh=30)       

        mybox.grid_columnconfigure(5,weight=1)
        mybox.grid_rowconfigure(5,weight=1)
        frame.grid_columnconfigure(5,weight=1)
        frame.grid_rowconfigure(5,weight=1)

        vsb.pack(side="right", fill="y")
        canvas.pack(side="left", fill="both", expand=True)
        canvas.create_window((4,4), window=frame, anchor="nw", tags="frame")

        # be sure that we call OnFrameConfigure on the right canvas
        frame.bind("<Configure>", lambda event: self.OnFrameConfigure(canvas))
        canvas.bind('<Configure>', self.FrameWidth)

        self.fillWindow(frame)

        self.QuitButton = tk.Button(self, 
                                    text="QUIT", 
                                    command=root.destroy, 
                                    padx=25, pady=0)
        self.QuitButton.grid(column = 0, columnspan=3)


    def fillWindow(self, frame): 
        PartyWinnersList = [['Some list of places', "Somebody's Name", 0.37448599960838064], 
                            ['A shorter list', 'Three Long Names Here', 0.52167817821240514],
                            ['A much longer, longer entry', 'Short Name', 0.41945832387008858]]
        placement = 2
        for i in PartyWinnersList:
            ShowYear = tk.Label(frame,
                                      text="""%s """ % i[0],
                                      width=20,
                                      )
            ShowYear.grid(row=placement, column = 0, sticky=tk.S)
            ShowSystem = tk.Label(frame,
                                      text="""%s """ % i[1],
                                      width=20,
                                      )
            ShowSystem.grid(row=placement, column = 1, sticky=tk.N)
            PercentVotes = i[2]*100
            ShowVotes = tk.Label(frame,
                                      text="""%3.1f""" % PercentVotes,
                                      width=10,
                                      )
            ShowVotes.grid(row=placement, column = 2, sticky=tk.N)
            placement += 1

    def FrameWidth(self, event):
        canvas_width = event.width
        canvas.itemconfig(self.canvas_frame, width = canvas_width)

    def OnFrameConfigure(self, canvas):
        canvas.configure(scrollregion=canvas.bbox("all"))


if __name__ == "__main__": 
    root = tk.Tk()
    main = Selections(root)
    main.pack(side="top", fill="both", expand=True)
    root.mainloop()

1 个答案:

答案 0 :(得分:2)

无需在这里重新发明轮子。 Canvas()是一个tkinter小部件,与所有tkinter小部件一样,它必须使用几何管理器在窗口中绘制。这意味着我们可以操纵它在窗口中的显示方式。

以下示例程序根据this page上的示例进行了修改。

如果我们使用.pack(),那么我们可以执行以下操作:

from tkinter import *

root = Tk()

w = Canvas(root, width=200, height=100)
w.pack(fill="both", expand=True)

w.create_line(0, 0, 200, 100)
w.create_line(0, 100, 200, 0, fill="red", dash=(4, 4))

w.create_rectangle(50, 25, 150, 75, fill="blue")

root.mainloop()

fill="both"expand=True的组合告诉窗口小部件占用窗口中给出的所有额外空间并展开以填充它。

如果我们使用.grid(),那么我们必须做一些稍微不同的事情:

from tkinter import *

root = Tk()

root.columnconfigure(0, weight=1)
root.rowconfigure(0, weight=1)

w = Canvas(root, width=200, height=100)
w.grid(sticky=N+S+E+W)

w.create_line(0, 0, 200, 100)
w.create_line(0, 100, 200, 0, fill="red", dash=(4, 4))

w.create_rectangle(50, 25, 150, 75, fill="blue")

root.mainloop()

这里我们使用.rowconfigure().columnconfigure来告诉第0行和第0列(我们的画布所在的位置)比任何其他行或列具有更高的权重,这意味着他们可以获得更多的免费窗口中的空间比其他空间(在这种情况下,它看起来都不存在其他行或列),然后我们需要告诉窗口小部件实际扩展它所驻留的“单元格”,我们通过指定{ {1}},它告诉窗口小部件在展开时粘在单元格的所有4个边缘上,从而扩展窗口小部件。