【问题标题】:Tkinter Label not updating across classes (another one)Tkinter 标签未跨类更新(另一个)
【发布时间】:2020-12-18 13:57:39
【问题描述】:

目标:跨类显示变量

问题:更新标签,特别是第 99 行

错误:仅逻辑

环境: Python 3.6.9、Tk 8.6.8、操作系统 Ubuntu 18.04

写下来:

我试图在包含代码的第 99 行的 pViewSettings 类中显示变量 pPanelSettings.cutLength,但是我无法让它更新/刷新。在我的任何标签中包含textvariable 会使它显示为空白,即使我给它们一个初始值。在包含的尝试中,我留下了一个无效的刷新命令(第 106 行)以及一个无效的跟踪尝试(第 107 行)。其他尝试包括:

update_idletasks, 创建一个额外的字符串变量,它只是重新格式化整数变量以确认这不是问题, 在彼此内部引用pViewSettingspPanelSettings(导致循环), 以及我现在忘记的其他一些内容。

我最感兴趣的是找出我遗漏的“原因”,因为我将来会再次重复这个过程。很抱歉用另一个新手标签问题填满论坛,但我自己在这一点上不知所措。我相信这是一个我完全错过的简单修复。

理想情况下,我想了解textvariable 哪里出了问题,因为这似乎是最简单的解决方案,但与在线示例相比,我仍然看不出我错在哪里。

我:

我不打算在明年初之前进行 GUI 学习,但是我的这个项目的时间表加快了,所以我不得不快速投入。

我看过的帖子:

What are the arguments to Tkinter variable trace method callbacks?

Update Tkinter Label from variable

https://yagisanatode.com/2018/02/26/how-to-display-and-entry-in-a-label-tkinter-python-3/

许多其他人,但只是丢失了我所有的书签。

代码:

import tkinter as tk
import time as time
import math as math

#create main window
root = tk.Tk()
root.title('machine')

#create main container
mainFrame = tk.Frame(root)

#layout main container, grow with window size
mainFrame.pack(fill=tk.BOTH, expand=True)

#create globals
inchesInFeet = tk.IntVar()
answerReset = tk.IntVar()

#set globals
answerReset.set(0)

#create classes
class Page(tk.Frame):
    def __init__(self, *args, **kwargs):
        tk.Frame.__init__(self, *args, **kwargs)
    def show(self):
        self.lift()

class pPanelSettings(Page):
    def __init__(self, *args, **kwargs):
        Page.__init__(self, *args, **kwargs)
        #create variables
        self.cutFeet = tk.IntVar()
        self.cutInches = tk.IntVar()
        self.cutLength = tk.IntVar()
        self.panelCutConfirm = tk.BooleanVar()
        #set variables
        self.cutFeet.set(0)
        self.cutInches.set(0)
        self.cutLength.set(0)
        self.panelCutConfirm.set(0)
        #widgets
        self.pageTitle = tk.Label(self, text='PANEL SETTINGS')
        self.panelBlock = tk.LabelFrame(self, padx=5, pady=5)
        self.panelLabel = tk.Label(self.panelBlock, text='CURRENT PANEL SET LENGTH')
        self.panelSetting = tk.Label(self.panelBlock, text=self.cutLength.get())
        self.messageDisplay = tk.Label(self, text='Set cut length (feet):')
        self.wYesNo = tk.LabelFrame(self, padx=5, pady=5)
        self.bYes = tk.Button(self.wYesNo, text='ENTER', command=self.setCutFeet, height=4, activebackground='green1', background='green2')
        self.response = tk.Entry(self, justify='center')
        #layout
        self.pageTitle.pack(side='top', fill='x')
        self.panelBlock.pack(side='top', fill='x', pady=5)
        self.panelLabel.pack(side='left', fill='x', padx=50)
        self.panelSetting.pack(side='right', fill='x')
        self.messageDisplay.pack(side='top', fill='x', pady=60)
        self.wYesNo.pack(side='bottom', fill='x', padx=20, pady=20, expand=True)
        self.bYes.pack(side='left', fill='both', padx=10, expand=True)
        self.response.pack(side='bottom', fill='x', padx=20, pady=60)
        #settings
        self.response.focus_set()

    def clearText(self):
        self.response.delete(0, 'end')

    def transition(self):
        self.after(2000, self.pageReset)
        
    def pageReset(self): #resets widgets to initial view
        self.response.delete(0, 'end')
        self.messageDisplay.config(text='Set cut length (feet):')
        self.response.pack(side='bottom', fill='x', padx=20, pady=60)
        self.wYesNo.pack(side='bottom', fill='x', padx=20, pady=20, expand=True)
        self.bYes.config(command=self.setCutFeet)
        self.panelSetting.pack(side='right', fill='x')
      
    def setCutFeet(self):
        self.cutFeet.set(int(self.response.get()))
        self.setCutConfirm()
     
    def setCutConfirm(self):
        self.panelCutConfirm.set(True)
        self.cutLength.set(self.cutFeet.get())
        self.panelSetting.config(text=self.cutLength.get())
        print(self.cutLength.get())  ##verification test point using shell
        self.messageDisplay.config(text='Panel cut length set.')
        self.wYesNo.pack_forget()
        self.transition()
        
