import tkinter as tk from tkinter import ttk import threading from .serial_reader import WeightReader from .config import DEFAULT_CALIB, DISPLAY_TYPES class WeightApp(tk.Tk): def __init__(self, weight_reader): super().__init__() self.weight_reader: WeightReader = weight_reader self.toolbar = tk.Frame(self, padx=10) self.toolbar.pack(side=tk.LEFT) #### Connection Settings #### self.connection_settings = tk.Frame(self.toolbar, pady=10) self.scan_ports_button = ttk.Button(self.connection_settings, text="Scan Devices", command=self.update_devices) self.scan_ports_button.pack() self.port_label = ttk.Label(self.connection_settings, text="Port:") self.port_label.pack(side=tk.LEFT) self.port = ttk.Combobox(self.connection_settings, values=[]) self.update_devices() self.port.pack(side=tk.LEFT) self.connection_settings.pack() self.connect_button = ttk.Button(self.toolbar, text="Connect", command=self.connect) self.connect_button.pack() #### Weight Reader Settings #### self.reader_settings = tk.Frame(self.toolbar, pady=30) self.reader_settings.pack() self.calib_factor = tk.Frame(self.reader_settings) self.calib_factor.pack() self.calib_label = ttk.Label(self.calib_factor, text="Calibration Factor:") self.calib_label.pack() self.calib_weight = ttk.Combobox(self.calib_factor, values=[100], width=5) self.calib_weight.set(100) self.calib_weight.pack(side=tk.LEFT) self.calib_measurements = ttk.Entry(self.calib_factor) self.calib_measurements.insert(0, DEFAULT_CALIB) self.calib_measurements.pack(side=tk.LEFT) self.update_calib_button = ttk.Button(self.reader_settings, text="Update Calibration", command=self.update_calib) self.update_calib_button.pack() self.display_type = tk.Frame(self.toolbar, pady=20) self.display_type.pack() self.display_type_label = ttk.Label(self.display_type, text="Visual:") self.display_type_label.pack(side=tk.LEFT) self.display_type_select = ttk.Combobox(self.display_type, values=[t.value for t in DISPLAY_TYPES]) self.display_type_select.set(DISPLAY_TYPES.NUMBER.value) self.display_type_select.pack(side=tk.LEFT) #### Display #### self.main_frame = tk.Frame(self, width=144, height=168, padx=50) self.main_frame.pack(side=tk.RIGHT) #### Actions #### self.actions = tk.Frame(self.main_frame) self.actions.pack() self.tare_button = ttk.Button(self.actions, text="Tare", command=self.weight_reader.tare) self.tare_button.pack() self.canvas = tk.Canvas(self.main_frame, width=144, height=168, background='white') self.canvas.pack() self.label = self.canvas.create_text(50, 68, text="0.0 g", font=("Arial", 18), fill='black', justify='left') self.update_weight_display() self.focus_force() def connect(self): if self.weight_reader.serial is None: port = self.port.get() self.weight_reader.connect(port) self.connect_button.config(text="Disconnect") self.connection_settings.pack_forget() else: self.weight_reader.disconnect() self.connect_button.config(text="Connect") self.connect_button.pack_forget() self.reader_settings.pack_forget() self.actions.pack_forget() self.connection_settings.pack() self.connect_button.pack() self.reader_settings.pack() self.actions.pack() def update_devices(self): self.weight_reader.scan_devices() self.port.config(values=self.weight_reader.ports) if len(self.weight_reader.ports) > 0: self.port.set(self.weight_reader.ports[0]) def update_calib(self): self.weight_reader.calib_factor = self.calib_weight.get() / float(self.calib_measurements.get()) def update_weight_display(self): weight = self.weight_reader.value self.canvas.itemconfig(self.label, text=f"{weight:.1f} g") self.after(100, self.update_weight_display) def main(): weight_reader = WeightReader() threading.Thread(target=weight_reader.read_weights, daemon=True).start() app = WeightApp(weight_reader) app.protocol("WM_DELETE_WINDOW", lambda: on_closing(app, weight_reader)) app.mainloop() def on_closing(app, weight_reader): weight_reader.stop() app.destroy() if __name__ == "__main__": main()