Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
tkinter
#16
(Mar-24-2023, 03:25 AM)deanhystad Wrote: Use python tags when posting code.

I don't understand why you are trying to write this as a GUI application. There is nothing going on that wouldn't work better as a console application.

You are not following the correct pattern to use tkinter. In tkinter you make a root window and then run the root_window.mainloop() function. mainloop() is what makes the windows appear and buttons and entry objects work. And you won't be using the keyboard library either. The GUI should be getting the keystrokes. And you shouldn't have any code that blocks the GUI from running. Waiting for something in the test should not result in the GUI waiting.

If you feel the need to write this as a tkinter application, I envision something like this:
import time
import threading
import tkinter as tk
from tkinter import scrolledtext, simpledialog, messagebox
from functools import partial
 
# from serial import Serial
class Serial:
    """Fake serial driver so I can run tests"""
 
    def __init__(self, *args, **kvargs):
        self.volts = "0"
        pass
 
    def open(self):
        pass
 
    def close(self):
        pass
 
    def write(self, bytes):
        if bytes.startswith(b"VOLT"):
            self.volts = bytes[4:-1]
        window.print(f"writing {bytes}")
        return self.volts
 
 
def voltage_test(runner, voltage=None):
    """Run a voltage test"""
    if voltage is None:
        voltage = runner.request(
            lambda: simpledialog.askfloat(title="Test", prompt="Enter voltage")
        )
    ser9 = Serial(port="COM9", baudrate=9600, timeout=1)
    runner.print("-- Going to Remote Mode.")
    ser9.write("SESS01\r".encode())
    ser9.write("SESS01\r".encode())
    runner.print(f"-- Setting up the voltage to {voltage}.")
    ser9.write(
        f"VOLT{int(voltage*100):05}r".encode()
    )  # Is this the only part that changes?
    runner.print("-- Closing output switch.")
    ser9.write("SOUT000\r".encode())
    ser9.write("SOUT000\r".encode())
    MEAS_1 = ser9.write("GETD\r".encode())  # How does this get a value?
    time.sleep(0.5)
    runner.print(
        f"-- Commanding {voltage} volts",
        f"-- PS1 reporting: {MEAS_1.decode()} volts",
        "-- Connecting DMM to PS1 entering the console.",
    )
    ser9.close()
    runner.request(
        lambda: messagebox.showinfo(title="Test", message="Press Ok to continue")
    )
    ser4 = Serial(port="COM4", baudrate=9600, timeout=1)
    ser4.write(b"\x03")
    ser4.write(b"\x03")
    ser4.close()
 
 
def help(runner):
    """Display help text"""
    runner.print(
        "======================================================================",
        "P.N: BK Precision 1697",
        "AC/DC Power Supplies Verification Procedure",
        "Verification Procedure Ver 1.0",
        "======================================================================",
        "DC Power Supply No.1 \n",
        "COM9 will be open to get access to PS.1 and set voltages...",
        "COM4 will be used to connect DMM to read voltages.",
    )
 
 
def countdown(runner, count, period=1):
    """Demonstrate that text is displayed while test runs"""
    for i in range(count, 0, -1):
        runner.print(str(i))
        time.sleep(period)
 
 
