非阻塞函数调用阻止tkintker GUI启动

时间:2017-05-30 10:53:14

标签: python-3.x tkinter python-asyncio

该示例显示了我创建非阻塞状态栏的方法,同时热情地提高了我在python中的技能。

问题是,gui不会被创建而且没有显示错误,尽管例如isEthernetUp()在与LAN断开连接时工作正常。令人惊讶的是,尽管使用了pythons async lib,但仍未创建GUI。我可以做些什么来不时更新状态?使用异步方法解决另一个问题?我是否必须降低级别并使用线程同时妖魔化它们?

我的例子:

import tkinter as tk
import socket
import asyncio
import asyncore
import datetime
import time


class Statusbar():
    def __init__(self):
        self.root = tk.Tk()
        self.root.title("Am I connected?")

        self.net_color = "red"
        self.connected = False
        self.timer = 0

        monitor = tk.Frame(self.root)
        monitor.grid(row=0, column=0)
        monitor_label = tk.Label(monitor, bd=2, relief=tk.SUNKEN,
                                 text="Net",
                                 fg="white",
                                 bg=self.net_color,
                                 padx=3,
                                 font=('courier', 16, 'bold'))
        monitor_label.grid(row=0, sticky=tk.E)

        time_label = tk.Label(self.root, text=self.timer, font=("courier", 16), relief=tk.SUNKEN)
        time_label.grid(row=0, column=1, sticky=tk.NSEW)

        self.getInfos()
        self.root.mainloop()

    def getInfos(self):
        try:
            n = NetworkIndicate()
            t = TimeIndicate()

            loop = asyncio.get_event_loop()
            loop.run_forever()
            while 1:
                self.connected = loop.run_until_complete(n.isEthernetUp())
                self.timer = loop.run_until_complete(t.whatTimeIsLove())

        except KeyboardInterrupt:
            # Canceling tasks
            asyncio.gather(*asyncio.Task.all_tasks()).cancel()
            loop.stop()
            loop.close()


class NetworkIndicate(asyncore.dispatcher):
    def __init__(self):
        pass

    @asyncio.coroutine
    async def isEthernetUp(self):
        """
        Updates the master's background color option if an IPv4 other than localhost was found and returns a boolean value.
        :return: boolean
        """
        try:
            s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
            s.connect(('<broadcast>', 0))

            # Referencing Example
            e = Statusbar()
            # Changes the color of the background color in Statusbar
            e.net_color = "green"
            return True
        except OSError:
            return False


class TimeIndicate(asyncore.dispatcher):
    def __init__(self):
        pass

    @asyncio.coroutine
    async def whatTimeIsLove(self):
        """
        Returns just the current unformatted time
        :return: string
        """
        return datetime.datetime.now()


if __name__ == '__main__':
    Statusbar()

1 个答案:

答案 0 :(得分:3)

我通常使用这种方法来使用内置的tkinter事件循环(使用之后的命令),这将避免阻塞:

import tkinter
from tkinter import *

class Visual(Frame):

    def __init__(self, root):
        self.root = root
        self.root.title("Am I connected?")

        self.net_color = "red"
        self.connected = False
        self.timer = 0

        monitor = Frame(self.root)
        monitor.grid(row=0, column=0)
        monitor_label = Label(monitor, bd=2, relief=SUNKEN,
                                 text="Net",
                                 fg="white",
                                 bg=self.net_color,
                                 padx=3,
                                 font=('courier', 16, 'bold'))
        monitor_label.grid()
        self.getInfos()

    def getInfos(self):
        print("Got the info")
        self.root.after(1000, self.getInfos)

if __name__ == '__main__':
    root = Tk()
    v = Visual(root)
    root.mainloop()