tkinter:如何获得标签的子类显示在屏幕上?



我正在尝试用Python中的类做一些事情(我来自过程语言背景)。尝试创建一个支持几个新方法来操作标签文本的tkinter的Label小部件的版本。

我的问题是我不能让标签在屏幕上实际可见。

代码如下:

from tkinter import *
DEFAULT_BG = '#f0f0f0'

class cngMsg(Label):
"""Message Display label"""
def __init__(self, parent, w, h):
"""Init the Message Label"""
self.parent = parent
Label.__init__(self, parent)
self.msgText = "Hello World"
self.msgLabel = Label(parent, text=self.msgText)
self.msgLabel.config(height=h, width=w, bg=DEFAULT_BG)
def clear(self):
self.msgText = ""
print(len(self.msgText))
self.msgLabel.config(text=self.msgText)
def newMessage(self, message):
print("about to display <" + message + ">")
self.msgText = message
print(len(self.msgText))
self.msgLabel.config(text=self.msgText)
def show(self, message, sameLine=None):
if (not sameLine) and len(self.msgText) > 0:
self.msgText += '/n'
print("about to show: <" + message + ">")
self.msgText = self.msgText + message
print(len(self.msgText))
self.msgLabel.config(text=self.msgText)

#Root Stuff
if __name__ == "__main__":
app = Tk()
app.title("Message Test")
# this is the start of the application
print("initialise the Message Test")
gMsg = cngMsg(app, 60, 20)
gMsg.pack()
gMsg.newMessage("new message")
gMsg.show("this is a test")
gMsg.show("second test")
app.mainloop()

调试打印消息出现在控制台上,但应用程序窗口不显示标签。

GUI编程需要使用非过程范式,因为它们是用户输入驱动的。随着时间的推移执行函数的问题讨论了这个问题,并有一些示例代码。

就我个人而言,我经常发现在创建GUI应用程序时,将它们视为fsm(有限状态机)是很有用的,在fsm中,用户输入会导致它们改变状态。

下面是如何做类似于我认为你在你的样本代码中尝试的事情,这是基于@Bryan Oakley对链接问题的回答(更新到Python 3)。它还显示了子类化tkinter类的正确方法。此外,它主要遵循PEP 8 - Python代码风格指南,我强烈建议您阅读并开始遵循。

from tkinter import *
DEFAULT_BG = '#f0f0f0'
DEFAULT_MSG_TEXT = "Hello World"
DELAY = 1000  # Milliseconds.

class CngMsg(Label):
"""Message Display label"""
def __init__(self, parent, w, h):
# Intialize with default text and background color.
super().__init__(parent, text=DEFAULT_MSG_TEXT, height=h, width=w, bg=DEFAULT_BG)
def clear(self):
self.config(text='')
def newMessage(self, message):
self.config(text=message)
def show(self, message, same_line=False):
text = self.cget('text')  # Get value of current option.
if not same_line and text:
text += 'n'
text += message
self.config(text=text)

class MyApp(Tk):
def __init__(self):
super().__init__()
self.frame = Frame(self)
self.frame.pack()
self.test_msg = CngMsg(self.frame, 60, 20)
self.test_msg.pack()
self.state = 0
self.do_test()
def do_test(self):
if self.state == 0:
self.test_msg.newMessage("start message")
self.state = 1
elif self.state == 1:
self.test_msg.show("this is a test")
self.state = 2
elif self.state == 2:
self.test_msg.show("second test")
self.state = 3
elif self.state == 3:
self.test_msg.clear()
self.test_msg.show("TEST COMPLETED")
self.state = -1  # Enter final state.
elif self.state != -1:
self.quit()  # Stop mainloop.
raise RuntimeError("Unknown state encountered")
if self.state != -1: # Not final state?
self.after(DELAY, self.do_test)  # Schedule another call.

if __name__ == "__main__":
root = MyApp()
root.title("Message Test")
root.mainloop()

您的cngMsg类正在创建两个标签。第一个是类本身的实例。第二个是在执行self.msgLabel = Label(parent, text=self.msgText)时创建的。第二个标签是cngMsg标签的子标签。由于您没有在第二个标签上调用pack,placegrid,因此它不会出现在任何地方。

在你的newMessage方法中,你正在更新不可见标签中的文本,而不是实际的标签。

你不需要第二个标签,在newMessage中你应该这样配置它:

def newMessage(self, message):
self.msgText = msgText
self.configure(text=self.msgText)

同样,showclear应该以类似的方式定义:

def clear(self):
self.msgText = ""
self.config(text=self.msgText)
def show(self, message, sameLine=None):
if (not sameLine) and len(self.msgText) > 0:
self.msgText += '/n'
self.msgText = self.msgText + message
self.config(text=self.msgText)

最新更新