具有现有while循环的Pi GUI

时间:2020-06-19 10:14:33

标签: python tkinter

我正在努力获得一个简单的GUI,以便在Raspberry Pi(Buster)上使用python(2.7)。

我已经尝试过Tkinter和PySimpleGUI,但是它们都有效地使用了while循环和 我的程序中已经有这样的循环,可以正常工作。 Tkinter和PySimpleGUI都阻塞了主循环。

尝试在线程中运行Tkinter和PySimpleGUI似乎不起作用, 各种元素与线程不兼容,并挂有各种错误消息。 无论如何,似乎一旦进入线程,您将无法与GUI小部件进行交互 除非您创建复杂的队列并且它们不是线程安全的。

我要做的就是写出'Alert Door'打印语句(while循环的最后一行) 进入文本字段(漂亮/彩色的东西) 然后有一个警报声(GPIO)和一个用于清除警报和文本字段的按钮。

任何想法都令人惊讶,似乎可用的Pi GUI不合适。 温柔一点,我是新手。

def vp_start_gui():
        #'''Starting point when module is the main routine.'''
                global val, w, root
                root = tk.Tk()
                top = Toplevel1 (root)
                redalert_support.init(root, top)
                root.mainloop()
                w = None


def destroy_Toplevel1():
    global w
    w.destroy()
    w = None

class Toplevel1:
    def __init__(self, top=None):
        '''This class configures and populates the toplevel window.
           top is the toplevel containing window.'''
        _bgcolor = '#d9d9d9'  # X11 color: 'gray85'
        _fgcolor = '#000000'  # X11 color: 'black'
        _compcolor = '#d9d9d9' # X11 color: 'gray85'
        _ana1color = '#d9d9d9' # X11 color: 'gray85'
        _ana2color = '#ececec' # Closest X11 color: 'gray92'
        font13 = "-family {Segoe UI} -size 22"
        font14 = "-family {Segoe UI} -size 21"

        top.geometry("480x300+267+205")
        top.minsize(120, 1)
        top.maxsize(1028, 749)
        top.resizable(1, 1)
        top.title("SecuriCode RedAlert")
        top.configure(background="#4339fb")

        self.Button1 = tk.Button(top)
        self.Button1.place(relx=0.333, rely=0.667, height=54, width=177)
        self.Button1.configure(activebackground="#ececec")
        self.Button1.configure(activeforeground="#000000")
        self.Button1.configure(background="#ffff00")
        self.Button1.configure(cursor="fleur")
        self.Button1.configure(disabledforeground="#a3a3a3")
        self.Button1.configure(font=font14)
        self.Button1.configure(foreground="#000000")
        self.Button1.configure(highlightbackground="#d9d9d9")
        self.Button1.configure(highlightcolor="black")
        self.Button1.configure(pady="0")
        self.Button1.configure(text='''Clear Alarm''')

        self.Text1 = tk.Text(top)
        self.Text1.place(relx=0.125, rely=0.133, relheight=0.423, relwidth=0.756)

        self.Text1.configure(background="white")
        self.Text1.configure(font=font13)
        self.Text1.configure(foreground="black")
        self.Text1.configure(highlightbackground="#d9d9d9")
        self.Text1.configure(highlightcolor="black")
        self.Text1.configure(insertbackground="black")
        self.Text1.configure(selectbackground="#c4c4c4")
        self.Text1.configure(selectforeground="black")
        self.Text1.configure(wrap="word")

vp_start_gui()


while 1:

    #Receive data from LAN device
    reply = s.recv(34)

    #Receive replies from SMS Gateway
    #smsreply = g.recv(34)   

    #Check for Lan device keep alive replies
    if reply.find(alivereply) != -1:
        #print 'Device alive'
        print reply

    #Check for valid Tag strings
    if reply.find(tagstring) != -1:
        print 'Tag string received'
        print reply

        #Send SMS alert message
        doorcode = reply[5:6]
        doornumber = int(doorcode, 16)
        #print doornumber

        tagcode = reply[8:9]
        tagnumber = int(tagcode, 16)
        #print tagnumber

        print 'Alert Door ' +str(doornumber) + '  Tag '  +str(tagnumber) 

2 个答案:

答案 0 :(得分:1)

Tkinter和PySimpleGUI都阻塞了主循环。

