-1

I want to start a webserver if the user does click on a button. Therefore I have written the following code:

import tkinter as tk
import tkinter.ttk as ttk
from tkinter import messagebox
import time
from multiprocessing import Process


class MainWindow(ttk.Frame):

    def __init__(self, parent):
        self.parent = parent
        ttk.Frame.__init__(self, master=self.parent)
        self.parent.grab_set()
        self.parent.title("Test_Program")
        self.parent.geometry("500x500")
        ttk.Button(self.parent, text="Start Web-Server", command=self.start_webserver).pack()

    def start_webserver(self):
        if __name__ == '__main__':
            loading_screen = LoadingScreen(self)
            result = [0]
            sub_process = Process(target=start_webserver, args=(result,))
            sub_process.start()
            sub_process.join()
            sub_process.terminate()
            loading_screen.destroy()
            if result[0] == 0:
                messagebox.showinfo("Webserver Status", "Webserver is running!")
            else:
                messagebox.showerror("Webserver Status", "Webserver can't be started an Error occured!")


class LoadingScreen(tk.Toplevel):

    def __init__(self, parent):
        self.parent = parent
        tk.Toplevel.__init__(self, master=self.parent)
        self.geometry("200x50")
        self.title("Loading Screen")
        self.transient(self.parent)
        self.grab_set()
        ttk.Label(self, text="Copying data!").pack()
        status_bar = ttk.Progressbar(self, length=180, mode="indeterminate")
        status_bar.start(5)
        status_bar.pack()

    def __del__(self):
        if isinstance(self.parent, tk.Toplevel):
            self.parent.grab_set()


def start_webserver(result):
    time.sleep(2) # This does represent the time thats necessary to start the webserver
    result[0] = 1

def main():
    root = tk.Tk()
    main_window = MainWindow(root)
    main_window.pack()
    root.mainloop()

if __name__ == "__main__":
    main()

If I click on "start webserver" its two seconds frozen because of time.sleep(2) and no progress bar does get displayed. Afterwards its done. I don't know why there is no progressbar displayed. I have used an array named "result" as parameter to get the return value of start_webserver(result) from sub_process to main_process. Unfortunately this is not working too because the value of "result[0]" stays 0. I don't know what to do. The idea of using an array I have found on stackoverflow too.

Here is the Link: how to get the return value from a thread in python?

Lehtim
  • 125
  • 1
  • 12
  • Because [`sub_process.join()`](https://docs.python.org/3/library/multiprocessing.html#multiprocessing.Process.join) blocks until `sub_process` terminates. – Stop harming Monica Mar 15 '18 at 13:03
  • @Goyo But I thought after 2 seconds join does not block anymore because the thread is done and terminate gets called ... without join or without destroy there is no change ... Or may I misunderstood you? What do I have to change in your opinion? – Lehtim Mar 15 '18 at 13:30
  • After 2 seconds `loading_screen` is destroyed along with the progress bar so you won't see it then either. – Stop harming Monica Mar 15 '18 at 14:46

1 Answers1

0

I have found out an answer by my own. Thanks for your help join() wasn't right. I have done it a different way and closing the "loading_screen" as well as opening the messagebox after the job has been done in the second thread.

That's the Code:

import tkinter as tk
import tkinter.ttk as ttk
from tkinter import messagebox
import time
from threading import Thread


class MainWindow(ttk.Frame):

    def __init__(self, parent):
        self.parent = parent
        ttk.Frame.__init__(self, master=self.parent)
        self.parent.grab_set()
        self.parent.title("Test_Program")
        self.parent.geometry("200x50")
        ttk.Button(self.parent, text="Start Web-Server", command=self.start_webserver).pack()

    def start_webserver(self):
        if __name__ == '__main__':
            loading_screen = LoadingScreen(self)
            thread = Thread(target=start_webserver, args=(loading_screen, ))
            thread.start()


class LoadingScreen(tk.Toplevel):

    def __init__(self, parent):
        self.parent = parent
        tk.Toplevel.__init__(self, master=self.parent)
        self.geometry("200x50")
        self.title("Loading Screen")
        self.transient(self.parent)
        self.grab_set()
        ttk.Label(self, text="Copying data!").pack()
        status_bar = ttk.Progressbar(self, length=180, mode="indeterminate")
        status_bar.start(2)
        status_bar.pack()

    def __del__(self):
        if isinstance(self.parent, tk.Toplevel):
            self.parent.grab_set()


def start_webserver(widget):
    return_val = do_some_stuff()
    if return_val:
        widget.destroy()
        messagebox.showinfo("Webserver Status", "Webserver is running!")
    else:
        widget.destroy()
        messagebox.showerror("Webserver Status", "Webserver can't be started an Error occured!\n"
                                                 "Please look inside 'Logfiles/logfile' for more details.")


def do_some_stuff():
    time.sleep(2) # This does represent the time thats necessary to start the webserver
    return True


def main():
    root = tk.Tk()
    main_window = MainWindow(root)
    main_window.pack()
    root.mainloop()


if __name__ == "__main__":
    main() 
Lehtim
  • 125
  • 1
  • 12