【问题标题】:tkinter frame: fix frame height when changing its contenttkinter 框架:在更改其内容时修复框架高度
【发布时间】:2015-02-22 01:02:16
【问题描述】:

我正在开发一个带有适当 GUI 的自行编写的模拟工具。通常有两种主要的用户模式。在第一个中,用户可以为所需的计算输入多个值。在所有计算完成后,用户可以通过点击右下角的“显示结果”按钮切换到“结果模式”。通过这样做,GUI 上部带有图像的主窗口不会改变。但是,GUI 下部的先前输入条目应更改为消息区域,其中显示错误、警告或其他信息(持续时间、收敛性...)。

我可以让两种 GUI 模式都可以切换,但是下框架(称为 lowerframe 的框架)的框架高度发生了变化,看起来很丑。

我认为所描述的行为是框架内容高度不同的结果。在第一种模式中,有几个 entry 小部件,而在第二种模式中,只有一个小的 label 小部件包含 foo

如何防止框架的高度动态变化?换句话说:有没有办法固定lowerframe的高度?

我指定了height=200(以及GUI右下角的btnframe),这似乎没有任何效果,因为包含foo-label小部件的框架肯定比那些小200 像素。

--- MWE ---

#!/usr/bin/env python3
# coding: utf-8

from tkinter import *
from tkinter import ttk
from PIL import Image, ImageTk