class pViewSettings(Page): ##this page needs auto update/refresh to display current settings from other pages
    def __init__(self, *args, **kwargs):
        Page.__init__(self, *args, **kwargs)
        #pages to objects
        oPanelSettings = pPanelSettings(self)
        #widgets
        self.pageTitle = tk.Label(self, text='VIEW SETTINGS')
        self.panelBlock = tk.LabelFrame(self, padx=5, pady=5)
        self.panelLabel = tk.Label(self.panelBlock, text='PANEL LENGTH')
        self.panelSetting = tk.Label(self.panelBlock, text=oPanelSettings.cutLength.get())
        #layout
        self.pageTitle.pack(side='top', fill='x')
        self.panelBlock.pack(side='top', fill='x', pady=5)
        self.panelLabel.pack(side='left', fill='x', padx=50)
        self.panelSetting.pack(side='right', fill='x')
        #actions
        self.refreshSelf() ##i know that this doesn't work, but i do not understand why
        oPanelSettings.cutLength.trace('r', self.refreshSelf) ##i really feel like this should work though

    def refreshSelf(self):
        #pages to objects
        oPanelSettings = pPanelSettings(self)
        #action
        self.after(1000, self.refreshSelf)
        self.panelSetting.config(text=oPanelSettings.cutLength.get())

class pMainView(tk.Frame):
    def __init__(self, *args, **kwargs):
        tk.Frame.__init__(self, *args, **kwargs)
        #pages to objects
        oPanelSettings = pPanelSettings(self)
        oViewSettings = pViewSettings(self)

        #create menu and view windows
        buttonFrame = tk.Frame(self)
        container = tk.Frame(self)
        buttonFrame.pack(side='left', fill='both', expand=False) #menu column
        container.pack(side='right', fill='both', expand=True) #main view window

        #place page objects into main view window
        oPanelSettings.place(in_=container, x=0, y=0, relwidth=1, relheight=1)
        oViewSettings.place(in_=container, x=0, y=0, relwidth=1, relheight=1)
        
        #create menu buttons
        bPanelSettings = tk.Button(buttonFrame, text='Panel Settings', command=oPanelSettings.lift)
        bViewSettings = tk.Button(buttonFrame, text='View Settings', command=oViewSettings.lift)
        
        #menu layout
        bPanelSettings.pack(side='top', fill='both', expand=True)
        bViewSettings.pack(side='top', fill='both', expand=True)
        
        #startup display page
        oViewSettings.show()

if __name__ == '__main__':
    root = tk.Tk()
    oMainView = pMainView(root)
    oMainView.pack(side='top', fill='both', expand=True)
    root.wm_geometry('1024x600')
    root.mainloop()

非常感谢任何和所有帮助。有人打电话给布莱恩奥克利来救我! :) :)

编辑 #1:缩短代码以实现最少的复制。

