0

When I push the button the scan_open_ports start working until the line ip_list.curselection() where it stops, this line blocks the running of the function... I wanted to know why and how to fix that? Thanks

def scan_open_ports():
    #long runtime function
    print "Asdasd\"
    ip_list.curselection()
def thr_open_ports():
    threading.Thread(target=scan_open_ports).start()
ip_list = Listbox()
scan_ports = Button(window, text="Scan Open Ports", command= thr_open_ports, height = 10, width = 20)
Khrui
  • 15
  • 4
  • Did you find any suitable code here on stackoverflow? – quamrana May 13 '19 at 18:16
  • Perhaps you could update your question with a link to that question/answer and the text of your own code where you say the button is stuck. – quamrana May 13 '19 at 18:22
  • Ok, I think that `tkinter` itself is not multithreaded. To communicate back to `tkinter` I think you will have to use a queue and use some mechanism to poll that queue and do something with it then. – quamrana May 13 '19 at 19:13
  • I tried using queue and it stiil didn't work... Do you have any better idea than threading? – Khrui May 13 '19 at 19:17
  • Not if you have a function that takes a long time to run and you still need the GUI to be responsive. – quamrana May 13 '19 at 19:18

1 Answers1

0

I have shamelessly stolen some code from this answer, just as a basis for some tkinter code: How to align label, entry in tkinter

The following code adapts this to have a Queue and a Thread which only runs after a button press.

The Thread communicates back to the mainloop through the Queue which is polled by calls to root.after()

from tkinter import *
from threading import Thread
from queue import Queue
from time import sleep
from random import randint

root = Tk()

root.geometry("583x591+468+158")
root.title("NOKIA _ANSI Performance")
root.configure(borderwidth="1")
root.configure(relief="sunken")
root.configure(background="#dbd8d7")
root.configure(cursor="arrow")
root.configure(highlightbackground="#d9d9d9")
root.configure(highlightcolor="black")

Label3 = Label(root)
Label3.configure(text='''Device  IP Address :''')
Label3.pack()
Label5 = Label(root)
Label5.configure(text='''Username :''')
Label5.pack()

Entry5 = Entry(root)
Entry5.pack()
th = None
q = Queue()

def run_me(q):
    sleep(5)
    q.put(randint(1, 99))

def check_queue():
    if not q.empty():
        item = q.get()
        Label5.configure(text=str(item))
    root.after(200, check_queue)

def do_thread():
    global th
    th = Thread(target=run_me, args=(q,))
    th.start()

Button1 = Button(root)
Button1.configure(pady="0")
Button1.configure(text='''NEXT''')
Button1.configure(command=do_thread)
Button1.pack()
root.after(200, check_queue)
mainloop()

The mainloop() is not blocked either by the Thread nor by the polling that check_queue() does.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
quamrana
  • 37,849
  • 12
  • 53
  • 71
  • You do have to press the `NEXT` button and wait 5 seconds before seeing the `Username` label change text. I did run the code several times before posting. – quamrana May 14 '19 at 13:06
  • I've just done another test in which I get the `NEXT` button to call `run_me(q)` directly. When I press the button, the whole GUI hangs for 5 seconds while the `sleep(5)` executes. Using a `Thread` works around that. – quamrana May 14 '19 at 13:11