并非总是如此。以我的经验,阻止tkinter阻止主程序循环的最佳解决方案是使用root_window.update()而不是root_window.mainloop()

使用此方法,您可以不断迭代while循环,还可以更新tkinter窗口。

希望这会有所帮助。

更新

在您进行编辑之后,我亲自查看了您的代码。

我更改了函数vp_start_gui()并在循环外创建了根窗口。此代码的主要目的是让您了解如何正确实现tkinter窗口。将鼠标悬停在其上时的活动背景; tkinter.tk按钮默认情况下不具有此功能。活动背景的真正含义是单击按钮时的背景颜色。尽管有多种方法可以使用tkinter.tk来完成此操作,使用tkinter.ttk轻松获得所需内容的简单方法。

import tkinter as tk
from tkinter import ttk
def vp_update_gui():
        #'''Starting point when module is the main routine.'''
                global val, w, root  
                #redalert_support.init(root, top)
                root.update()
                w = None


def destroy_Toplevel1():
    global w
    w.destroy()
    w = None

class Toplevel1:
    def __init__(self, top=None):
        '''This class configures and populates the toplevel window.
           top is the toplevel containing window.'''
        _bgcolor = '#d9d9d9'  # X11 color: 'gray85'
        _fgcolor = '#000000'  # X11 color: 'black'
        _compcolor = '#d9d9d9' # X11 color: 'gray85'
        _ana1color = '#d9d9d9' # X11 color: 'gray85'
        _ana2color = '#ececec' # Closest X11 color: 'gray92'
        font13 = "-family {Segoe UI} -size 22"
        font14 = "-family {Segoe UI} -size 21"

        top.geometry("480x300+267+205")
        top.minsize(120, 1)
        top.maxsize(1028, 749)
        top.resizable(1, 1)
        top.title("SecuriCode RedAlert")
        top.configure(background="#4339fb")

        s = ttk.Style()
        s.configure('Kim.TButton', foreground='maroon',activeforeground="yellow")
        self.Button1 = ttk.Button(top,style='Kim.TButton',text='''Clear Alarm''')
        self.Button1.place(relx=0.333, rely=0.667, height=54, width=177)


        self.Text1 = tk.Text(top)
        self.Text1.place(relx=0.125, rely=0.133, relheight=0.423, relwidth=0.756)

        self.Text1.configure(background="white")
        self.Text1.configure(font=font13)
        self.Text1.configure(foreground="black")
        self.Text1.configure(highlightbackground="#d9d9d9")
        self.Text1.configure(highlightcolor="black")
        self.Text1.configure(insertbackground="black")
        self.Text1.configure(selectbackground="#c4c4c4")
        self.Text1.configure(selectforeground="black")
        self.Text1.configure(wrap="word")


root = tk.Tk()
top = Toplevel1(root)

while 1:
    vp_update_gui()

    #Receive data from LAN device
    reply = 's.recv(34)'

    #Receive replies from SMS Gateway
    #smsreply = g.recv(34)   

    #Check for Lan device keep alive replies
    if reply == '-1':
        #print 'Device alive'
        print (reply)

    #Check for valid Tag strings
    if reply == '+1':
        print ('Tag string received')
        print (reply)

        #Send SMS alert message
        doorcode = reply[5:6]
        doornumber = int(doorcode, 16)
        #print doornumber

        tagcode = reply[8:9]
        tagnumber = int(tagcode, 16)
        #print tagnumber

        print( 'Alert Door ' +str(doornumber) + '  Tag '  +str(tagnumber) )

答案 1 :(得分:0)

通过在“异步模式”下运行PySimpleGUI程序,可以轻松解决“阻塞”问题。文档中有大量有关在读取调用中使用超时的信息,您将找到大量演示此技术的演示程序。

这是循环的示例代码,每100毫秒更新一次计数器。您可以为硬件条件或某些条件集添加轮询,而不是更新文本。在此处可以添加代码以轮询某些内容。

import PySimpleGUI as sg

layout = [  [sg.Text('My Window')],
            [sg.Text('Will output here', key='-OUT-')],
            [sg.Button('Exit')]  ]

window = sg.Window('A non-blocking window', layout)

count = 0

while True:
    event, values = window.read(timeout=100)    # returns every 100 milliseconds
    if event == sg.WIN_CLOSED or event == 'Exit':
        break
    window['-OUT-'].update(f'Count={count}')
    count += 1
window.close()