Окно сообщения Python не обновляется, когда метод класса запрашивается из запроса глобального экземпляра.Что мне здесь не хватает? - PullRequest
0 голосов
/ 16 октября 2018
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()  

'' 'Использование кнопки на странице ops должно дать мне тот же результат, что и текст статистики в окне сообщения.Это небольшой пример очень большого графического интерфейса.У меня есть поток, который вызывает глобальную функцию при получении данных.Это все работает.Что мне нужно сделать, это распечатать полученные данные в окне сообщения моей страницы операций, не запрашивая их.Тестовая кнопка для имитации запроса.

Но он не работает.Какие-нибудь мысли?'' '

1 Ответ

0 голосов
/ 16 октября 2018

Я запускаю твой код, нажимаю кнопку и вижу print() s, так что я не знаю, что не так.Ваш вопрос говорит «Но он не работает» , но не описывает точно, как он терпит неудачу.Представленный пример, кажется, работает нормально и не воспроизводит проблему?

Избегайте использования потоков, хотя - вам не нужен поток для получения чего-либо из сети, вы можете использовать низкоуровневый tkinter createfilehandler длясоздайте событие, которое будет вызываться, когда что-то доступно для чтения в сокете, без зависания графического интерфейса и без потоков.Или, если вы предпочитаете более высокий уровень (рекомендуется), вы можете использовать асинхронные коммуникационные протоколы фреймворка!

РЕДАКТИРОВАТЬ: Из комментариев я наконец-то вижу вашу проблему: У вас есть два экземпляра Api_Operationsкласс .

Один из них создается и сохраняется как глобальная переменная с именем Api:

Api = Api_Operations(App)

Другой создается внутри класса API_Tabs в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() вы можете получить доступс помощью экземпляра API_Tabs, хранящегося в глобальном имени App:

App.Api.PrintMessage()

Вы можете удалить строку Api = Api_Operations(App).

...