class Window(Frame):
    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.parameternames = []

        # create master window
        self.master = master

        # create master window
        self.create_masterwindow()

    def create_masterwindow(self):
        """
        creates master window with menubar and sets GUI to input mode
        """
        self.master.title('GUI')
        self.master.geometry('1280x850')
        self.master.resizable(width=FALSE, height=FALSE)

        self.gui_inputmode(firstcall=True)
        self.handle_resultsbtn(firstcall=True, showbtn=False)

    def gui_inputmode(self, firstcall=False):
        """
        turn GUI inputmode on
        """
        if firstcall:
            self.master.grid_columnconfigure(0, weight=1)
            self.master.grid_rowconfigure(0, weight=1)

            self.create_upperframe()
            self.upperframe.grid(row=0, column=0, pady=20, padx=20, columnspan=2, sticky='NEW')

            self.create_lowerframe()
            self.lowerframe.grid(row=1, column=0, pady=10, padx=20, sticky='SEW')

            self.create_btnframe()
            self.btnframe.grid(row=1, column=1, pady=5, padx=20, sticky='NSEW')
            self.put_inputfields()
            self.handle_inputbtn(firstcall=True, showbtn=True)

            self.pid = ImageTk.PhotoImage(file='test_1230_510.png')

            self.pidlabel = Label(self.upperframe, image=self.pid)
            self.pidlabel.pid = self.pid  # store a reference to the image as an attribute of the widget
            self.pidlabel.grid(row=0, column=0)

        else:
            self.handle_resultsbtn(showbtn=False)
            self.handle_inputbtn()
            self.error_label.grid_remove()
            for i, subdict in enumerate(self.parameternames):
                if type(subdict) == dict:
                    self.master.nametowidget(subdict['pname_entry_table']).grid()

    def gui_resultsmode(self):
        """
        turn GUI resultsmode on
        """
        self.handle_inputbtn(showbtn=False)
        self.handle_resultsbtn()

        for i, subdict in enumerate(self.parameternames):
            if type(subdict) == dict:
                self.master.nametowidget(subdict['pname_entry_table']).grid_remove()

        self.error_label = ttk.Label(self.lowerframe, text='foo')
        self.error_label.grid(row=0, column=0, sticky='E')

    def create_upperframe(self):
        """
        creates frame for PID and loads appropriate PID (GUI input mode)
        """
        if hasattr(self, 'upperframe'):
            del self.upperframe
        self.upperframe = Frame(self.master, width=1235, height=510, relief=RIDGE, bd=2)

    def create_lowerframe(self):
        """
        creates lower frame
        """
        if hasattr(self, 'lowerframe'):
            del self.lowerframe
        self.lowerframe = Frame(self.master, relief=RIDGE, bd=2, height=200)

    def put_inputfields(self):
        """
        creates entry widgets in lowerframe to read parameter as user input (GUI input mode)
        """
        for i in range(0, 18):
            r = (i // 4)
            c = (i % 4)*3

            self.lowerframe.grid_columnconfigure(c, weight=1)
            self.lowerframe.grid_columnconfigure(c+2, weight=1)

            entry_table = Entry(self.lowerframe, width=10, justify='right')
            entry_table.insert(0, format(float(42), ".3f"))
            entry_table.grid(row=r, column=c+1, pady=5, padx=0, sticky='EW')
            subdict = {}
            subdict['pname_entry_table'] = str(entry_table)
            self.parameternames.append(subdict)

    def handle_inputbtn(self, firstcall=False, showbtn=True):
        """
        creates buttons in btnframe when GUI in input mode
        """
        if firstcall:
            self.startanalysis_btn = Button(self.btnframe, width=15, text='Start Analysis')
            self.abortanalysis_btn = Button(self.btnframe, width=15, text='Abort Analysis')
            self.resetanalysis_btn = Button(self.btnframe, width=15, text='Reset Analysis')
            self.showresults_btn = Button(self.btnframe, width=15, text='Show Results', command=self.gui_resultsmode)
        if showbtn:
            self.startanalysis_btn.grid(pady=5)
            self.abortanalysis_btn.grid(pady=5)
            self.resetanalysis_btn.grid(pady=5)
            self.showresults_btn.grid(pady=5, sticky='S')
        if not showbtn:
            self.startanalysis_btn.grid_remove()
            self.abortanalysis_btn.grid_remove()
            self.resetanalysis_btn.grid_remove()
            self.showresults_btn.grid_remove()

    def handle_resultsbtn(self, firstcall=False, showbtn=True):
        """
        creates buttons in btnframe when GUI in result mode
        """
        if firstcall:
            self.exportdata_btn = Button(self.btnframe, width=15, text='Export Data')
            self.exportgraphs_btn = Button(self.btnframe, width=15, text='Export Graphs')
            self.createreport_btn = Button(self.btnframe, width=15, text='Create Report')
            self.showinput_btn = Button(self.btnframe, width=15, text='Show Input', command=self.gui_inputmode)
        if showbtn:
            self.exportdata_btn.grid(pady=5)
            self.exportgraphs_btn.grid(pady=5)
            self.createreport_btn.grid(pady=5)
            self.showinput_btn.grid(pady=5, sticky='S')
        if not showbtn:
            self.exportdata_btn.grid_remove()
            self.exportgraphs_btn.grid_remove()
            self.createreport_btn.grid_remove()
            self.showinput_btn.grid_remove()

    def create_btnframe(self):
        """
        creates frame for buttons in lower right corner
        """
        if hasattr(self, 'btnframe'):
            del self.btnframe
        self.btnframe = Frame(self.master, width=130, height=200)
        self.btnframe.grid_rowconfigure(3, weight=1)


master = Tk()
app = Window(master)
master.mainloop()

--- 测试图像 ---

【问题讨论】:

    标签: python python-3.x tkinter widget tk


    【解决方案1】:

    .grid_propagate(flag) 是您正在寻找的。

    设置框架的高度和宽度后,如果禁用传播,无论您有多少小部件,其大小都将相同。

    例如,我写了一些代码。尽管它看起来很丑,但它显示了传播的工作原理。

    import tkinter as tk
    
    root = tk.Tk()
    root.geometry("500x300")
    
    def add():
        tk.Entry(frame).grid()
    
    def disable():
        frame.configure(height=frame["height"],width=frame["width"])
        frame.grid_propagate(0)
    
    def enable():
        frame.grid_propagate(1)
    
    frame = tk.Frame(root, height=100,width=150,bg="black")
    frame.grid(row=1,column=0)
    
    tk.Button(root, text="add widget", command=add).grid(row=0,column=0)
    tk.Button(root, text="disable propagation", command=disable).grid(row=0,column=1)
    tk.Button(root, text="enable propagation", command=enable).grid(row=0,column=2)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-26
      • 2021-11-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多