首页 > 解决方案 > tkinter:如何让标签的子类显示在屏幕上?

问题描述

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

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

这是代码:

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

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

标签: pythontkintersubclass

解决方案


GUI 编程需要使用非过程范式,因为它们是用户输入驱动的。问题Tkinter — execution functions over time讨论了这一点并有一些示例代码。

就我个人而言,我经常发现在创建 GUI 应用程序时将它们视为 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()


推荐阅读