Bottom Page

Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
 [Tkinter] Call a class method from another (Tk GUI) class?
#1
I am trying to create a simple timed event class that I can use to trigger repeating events in other programs (e.g.: data logger). I know that since Python functions (methods) are first class objects they can be passed around easily, stored in lists or dicts, etc. so I thought that it would be easy to just store a function as a class attribute and call it from there when needed. But, I'm having trouble calling the stored function. In my App class (Tk) I need to call the function in App.run_events() but if I try without the parenthesis it does nothing and if I add them the program hangs. I suspect I'm missing something obvious but after spending the last decade coding in LabVIEW my brain might just be corrupted in some way.

The issue is down between the lines of ###########s...

If I'm doing something "un-pythonic" and you feel there's a better way to tackle this please feel free to say so. I'm finally back to Python in my main job so I want to move forward doing things the right way.

Thanks All,
K

#! /usr/bin/env python

import tkinter as tk
import time

class Event(object):
    """ Event Class for timing repetitive events. """

    event_list = []

    def __init__(self, name, interval, method_to_call):
        self.name = name
        self.interval = interval # The time delay (in seconds) between subsequent triggers of this event.
        self.method_to_call = method_to_call # The function to be executed when this event is triggered.
        self.init_time = time.time() # Keep the timestamp of when the event was initialized for later use.
        self.last_time = self.init_time
        Event.event_list.append(self)

    def __str__(self):
        return f"EVENT -- Name: {self.name}, Interval: {self.interval}, Method Called: {self.method_to_call.__name__}."

    def check_event_ready(self):
        """ Test whether an event interval has elapsed and it's ready to run again. """

        if time.time() - self.last_time >= self.interval:
            self.last_time = time.time()
            return True
        else:
            return False


class App():
    def __init__(self):
        self.root = tk.Tk()

        self.event_listbox = tk.Listbox(width=50, height=25)
        self.event_listbox.pack()

        self.status_listbox = tk.Listbox(width=50, height=5)
        self.status_listbox.pack()

        self.setup() # Load up the Events to run.
        self.run_events() # Start the Event checking loop.
        self.root.mainloop() # Start the Tk GUI.

    def setup(self):
        """ Setup the events with their interval timing and function to execute. """

        ev1 = Event("Collect Data", 2, self.collect_data)
        ev2 = Event("Update Network", 5, self.update_network)
        for e in Event.event_list:
            print(e)

#####################################################################################################################
    def run_events(self):
        """ Spins a fast loop (using Tk.root.after()) to constantly check whether it's time to trigger an event. """

        for event in Event.event_list:
            if event.check_event_ready():
                self.event_listbox.insert(tk.END, event.name)
                event.method_to_call ### HOW DO I CALL THIS METHOD???
                print(event.method_to_call.__name__) # It prints just fine.
######################################################################################################################

        self.root.after(10, self.run_events) # Repeat at 10mS resolution.

    def collect_data(self):
        self.status_listbox.insert(tk.END, "Collect Data Running")
        time.sleep(500) # Add time delay to see if I need to use threading.

    def update_network(self):
        self.status_listbox.insert(tk.END, "Update Network Running")
        time.sleep(500)

app = App()
"So, brave knights, if you do doubt your courage or your strength, come no further, for death awaits you all with nasty, big, pointy teeth!" - Tim the Enchanter
Quote
#2
Looks like I got ahead of myself and caused the problem. Blush It was the time.sleep() functions I added to the methods I wanted to call through the events that were causing the program to hang. I knew I would eventually need to thread the functions running under Tk so I should have left the calls to sleep() out until I had the basics working. I keep forgetting the python's sleep() function is in seconds, NOT milli-seconds so of course it looked like the program was hanging when it was working fine.

If you want to run the code just change the 500 in time.sleep(500) to a small number of seconds and you can see that the functions are being called but then tie up the thread. Time to start working with the threading and multi-processor modules...
"So, brave knights, if you do doubt your courage or your strength, come no further, for death awaits you all with nasty, big, pointy teeth!" - Tim the Enchanter
Quote
#3
Instead of time.sleep, use tkinter's after method.
Quote
#4
Thanks for your reply! I'm using .after() in the Event class to poll for when an event is ready to run but I can't use it to replace sleep since sleep is only a simulation for testing. In the real code, an event like collect_data will cause real hardware to scan a bunch of signals and it will actually take a few seconds. I don't want the GUI to go unresponsive so I'm pretty sure the best solution is threading (or multi-processing). I'm working on that now... Slowly. Wall
"So, brave knights, if you do doubt your courage or your strength, come no further, for death awaits you all with nasty, big, pointy teeth!" - Tim the Enchanter
Quote

Top Page

Possibly Related Threads...
Thread Author Replies Views Last Post
  repeated method call berckut72 4 67 Jan-22-2020, 08:47 AM
Last Post: berckut72
  [Tkinter] Using variables from one class to another vatsava 0 118 Jan-03-2020, 08:12 AM
Last Post: vatsava
  Unable fetch fucntion data in class in tkinter jenkins43 2 239 Nov-30-2019, 09:47 PM
Last Post: jenkins43
  Tkinter Class pythonenthusiast2 1 190 Nov-24-2019, 03:51 AM
Last Post: Larz60+
  [Tkinter] Update variable between class/frame edwin6938 6 230 Nov-22-2019, 08:13 AM
Last Post: edwin6938
  Configure label from different class storzo 1 2,297 Aug-19-2019, 01:30 PM
Last Post: Denni
  [Tkinter] Delete an object created from another class alan9979 4 261 Jul-13-2019, 08:48 AM
Last Post: alan9979
  Button in one class, methods in another one alan9979 4 417 Jul-11-2019, 01:57 AM
Last Post: joe_momma
  [PyQt] call a function in another class darktitan 6 1,808 Jun-22-2019, 03:33 AM
Last Post: darktitan
  PyQt Threading & Class handling mrdominikku 8 2,550 Mar-10-2019, 09:14 PM
Last Post: mrdominikku

Forum Jump:


Users browsing this thread: 1 Guest(s)