2012-03-29 101 views
0

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

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() 
+0

,请让你的缩进直,因为这是在Python至关重要。 – Constantinius 2012-03-29 09:45:04

+0

抱歉,当我将其复制到问题中时,它有所不同。 – iFetus 2012-03-29 09:46:54

回答

4

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

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

另一个关键是要确保循环的一次迭代速度很快 - 它需要在一秒钟内(更像100ms以下),否则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 
+0

我得到一个AttributeError:应用程序实例在'后'没有属性。任何想法是什么? – iFetus 2012-03-30 00:59:47

+1

@iFetus:我应该说上面假设Tkinter.Tk中的“self”。在你的情况下,你需要使用'master.after'或'self.master.after'或其他。 ''之后'是所有小部件通用的Tkinter方法。 – 2012-03-30 01:14:35

+0

哦,我明白了!我得到了它的工作。谢谢你的帮助。 – iFetus 2012-03-30 01:33:47

1

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

+0

这就是我的想法,但是在那附近呢? – iFetus 2012-03-29 10:17:02

+1

是的。你可以在不同的线程中处理UI事件(或者在不同的线程中进行工作)。您还可以检查tkinter是否提供了“主循环”的替代方案,以便您可以编写自己的主循环来处理UI事件和您在同一个线程中的工作。 – katzenversteher 2012-03-29 10:21:42

1

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

由于我没有在Tkinter中处理多线程,只能为您提供切入点:

祝你好运!