From f1b5ff33a1c6d885ab6d229c1726e76d3df5b20e Mon Sep 17 00:00:00 2001 From: "Jason.W" Date: Fri, 5 Jul 2024 15:18:42 +0800 Subject: [PATCH] improve the layout of Debugger interface and add the button tips --- pyUI/Calibrator.py | 8 +++ pyUI/Debugger.py | 119 ++++++++++++++++++++++++++++++++---------- pyUI/SkillComposer.py | 6 ++- pyUI/UI.py | 14 ++++- pyUI/translate.py | 18 ++++++- 5 files changed, 132 insertions(+), 33 deletions(-) diff --git a/pyUI/Calibrator.py b/pyUI/Calibrator.py index c4a0b82..b6bd048 100755 --- a/pyUI/Calibrator.py +++ b/pyUI/Calibrator.py @@ -14,7 +14,14 @@ def __init__(self,model,lan): language = lan # global goodPorts connectPort(goodPorts) + start = time.time() + while config.model_ == '': + if time.time() - start > 5: + config.model_ = model + print('Use the model set in the UI interface.') + time.sleep(0.01) self.model = config.model_ + self.winCalib = Tk() self.winCalib.title(txt('calibTitle')) self.winCalib.geometry('+200+100') @@ -174,6 +181,7 @@ def closeCalib(self): # if len(goodPorts)>0: # t=threading.Thread(target=keepReadingSerial,args=(goodPorts,)) # t.start() + model = "Bittle" Calibrator(model,language) closeAllSerial(goodPorts) os._exit(0) diff --git a/pyUI/Debugger.py b/pyUI/Debugger.py index 0f50229..e3e518e 100644 --- a/pyUI/Debugger.py +++ b/pyUI/Debugger.py @@ -1,5 +1,11 @@ #!/usr/bin/python3 # -*- coding: UTF-8 -*- + +# Junfeng Wang +# Petoi LLC +# Jun. 26th, 2024 + + from commonVar import * language = languageList['English'] @@ -9,38 +15,95 @@ def txt(key): class Debugger: def __init__(self,model,lan): - self.debuggerReady = False global language language = lan # global goodPorts - + connectPort(goodPorts) + start = time.time() + while config.model_ == '': + if time.time() - start > 5: + config.model_ = model + print('Use the model set in the UI interface.') + time.sleep(0.01) self.model = config.model_ + self.winDebug = Tk() - self.winDebug.title(txt('Debugger')) - self.winDebug.geometry('296x56+200+100') - self.winDebug.resizable(False, False) - # self.calibSliders = list() + self.debuggerReady = False + self.OSname = self.winDebug.call('tk', 'windowingsystem') if self.OSname == 'win32': self.winDebug.iconbitmap(resourcePath + 'Petoi.ico') - self.voiceResetButtonW = 30 + self.winDebug.geometry('398x150+800+400') + elif self.OSname == 'aqua': + self.winDebug.geometry('+800+400') + self.backgroundColor = 'gray' else: - self.voiceResetButtonW = 20 - self.frameDebugButtons = Frame(self.winDebug) - self.frameDebugButtons.grid(row=0, column=0) - self.myFont = tkFont.Font(family='Times New Roman', size=12, weight='bold') - voiceResetButton = Button(self.frameDebugButtons, text=txt('Reset voice module'), font=self.myFont, fg = 'blue', width=self.voiceResetButtonW,command=lambda: self.resetVoice()) - voiceResetButton.grid(row=0, column=0, padx=8, pady=(10, 10)) + self.winDebug.tk.call('wm', 'iconphoto', self.winDebug._w, "-default", + PhotoImage(file= resourcePath + 'Petoi.png')) + self.winDebug.geometry('+800+400') - self.winDebug.protocol('WM_DELETE_WINDOW', self.on_closing) + self.myFont = tkFont.Font( + family='Times New Roman', size=20, weight='bold') + self.winDebug.title(txt('Debugger')) + self.createMenu() + bw = 23 + self.modelLabel = Label(self.winDebug, text=self.model, font=self.myFont) + self.modelLabel.grid(row=0, column=0, pady=10) + voiceResetButton = Button(self.winDebug, text=txt('Reset voice module'), font=self.myFont, fg='blue', width=bw, relief='raised', + command=lambda: self.resetVoice()) + voiceResetButton.grid(row=1, column=0, padx=10, pady=(0, 10)) + tip(voiceResetButton, txt('tipRstVoice')) - connectPort(goodPorts) self.debuggerReady = True - + self.winDebug.protocol('WM_DELETE_WINDOW', self.on_closing) + self.winDebug.update() + self.winDebug.resizable(False, False) self.winDebug.focus_force() # force the main interface to get focus self.winDebug.mainloop() + + + def createMenu(self): + self.menubar = Menu(self.winDebug, background='#ff8000', foreground='black', activebackground='white', + activeforeground='black') + file = Menu(self.menubar, tearoff=0, background='#ffcc99', foreground='black') + for key in NaJoints: + file.add_command(label=key, command=lambda model=key: self.changeModel(model)) + self.menubar.add_cascade(label=txt('Model'), menu=file) + + lan = Menu(self.menubar, tearoff=0) + for l in languageList: + lan.add_command(label=languageList[l]['lanOption'], command=lambda lanChoice=l: self.changeLan(lanChoice)) + self.menubar.add_cascade(label=txt('lanMenu'), menu=lan) + + helpMenu = Menu(self.menubar, tearoff=0) + helpMenu.add_command(label=txt('About'), command=self.showAbout) + self.menubar.add_cascade(label=txt('Help'), menu=helpMenu) + + self.winDebug.config(menu=self.menubar) + + + def changeModel(self, modelName): + self.model = copy.deepcopy(modelName) + self.modelLabel.configure(text=self.model) + print(self.model) + + + def changeLan(self, l): + global language + if self.debuggerReady and txt('lan') != l: + language = copy.deepcopy(languageList[l]) + self.menubar.destroy() + self.createMenu() + self.winDebug.title(txt('Debugger')) + self.winDebug.winfo_children()[1].config(text=txt('Reset voice module')) + tip(self.winDebug.winfo_children()[1], txt('tipRstVoice')) + + + def showAbout(self): + messagebox.showinfo(txt('titleVersion'), txt('msgVersion')) + self.winDebug.focus_force() - + def createImage(self, frame, imgFile, imgW): img = Image.open(imgFile) @@ -59,7 +122,7 @@ def resetVoice(self): self.showDialog() def showDialog(self): - # # Declare a global variable to access it within the function + # Declare a global variable to access it within the function # Create the dialog window self.voiceResetWin = Toplevel(self.winDebug) self.voiceResetWin.title(txt('Warning')) @@ -90,22 +153,21 @@ def showDialog(self): def getButtonClick(self, buttonValue): """Function to handle button clicks and close the window.""" self.voiceReturn = buttonValue # Assign the button value to the global variable - logger.info(f"voiceReturn is {self.voiceReturn}") # debug + logger.debug(f"voiceReturn is {self.voiceReturn}") self.voiceResetWin.destroy() # Destroy the window if self.debuggerReady == 1: if self.voiceReturn == True: if 'Chinese'in txt('lan'): - cmd = "XAb" - send(goodPorts, [cmd, 0]) - messagebox.showinfo(None, txt('Reset successfully')) + cmdList = ["XAa", "XAb"] else: cmdList = ["XAb", "XAa"] - for cmd in cmdList: - send(goodPorts, [cmd, 0]) - if cmd == "XAb": - time.sleep(2) - else: - messagebox.showinfo(None, txt('Reset successfully')) + + for cmd in cmdList: + send(goodPorts, [cmd, 0]) + if cmd == cmdList[0]: + time.sleep(2) + else: + messagebox.showinfo(None, txt('Reset successfully')) def on_closing(self): @@ -119,6 +181,7 @@ def on_closing(self): if __name__ == '__main__': goodPorts = {} try: + model = "Bittle" Debugger(model,language) closeAllSerial(goodPorts) os._exit(0) diff --git a/pyUI/SkillComposer.py b/pyUI/SkillComposer.py index 86aa47b..86073b1 100755 --- a/pyUI/SkillComposer.py +++ b/pyUI/SkillComposer.py @@ -71,8 +71,8 @@ def __init__(self,model, lan): start = time.time() while config.model_ == '': if time.time()-start > 5: - config.model_ = 'Bittle' - print('Use Bittle as default model') + config.model_ = model + print('Use the model set in the UI interface.') time.sleep(0.01) self.model = config.model_ try: @@ -666,6 +666,7 @@ def changeLan(self, l): def showAbout(self): messagebox.showinfo('Petoi Controller UI', u'Petoi Controller for OpenCat\nOpen Source on GitHub\nCopyright © Petoi LLC\nwww.petoi.com') + self.window.focus_force() def changeModel(self, modelName): if self.ready and modelName != self.model: @@ -1843,6 +1844,7 @@ def on_closing(self): # if len(goodPorts)>0: # t=threading.Thread(target=keepReadingSerial,args=(goodPorts,)) # t.start() + model = "Bittle" SkillComposer(model, language) closeAllSerial(goodPorts) os._exit(0) diff --git a/pyUI/UI.py b/pyUI/UI.py index 3837bcf..2ac412c 100755 --- a/pyUI/UI.py +++ b/pyUI/UI.py @@ -87,8 +87,11 @@ def __init__(self): self.modelLabel = Label(self.window, text=model, font=self.myFont) self.modelLabel.grid(row=0, column=0, pady=10) for i in range(len(apps)): - Button(self.window, text=txt(apps[i]), font=self.myFont, fg='blue', width=bw, relief='raised', - command=lambda app=apps[i]: self.utility(app)).grid(row=1 + i, column=0, padx=10, pady=(0, 10)) + self.moduleButton = Button(self.window, text=txt(apps[i]), font=self.myFont, fg='blue', width=bw, relief='raised', + command=lambda app=apps[i]: self.utility(app)) + self.moduleButton.grid(row=1 + i, column=0, padx=10, pady=(0, 10)) + if apps[i] == 'Debugger': + tip(self.moduleButton, txt('tipDebugger')) self.ready = True self.window.protocol('WM_DELETE_WINDOW', self.on_closing) @@ -135,6 +138,9 @@ def changeLan(self, l): self.window.title(txt('uiTitle')) for i in range(len(apps)): self.window.winfo_children()[1 + i].config(text=txt(apps[i])) + if apps[i] == 'Debugger': + tip(self.window.winfo_children()[1 + i], txt('tipDebugger')) + def saveConfigToFile(self, filename): if len(self.configuration) == 6: @@ -151,6 +157,9 @@ def saveConfigToFile(self, filename): f.close() def utility(self, app): + global model + global language + self.saveConfigToFile(defaultConfPath) logger.info(f"{self.configuration}") self.window.destroy() @@ -190,6 +199,7 @@ def on_closing(): def showAbout(self): messagebox.showinfo('Petoi Desktop App', u'Petoi Desktop App\nOpen Source on GitHub\nCopyright © Petoi LLC\nwww.petoi.com') + self.window.focus_force() def on_closing(self): if messagebox.askokcancel(txt('Quit'), txt('Do you want to quit?')): diff --git a/pyUI/translate.py b/pyUI/translate.py index d1ee81a..26370ed 100644 --- a/pyUI/translate.py +++ b/pyUI/translate.py @@ -1,5 +1,5 @@ versionNum = '1.2.1' -dateStr = '2024-07-02' +dateStr = '2024-07-05' textEN = { 'lan':'English', @@ -16,6 +16,8 @@ 'Scheduler':'Scheduler', 'Firmware Uploader':'Firmware Uploader', 'Debugger': 'Debugger', + 'tipDebugger':'Provide convinient tools to debug the robot.', + 'tipRstVoice':'Click this button to reset the voice module.', 'Eye color picker':'Eye color picker', 'Creator Information':'Creator Information', 'Creator':'Creator', @@ -286,6 +288,8 @@ 'Scheduler':'时序器', 'Firmware Uploader':'固件上载', 'Debugger': '调试器', + 'tipDebugger':'提供便捷的机器人调试工具。', + 'tipRstVoice':'点击此按钮重置语音模块。', 'Eye color picker':'眼色选择器', 'Creator Information':'创作者信息', 'Creator':'创作者', @@ -552,6 +556,8 @@ 'Scheduler':'排程器', 'Firmware Uploader':'固件上傳', 'Debugger': '調試器', + 'tipDebugger':'提供便捷的機器人除錯工具。', + 'tipRstVoice':'點擊此按鈕重設語音模組。', 'Eye color picker':'眼睛顏色選擇器', 'Creator Information':'創作者信息', 'Creator':'創作者', @@ -819,6 +825,8 @@ 'Scheduler':'Planer', 'Firmware Uploader':'Firmware-Uploader', 'Debugger': 'Debugger', + 'tipDebugger':'Bequeme Werkzeuge zur Fehlerbehebung des Roboters bereitstellen.', + 'tipRstVoice':'Klicken Sie auf diese Schaltfläche, um das Sprachmodul zurückzusetzen.', 'Eye color picker':'Augenfarbauswahl', 'Creator Information':'Erstellerinformationen', 'Creator':'Schöpfer', @@ -1091,6 +1099,8 @@ 'Scheduler':'ตัวจัดตาราง', 'Firmware Uploader':'ตัวอัปโหลดเฟิร์มแวร์', 'Debugger': 'ดีบักเกอร์ ', + 'tipDebugger':'จัดเตรียมเครื่องมือที่สะดวกสำหรับดีบักหุ่นยนต์ .', + 'tipRstVoice':'กดปุ่มนี้เพื่อรีเซ็ตโมดูลเสียง (กดปุ่มนี้เพื่อรีเซ็ตโมดูลเสียง.', 'Eye color picker':'ตัวเลือกสีตา', 'Creator Information':'ข้อมูลผู้สร้าง', 'Creator':'ผู้สร้าง', @@ -1362,6 +1372,8 @@ 'Scheduler':'Planificateur', 'Firmware Uploader':'Chargeur de firmware', 'Debugger': 'Débogueur', + 'tipDebugger':'Fournir des outils pratiques pour déboguer le robot.', + 'tipRstVoice':'Cliquez sur ce bouton pour réinitialiser le module vocal.', 'Eye color picker':'Sélecteur de couleur des yeux', 'Creator Information':'Informations sur le créateur', 'Creator':'Créateur', @@ -1632,6 +1644,8 @@ 'Scheduler':'スケジューラ', 'Firmware Uploader':'ファームウェアアップローダ', 'Debugger': 'デバッガー', + 'tipDebugger':'ロボットのデバッグに便利なツールを提供する。', + 'tipRstVoice':'このボタンをクリックして音声モジュールをリセットします。', 'Eye color picker':'目の色選択', 'Creator Information':'制作者情報', 'Creator':'制作者', @@ -1894,6 +1908,8 @@ 'Scheduler':'Sequenza', 'Firmware Uploader':'Caricatore di firmware', 'Debugger': 'Debugger', + 'tipDebugger':'Fornire strumenti convenienti per il debug del robot.', + 'tipRstVoice':'Clicca su questo pulsante per ripristinare il modulo vocale.', 'Eye color picker':'Selettore del colore degli occhi', 'Creator Information':'Informazioni sul creatore', 'Creator':'Creatore',