【问题讨论】:

    标签: python tkinter label


    【解决方案1】:

    使用StringVar更新标签的正确方法如下:

    这是一个最小的示例,您可以单击“添加”按钮来增加值并在“红色”和“青色”之间更改标签颜色。

    
    import tkinter as tk
    
    
    root = tk.Tk()
    value = 0
    labelVar = tk.StringVar()
    labelVar.set(f"Current value: {value}")
    
    
    def add_text():
        global value
        value += 1
        labelVar.set(f"Current value: {value}")
        if value % 2:
            newcolor = 'red'
        else:
            newcolor = 'cyan'
        label.config(bg=newcolor)
    
    
    label = tk.Label(root, textvariable=labelVar, bg='cyan')
    label.pack()
    
    tk.Button(root, text='Add', command=add_text).pack()
    
    root.mainloop()
    

    【讨论】:

    • 请澄清:我的代码在第 36 行将 cutLength 定义为 IntVar,在第 41 行以与您的示例 labelVar 相同的方式给出初始值。 textvariable 正在空白原始问题中所述的标签。
    【解决方案2】:

    对于任何可能在未来找到它的人——我最终只使用了全局变量并添加了一个自循环刷新。附加的代码不是“最小复制”,因为我不想把它擦掉,但它就在那里。我有点理解,最好从设置变量的位置提取变量,但我不明白全局变量与使用此处给出的共享数据示例有何不同(只需吸收 Bryan Oakley 发布的任何内容)How to access variables from different classes in tkinter?

    第 16/19 行 - 定义和初始设置全局变量

    第 123 行 - 更新全局变量(类 pPanelSettings)

    第 148 行 - 初始显示(类 pViewSettings)

    第 155 行 - 开始刷新(pViewSettings 类)

    第 159 行 - 只是 L148 的副本

    import tkinter as tk
    import time as time
    import math as math
    
    #create main window
    root = tk.Tk()
    root.title('Fabric Marker')
    
    #create main container
    mainFrame = tk.Frame(root)
    
    #layout main container, grow with window size
    mainFrame.pack(fill=tk.BOTH, expand=True)
    
    #define variables
    cutLength = tk.IntVar()
    
    #set variables
    cutLength.set(0)
    
    #define constants
    answerReset = tk.IntVar()
    
    inchesInFeet = tk.IntVar()
    inch = tk.IntVar()
    
    #set constants
    answerReset.set(0)
    
    inchesInFeet.set(12)
    inch.set(1)
    
    #create classes
    class Page(tk.Frame): ###I NEED NOTES TO UNDERSTAND THIS ONE ENTIRELY###
        def __init__(self, *args, **kwargs):
            tk.Frame.__init__(self, *args, **kwargs)
        def show(self):
            self.lift()
    
    class pPanelSettings(Page):
        def __init__(self, *args, **kwargs):
            Page.__init__(self, *args, **kwargs)
            #define variables
            self.cutFeet = tk.IntVar()
            self.cutInches = tk.IntVar()
            self.setCutConfirm = tk.BooleanVar()
            #set variables
            self.cutFeet.set(0)
            self.cutInches.set(0)
            self.setCutConfirm.set(False)
            #widgets
            self.pageTitle = tk.Label(self, text='PANEL SETTINGS')
            self.panelBlock = tk.LabelFrame(self, padx=5, pady=5)
            self.panelLabel = tk.Label(self.panelBlock, text='CURRENT PANEL SET LENGTH')
            self.panelSetting = tk.Label(self.panelBlock, text=(str(str(cutLength.get()) + '" / ' + str(self.cutFeet.get()) + '\' ' + str(self.cutInches.get()) + '"')))
            self.messageDisplay = tk.Label(self, text='Set cut length (feet):')
            self.outputDisplay = tk.Label(self)
            self.wYesNo = tk.LabelFrame(self, padx=5, pady=5)
            self.bYes = tk.Button(self.wYesNo, text='ENTER', command=self.setCutFeet, height=4, activebackground='green1', background='green2')
            self.bNo = tk.Button(self.wYesNo, text='CLEAR', command=self.clearText, height=4, activebackground='red1', background='red2')
            self.response = tk.Entry(self, justify='center')
            #layout
            self.pageTitle.pack(side='top', fill='x')
            self.panelBlock.pack(side='top', fill='x', pady=5)
            self.panelLabel.pack(side='left', fill='x', padx=50)
            self.panelSetting.pack(side='right', fill='x')
            self.messageDisplay.pack(side='top', fill='x', pady=60)
            self.wYesNo.pack(side='bottom', fill='x', padx=20, pady=20, expand=True)
            self.bYes.pack(side='left', fill='both', padx=10, expand=True)
            self.bNo.pack(side='right', fill='both', padx=10, expand=True)
            self.response.pack(side='bottom', fill='x', padx=20, pady=60)
            #settings
            self.response.focus_set()
    
        def clearText(self):
            self.response.delete(0, 'end')
    
        def confirmTransition(self):
            self.after(2000, self.pageReset)
            
        def pageReset(self):
            self.cutFeet.set(answerReset.get())
            self.cutInches.set(answerReset.get())
            self.response.delete(0, 'end')
            self.outputDisplay.pack_forget()
            self.messageDisplay.config(text='Set cut length (feet):')
            self.wYesNo.pack(side='bottom', fill='x', padx=20, pady=20, expand=True)
            self.bYes.config(command=self.setCutFeet)
            self.bNo.config(command=self.clearText)
            self.response.pack(side='bottom', fill='x', padx=20, pady=60)
            self.outputDisplay.config(foreground='black')
            self.panelSetting.pack(side='right', fill='x')
          
        def setCutFeet(self):
            self.cutFeet.set(int(self.response.get()))
            self.enterCutInches()
    
        def enterCutInches(self):
            self.response.delete(0, 'end')
            self.bYes.config(command=self.verifyInches)
            self.messageDisplay.config(text='Set cut length (inches):')
    
        def verifyInches(self):
            if (int(self.response.get()) >= (inchesInFeet.get())):
                self.response.delete(0, 'end')
                self.messageDisplay.config(text='Enter a number less than 12')
                return
            else:
                self.setCutInches()
    
        def setCutInches(self):
            self.cutInches.set(int(self.response.get()))
            self.response.delete(0, 'end')
            self.response.pack_forget()
            self.messageDisplay.config(text='Is this the correct cut length?')
            self.bYes.config(command=self.setPanelCut)
            self.bNo.config(command=self.pageReset)
            self.outputDisplay.config(text=str(str((self.cutFeet.get() * inchesInFeet.get()) + self.cutInches.get()) + '" / ' + str(self.cutFeet.get()) + '\' ' + str(self.cutInches.get()) + '"'))
            self.outputDisplay.pack(side='bottom', fill='x', padx=20, pady=60)
            
        def setPanelCut(self):
            self.setCutConfirm.set(True)
            cutLength.set((self.cutFeet.get() * inchesInFeet.get()) + self.cutInches.get())
            self.panelSetting.config(text=(str(str(cutLength.get()) + '" / ' + str(self.cutFeet.get()) + '\' ' + str(self.cutInches.get()) + '"')))
            print(cutLength.get())  ##verification test point using shell
            self.messageDisplay.config(text='Panel cut length set.')
            self.outputDisplay.config(foreground='green1', pady=120)
            self.bNo.config(command=self.pageReset)
            self.wYesNo.pack_forget()
            self.confirmTransition()
    
    class pViewSettings(Page):
        #confirm setting options on this page
        def __init__(self, *args, **kwargs):
            Page.__init__(self, *args, **kwargs)
            #define variables
            setMarkConfirm = tk.BooleanVar()
            setJobConfirm = tk.BooleanVar()
            #set variables
            setMarkConfirm.set(0)
            setJobConfirm.set(0)
            #widgets
            self.pageTitle = tk.Label(self, text='VIEW SETTINGS')
            self.panelBlock = tk.LabelFrame(self, padx=5, pady=5)
            self.panelLabel = tk.Label(self.panelBlock, text='PANEL LENGTH')
            self.panelSetting = tk.Label(self.panelBlock, text=str(cutLength.get()) + '" / ' + str(math.trunc(cutLength.get()/inchesInFeet.get())) + '\' ' + str(cutLength.get() - ((math.trunc(cutLength.get()/inchesInFeet.get())) * inchesInFeet.get())) + '"')
            #layout
            self.pageTitle.pack(side='top', fill='x')
            self.panelBlock.pack(side='top', fill='x', pady=5)
            self.panelLabel.pack(side='left', fill='x', padx=50)
            self.panelSetting.pack(side='right', fill='x')
            #action
            self.refreshSelf()
    
        def refreshSelf(self):
            #action
            self.panelSetting.config(text=str(cutLength.get()) + '" / ' + str(math.trunc(cutLength.get()/inchesInFeet.get())) + '\' ' + str(cutLength.get() - ((math.trunc(cutLength.get()/inchesInFeet.get())) * inchesInFeet.get())) + '"')
            self.after(10, self.refreshSelf)
    
    class pMainView(tk.Frame):
        def __init__(self, *args, **kwargs):
            tk.Frame.__init__(self, *args, **kwargs)
            #pages to objects
            oPanelSettings = pPanelSettings(self)
            oViewSettings = pViewSettings(self)
    
            #create menu and view windows
            buttonFrame = tk.Frame(self)
            container = tk.Frame(self)
            buttonFrame.pack(side='left', fill='both', expand=False) #menu column
            container.pack(side='right', fill='both', expand=True) #main view window
    
            #place page objects into main view window
            oPanelSettings.place(in_=container, x=0, y=0, relwidth=1, relheight=1)
            oViewSettings.place(in_=container, x=0, y=0, relwidth=1, relheight=1)
            
            #create menu buttons
            bPanelSettings = tk.Button(buttonFrame, text='Panel Settings', command=oPanelSettings.lift)
            bViewSettings = tk.Button(buttonFrame, text='View Settings', command=oViewSettings.lift)
            
            #menu layout
            bPanelSettings.pack(side='top', fill='both', expand=True)
            bViewSettings.pack(side='top', fill='both', expand=True)
    
            #startup display page
            oViewSettings.show()
    
    if __name__ == '__main__':
        root = tk.Tk()
        oMainView = pMainView(root)
        oMainView.pack(side='top', fill='both', expand=True)
        root.wm_geometry('1024x600')
        root.mainloop()
    

    【讨论】:

      猜你喜欢
      • 2017-11-18
      • 2021-03-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多