class MainWindow(tk.Tk):
    """A test runner"""
 
    columns = 4
 
    def __init__(self):
        super().__init__()
        self.title("AC/DC Power Supplies Verification Procedure")
        self.label = tk.Label(self, text="Test Results")
        self.label.pack(padx=5, pady=5)
        self.text = scrolledtext.ScrolledText(self, wrap=tk.WORD, width=80, height=20)
        self.text.pack(padx=5, pady=5)
        self.tests = {}
        self.test_buttons = []
        self.test_button_frame = tk.Frame(self)
        for column in range(self.columns):
            self.test_button_frame.grid_columnconfigure(column, weight=1, uniform="key")
        self.test_button_frame.pack(padx=5, pady=5, expand=True, fill=tk.X)
        self.request_action = None
        self.request_reply = None
 
    def add_test(self, title, func, *args):
        """Add a test to the menu"""
        self.tests[title] = partial(func, self, *args)
        self.test_buttons.append(
            tk.Button(
                self.test_button_frame, text=title, command=lambda: self.run_test(title)
            )
        )
        for index, button in enumerate(self.test_buttons):
            button.grid(
                row=index // self.columns, column=index % self.columns, sticky="news"
            )
 
    def run_test(self, test_name):
        """Run selected test"""
        self.text.delete(1.0, tk.END)
        for button in self.test_buttons:
            button["state"] = tk.DISABLED
        self.thread = threading.Thread(target=self.tests[test_name])
        self.thread.start()
        self.monitor_test()
 
    def monitor_test(self):
        """Monitor test execution.
        Executes any requests from the test. Enables test buttons when test is complete.
        """
        if self.thread and self.thread.is_alive():
            # Test is still running
            if self.request_action is not None:
                # execute the request
                self.request_reply = self.request_action()
                self.request_action = None
            self.after(100, self.monitor_test)
        else:
            # Test is complete
            self.thread = None
            for button in self.test_buttons:
                button["state"] = tk.NORMAL

    def print(self, *lines):
        """Print lines in scrolled text area."""
        for line in lines:
            self.text.insert(tk.END, line + "\n")
        self.update()
 
    def request(self, action):
        """Use to open dialogs in the GUI.  The test thread cannot do GUI things like open a dialog.
        action is a function closure that gets executed in the GUI thread.
        """
        self.request_action = action
        while self.request_action is not None:
            time.sleep(0.1)
        return self.request_reply
 
 
window = MainWindow()
help(window)
window.add_test("Help", help)
window.add_test("Countdown", countdown, 5)
window.add_test("Voltage Test", voltage_test)
window.add_test("Voltage Test: 1.0V", voltage_test, 1)
window.add_test("Voltage Test: 1.5V", voltage_test, 1.5)
window.add_test("Voltage Test: 2.0V", voltage_test, 2)
window.add_test("Voltage Test: 5.0V", voltage_test, 5)
window.mainloop()
The window is kind of a generic test runner, and you write tests as functions. The test functions are added to the runner using the "add_test()" method. This makes a button in the runner GUI. Pressing the button runs the test. The runner runs the test in a separate thread so you can do things like block waiting to read a serial port without it affecting how the GUI runs. The runner has a request function that lets the test pop up tkinter dialogs. This cannot be done in the test thread, so the request function passes the request on to the GUI thread which executes the request and returns the response.

Quote:No I didn't see it until now,
this is something very close to the idea I was in my head, but definitely this piece of code is going to help a lot
thanks
for you question, I'm trying to do this in GUI because the equipment is not mine, it's a requirement.
so, I'll try and keep you posted
thanks a lot
Reply


Messages In This Thread
tkinter - by juliolop - Sep-11-2020, 12:28 PM
RE: tkinter - by Larz60+ - Sep-11-2020, 04:41 PM
RE: tkinter - by juliolop - Sep-15-2020, 12:32 PM
RE: tkinter - by juliolop - Sep-14-2020, 07:54 PM
RE: tkinter - by Larz60+ - Sep-15-2020, 02:49 PM
RE: tkinter - by Knight18 - Sep-15-2020, 03:38 PM
RE: tkinter - by juliolop - Sep-16-2020, 01:59 PM
RE: tkinter - by juliolop - Sep-16-2020, 07:26 PM
RE: tkinter - by deanhystad - Sep-16-2020, 06:23 PM
RE: tkinter - by juliolop - Sep-16-2020, 06:37 PM
RE: tkinter - by deanhystad - Sep-16-2020, 06:53 PM
RE: tkinter - by deanhystad - Sep-17-2020, 05:06 PM
RE: tkinter - by juliolop - Sep-23-2020, 06:24 PM
RE: tkinter - by juliolop - Mar-22-2023, 07:40 PM
RE: tkinter - by deanhystad - Mar-24-2023, 03:25 AM
RE: tkinter - by juliolop - Apr-05-2023, 04:51 PM

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020