3

I have the tkinter GUI running on main thread and a while loop running on a second thread which updates label contents to be displayed on the GUI for a duration on n seconds. This runs fine on its own. Now I want a << and >> button on the GUI which makes the loop:

  • pause the current iteration, call the display method with the previous item, and resume the iteration when done
  • skip the current item midway and move over to the next item. But I could not find how to generate loop interrupt events. I cannot call continue or sleep depending on some variables/db entries which the buttons make (like in here Python: Tkinter pausing a while loop) because the interrupt can happen anywhere in the loop (not at a particular if/else line)

I have already referred to the Viewer program by codemy.com - https://github.com/flatplanet/Intro-To-TKinter-Youtube-Course/blob/master/viewer.py and of course google.

Here is a snippet of what I am trying to do. (https://gitlab.com/ananya26nov/PixelescoPy)

The main thread runs the GUI

guiObj = GuiWindow()
thread_list = []
thread = threading.Thread(target=worker, args=(guiObj,))
thread_list.append(thread)
thread.start()
guiObj.run_window_on_loop()
thread.join()
guiObj.quit_window()

The worker method for the thread has this:

 while len(files_not_viewed) != 0:
    chosen = random.choice(files_not_viewed)
    if is_not_viewed(chosen):
        pictureObj = Picture(chosen)
        # Display the chosen for <timer> seconds
        pictureObj.display(guiObj)
        time.sleep(timer)
        # Change the status of "chosen" to "viewed"
        mark_as_viewed(chosen)
    files_not_viewed = list(set(files_not_viewed) - set([chosen]))

The display method calls 'add_input_section' method of the following class

class GuiWindow():
def __init__(self):
    self.root = Tk()
    self.screen_width = self.root.winfo_screenwidth()
    self.screen_height = self.root.winfo_screenheight()
    self.image_label = None
    self.image = None
    self.folder_path = None
    self.timer = None

def run_window_on_loop(self):
    button_exit = Button(self.root, text="Exit Program", command=self.root.quit)
    button_exit.grid(row=1, column=1)
    self.root.mainloop()

def quit_window(self):
    self.root.quit()

def resize(self, image_path):
    my_pic = Image.open(image_path)
    pic_height = my_pic.height
    pic_width = my_pic.width
    if my_pic.height > (self.screen_height - 100):
        new_height= self.screen_height - 100
        new_width = int(new_height / pic_height * pic_width)
        pic_height = new_height
        pic_width = new_width

    if pic_width > self.screen_width - 5:
        new_width = self.screen_height - 5
        new_height = int(new_width / pic_width * pic_height)
        pic_height = new_height
        pic_width = new_width

    resized_image = my_pic.resize((pic_width, pic_height), Image.ANTIALIAS)
    return resized_image

def add_image(self, image_path):
    resized_img = self.resize(image_path)
    image_obj = ImageTk.PhotoImage(resized_img)
    image_label = Label(self.root, image=image_obj,
                        height=resized_img.height,
                        width=resized_img.width)
    self.image = image_obj # DO NOT REMOVE - Garbage collector error
    if self.image_label is not None:
        self.remove_image()
    image_label.grid(row=0, column=0, columnspan=3)
    self.image_label = image_label

def remove_image(self):
    self.image_label.grid_forget()
2
  • It’s hard to tell without all the code, but it seems that you’re manipulating the GUI from another thread, which is not in general allowed. You probably need to rework that before worrying about how to communicate between the threads. Commented Jul 2, 2020 at 23:56
  • @DavisHerring yes I have a thread which is manipulating the GUI. So that is happening alright. I can see new images coming up as controlled by this thread. Now I want a button in the GUI which has an ability to pause the thread's loop. The code is here if you want to have a look :/ : gitlab.com/ananya26nov/PixelescoPy Commented Jul 3, 2020 at 7:48

1 Answer 1

0

Use tk.BooleanVar() to manipulate the variables and also keep track the state when you try to pause so that you can resume when it's finished.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.