Python 当从全局实例请求中请求 class 方法时,消息框未更新。我在这里错过了什么?

Python Message box not updating when class method is requested from a global instance request. What am I missing here?

import tkinter as TK
from tkinter import *
from tkinter import ttk

############################################
root = TK.Tk()
root.geometry("1000x700+1+5")
WindowTitle = 'Test MessageBox'
Revision = 'Support 1.0';

gServerData = 'Let there be Rock'


# COMMAND/Communication Message Window Test Button #############
def ButtonTest():
    global gServerData
    #gServerData = '128,TestingMojo'
    print('* ButtonTest Function: Ready to Print in MessageBox',gServerData)
    Api.PrintMessage()

# TABS Notebook page Setup 
class API_Tabs(TK.Frame):

    def __init__(self,*args,**kwargs):
        Frame.__init__(self,*args,**kwargs)
        self.notebook = ttk.Notebook()
        self.Tabs()
        self.notebook.place(x=5, y = 1, height=690, width =990)
        self.master.title(WindowTitle)
        #self.MessageHistoryText = MessageHistoryText

    #Setup ttk Notebook style 
    def Tabs(self):
        page1 = Api_Select(self.notebook)
        page2 = Api_Operations(self.notebook) 

        self.notebook.add(page1,text="Main")
        self.notebook.add(page2,text="Operation")   

############################################    
class Api_Select(Frame):
    def __init__(self,name,*args,**kwargs):
        Frame.__init__(self,*args,**kwargs)
        self.name = name


class Api_Operations(Frame):
    def __init__(self,name,*args,**kwargs):
        Frame.__init__(self,*args,**kwargs)
        self.name = name
        self.createWidgets()
        self.PrintMessage()

    def PrintMessage(self):
        global gServerData
        print('* Print Message Function: Message Ready',gServerData)
        self.MessageHistoryText.delete('1.0',END)
        self.MessageHistoryText.insert(TK.END, 'GlobalServer:' + gServerData + '\n', 'notice')
        self.MessageHistoryText.see(TK.END)
        self.MessageHistoryText.update()
        root.update()
        print('* Print Message Function: MessageBox Update',gServerData)

    def createWidgets(self):
        self.mainFrame = Frame(self) #TK.Frame(self)
        self.mainFrame.place(x=0, y = 0, height=650, width = 1000)

        self.ButtonTestPB = TK.Button(self.mainFrame, text='TEST', command= ButtonTest)
        self.ButtonTestPB.place(x=50, y = 100, height=50, width = 50)

        # COMMAND/Communication Entry Window and Send Button #############
        self.MessageFrame = TK.Frame(self.mainFrame)
        self.MessageFrame.place(x=240, y = 50, height=370, width = 360)
        self.MessageCmdLabel = TK.Label(self.MessageFrame, text= 'Command/Communications',anchor="w" )
        self.MessageCmdLabel.place(x=0, y = 0, height=25, width = 200)
        self.MessageHistoryText = TK.Text(self.MessageFrame, height=20, width=40, relief=TK.SUNKEN)
        self.MessageHistoryScroll = TK.Scrollbar(self.MessageFrame)     
        self.MessageHistoryText.config(yscrollcommand=self.MessageHistoryScroll.set)
        self.MessageHistoryScroll.config(command=self.MessageHistoryText.yview)
        self.MessageHistoryText.place(x=0, y = 25, height=300, width = 350)
        self.MessageHistoryScroll.place(x=350, y = 25, height=300, width = 15)      
        self.MessageHistoryText.tag_configure('warning', foreground='red', background='gainsboro')
        self.MessageHistoryText.tag_configure('notice', foreground='blue', background='gainsboro')  

App = API_Tabs(root)
Api = Api_Operations(App)
#_thread.start_new_thread(Receive, ("Receive_Thread",))
App.mainloop()
root.destroy()  

''' 使用操作页面上的按钮应该会给我与消息框中的状态文本相同的结果。这是一个非常大的 GUI 的小例子。我有一个线程 运行,它在接收到数据时调用一个全局函数。这一切都有效。我需要做的是在不请求的情况下将接收到的数据打印到我的操作页面消息框。测试按钮是模拟请求。

但它不起作用。有什么想法吗? '''

我运行你的代码,点击按钮看到print()s,所以我不知道哪里错了。你的问题说 "But it is not working" 但没有准确描述它是如何失败的。提供的示例似乎工作正常并且没有重现问题?

虽然避免使用线程 - 你不需要线程来从网络接收东西,你可以使用 tkinter 的低级 createfilehandler 创建一个事件,当有东西可以读入时调用该事件一个套接字,没有冻结图形用户界面,也没有线程。或者如果你更喜欢更高级别(推荐)你可以使用异步框架通信协议!

编辑:从评论中我终于可以看出你的问题是什么:你有两个实例 Api_Operations class.

其中一个正在实例化并存储为名为 Api:

的全局变量
Api = Api_Operations(App)

另一个是在API_Tabs class 内部创建的,在Tabs() 方法中,并存储为名为page2:

的局部变量
page2 = Api_Operations(self.notebook) 

由于您正在显示 page2 但正在更新 Api,因此更新永远不会显示,因为您正在更新的实例不是屏幕中显示的实例。

要修复它,请将您在 API_Tabs.Tabs() 中创建的实例存储为属性:

def Tabs(self):
    page1 = Api_Select(self.notebook)
    self.Api = Api_Operations(self.notebook) 

    self.notebook.add(page1,text="Main")
    self.notebook.add(self.Api, text="Operation")

然后在您的 ButtonTest() 函数中,您可以使用存储在全局名称 App:

中的 API_Tabs 实例访问它
App.Api.PrintMessage()

您可以删除 Api = Api_Operations(App) 行。