0

I'm writing a basic war-driving program. I have gotten it to loop the command to pull all the wireless access points near by. The problem is my stop button doesn't work and I am unable to update the label(I'm not even sure if I can update the label).

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()
iFetus
  • 51
  • 11

3 Answers3

4

Tkinter is single threaded. That means that while you are in the while loop inside startButtonClick, no other events are processed. The stop button won't call its command until the startButtonClick function finishes

You need to remember that your program is already running a global infinite loop: the event loop. There's no reason to put another infinite loop inside it. When you want something to run forever, the trick is to put one iteration on the event loop, then when it runs it puts another iteration on the event loop.

The other key to this is to make sure that one iteration of the loop is fast -- it needs to be well under a second (more like under 100ms) or the UI will become laggy.

The logic looks something like this:

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
Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
  • I get a AttributeError: App instance has no attribute 'after'. Any idea what that's about? – iFetus Mar 30 '12 at 00:59
  • 1
    @iFetus: I should have said that the above assumes `self` in as instance of Tkinter.Tk. In your case you need to use `master.after` or `self.master.after` or whatever. `after` is a Tkinter method common to all widgets. – Bryan Oakley Mar 30 '12 at 01:14
1

I think the main thread is hanging in the while loop of the start button click. Since it's busy it won't even notice the stop button has been pressed.

katzenversteher
  • 810
  • 6
  • 13
  • That's what I'm thinking, but is there away around that? – iFetus Mar 29 '12 at 10:17
  • 1
    Yes. You could process the UI events in a different thread (or do the work in a different thread). You could also check if tkinter offers an alternative to "mainloop" so you could write your own mainloop that handles UI events and your work in the same thread. – katzenversteher Mar 29 '12 at 10:21
1

I can't tell you exactly why your stop button doesn't work, but I think I got the idea of your programm. My suggestion is to establish two threads. The first thread for the UI, and the second for constantly checking wireless networks with given interval (your current code checks ASAP - bad practice, you should pause within the loop.

Since I have not dealt with multithreading in Tkinter, I can only provide you with entry points:

Good luck!

Community
  • 1
  • 1
f4lco
  • 3,728
  • 5
  • 28
  • 53