【问题标题】:Python GUI buttons wont executePython GUI按钮不会执行
【发布时间】:2012-04-12 22:47:16
【问题描述】:

我正在编写一个基本的战争驾驶程序。我已经让它循环命令以拉动附近的所有无线接入点。问题是我的停止按钮不起作用,我无法更新标签(我什至不确定是否可以更新标签)。

import sys, os, subprocess, re
from Tkinter import *

missionGO = 0
count = 0

class App:

def __init__(self, master):

    frame = Frame(master)
    frame.pack()

    self.start = Button(frame, text="Start", fg="green",
                        command=self.startButtonClick)
    self.start.grid(row=3)

    self.stop = Button(frame, text="Stop", fg="red",
                       command=self.stopButtonClick)
    self.stop.grid(row=3, column=1)

    self.totalSSIDLabel = Label(frame, text="Current Access Points: ")
    self.totalSSIDLabel.grid(row=0)

    self.totalSSID = Label(frame, text=count)
    self.totalSSID.grid(row=0, column=1)

def startButtonClick(self):
    missionGO = 1
    while (missionGO == 1):
        wlan = getAccessPoints()
        x = numberOfAccessPoints(wlan)
        print x
    return

def stopButtonClick(self):
    missionGO = 0
    return

def stop(event):
    missionGO = 0

# Finds all wireless AP
def getAccessPoints():
    X = subprocess.check_output("netsh wlan show network mode=Bssid",
                                shell=True)
    return X

def numberOfAccessPoints(file):
    count = 0
    words = file.split()

for line in words:
    if re.match('SSID', line):
        count = count + 1
    return count

#Main
root = Tk()
app = App(root)
root.mainloop()

【问题讨论】:

  • 请直接缩进,因为这在 Python 中至关重要。
  • 对不起,当我把它复制到问题中时,它变得混杂了。

标签: python user-interface button tkinter label


【解决方案1】:

Tkinter 是单线程的。这意味着当您在startButtonClick 内的while 循环中时,不会处理其他事件。在startButtonClick 函数完成之前,停止按钮不会调用它的命令

您需要记住,您的程序已经在运行一个全局无限循环:事件循环。没有理由在其中放置另一个无限循环。当您希望某些东西永远运行时,诀窍是在事件循环上放置一个迭代,然后当它运行时,它会在事件循环上放置另一个迭代。

另一个关键是确保循环的一次迭代很快——它需要在 1 秒以内(更像是在 100 毫秒以内),否则 UI 会变得迟缓。

逻辑看起来像这样:

def startButtonClick(self):
    self.missionGO = 1
    self._do_one_iteration()

def _do_one_iteration(self):
    if self.missionGO == 1:
        wlan = getAccessPoints()
        x = numberOfAccessPoints(wlan)
        print x
        # this adds another iteration to the event loop
        self.after(10, self._do_one_iteration)

def stopButtonClick(self):
    self.missionGO = 0

【讨论】:

  • 我得到一个 AttributeError: App 实例没有属性 'after'。知道那是什么意思吗?
  • @iFetus:我应该说上面假设self是Tkinter.Tk的实例。在您的情况下,您需要使用 master.afterself.master.after 或其他。 after 是所有小部件通用的 Tkinter 方法。
【解决方案2】:

我认为主线程挂在开始按钮单击的 while 循环中。由于它很忙,它甚至不会注意到按下了停止按钮。

【讨论】:

  • 这就是我的想法,但是否存在这样的问题?
  • 是的。您可以在不同的线程中处理 UI 事件(或在不同的线程中进行工作)。您还可以检查 tkinter 是否提供“主循环”的替代方案,以便您可以编写自己的主循环来处理 UI 事件和您在同一线程中的工作。
【解决方案3】:

我不能确切地告诉你为什么你的停止按钮不起作用,但我想我明白了你的程序的想法。我的建议是建立两个线程。 UI 的第一个线程,第二个用于以给定的间隔不断检查无线网络(您当前的代码尽快检查 - 不好的做法,您应该在循环中暂停。

由于我没有处理过Tkinter中的多线程,所以只能给大家提供切入点:

祝你好运!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-25
    • 1970-01-01
    • 2012-02-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多