2017-07-24 4 views
1

Ich arbeite an einem Taschenrechner und ich habe ein Problem in Bezug auf meine Schlüssel-Bindungen aufgetreten. Am Ende der Einführung meiner GUI-Klasse wird ein Meldungsfeld erstellt, das die Bindungen an den Benutzer erläutert.Tkinter-Schlüssel funktioniert nicht nach Meldungsfeld

messagebox.showinfo("Guide", "Key bindings include: 1, 2, 3, 4, 5, 6, 7, 8, 9, 
0, ., +, -, *, /, (,), Enter, Backspace, Insert and Delete.") 

Ironischerweise bewirkt, dass alle der Bindungen nicht reagieren, bis das Meldungsfeld geschlossen und das tkinter Fenster abgewählt wird dann wieder angewählt. Die Bindungen sind wie folgt codiert:

Ich habe versucht, focus_set() zu verwenden, aber es hilft nicht. Was kann ich tun, damit meine Tastaturbindungen sofort reagieren, nachdem das Meldungsfeld geschlossen wurde?

Hier ist die Gesamtheit meines Codes für Kontext.

from tkinter import * 
from tkinter.ttk import * 
from tkinter import messagebox # added by @martineau 

class Logic: 
    def add_digit(self, *args): 
     if type(args[0]) == str: 
      self.expression.append(args[0]) 
     else: 
      self.expression.append(args[0].char) 
     self.labels[1].config(text="".join(self.expression)) 

    def add_operation(self, *args): 
     if type(args[0]) == str: 
      self.expression.append(args[0]) 
     else: 
      self.expression.append(args[0].char) 
     self.labels[1].config(text="".join(self.expression)) 

    def add_answer(self, *args): 
     self.expression.extend(list(self.labels[0]['text'])) 
     self.labels[1].config(text="".join(self.expression)) 

    def delete(self, *args): 
     if self.expression: 
      self.expression = list() 
      self.labels[1].config(text="".join(self.expression)) 
     else: 
      self.labels[0].config(text="") 

    def back(self, *args): 
     self.expression = self.expression[:-1] 
     self.labels[1].config(text="".join(self.expression)) 

    def equals(self, *args): 
     equation = list() 
     number = list() 

     if not self.expression: 
      self.labels[0].config(text='') 

     for value in self.expression: 
      if value in self.numpad_texts: 
       number.append(value) 
      else: 
       if number: 
        equation.append(str(float("".join(number)))) 
        number = list() 
       equation.append(value) 

     if number: 
      try: 
       equation.append(str(float("".join(number)))) 
      except ValueError: 
       messagebox.showerror("Error", "Syntax error: Your expression has incorrect syntax") 

     for i in range(len(equation)): 
      if equation[i] == '(' and i != 0: 
       if equation[i-1] not in self.operation_texts: 
        equation.insert(i, '*') 
      elif equation[i] == ')' and i != len(equation)-1: 
       if equation[i+1] not in self.operation_texts: 
        equation.insert(i+1, '*') 

     if equation: 
      try: 
       self.labels[0].config(text=str(eval(''.join(equation)))) 
      except ZeroDivisionError: 
       messagebox.showerror("Error", "Zero division error: Your expression has a division by zero") 
      except SyntaxError: 
       messagebox.showerror("Error", "Syntax error: Your expression has incorrect syntax") 

class GUI(Logic): 
    numpad_texts = ('7', '8', '9', '4', '5', '6', '1', '2', '3', '0', '.', 'Equals') 
    operation_texts = ('/', '*', '-', '+', '(', ')') 
    function_texts = ('Delete', 'Back') 

    def __init__(self, master): 
     master.title('Calculator') 

     self.expression = list() 

     self.label_frame = Frame(master) 
     self.label_frame.grid(columnspan=2) 

     self.labels = list() 

     for i in range(2): 
      self.labels.append(Label(self.label_frame)) 
      self.labels[i].grid(row=i, column=0, columnspan=4) 

     self.labels[0].bind("<Button-1>", self.add_answer) 

     self.numpad_frame = Frame(master) 
     self.numpad_frame.grid(row=1, rowspan=2) 

     self.numpad_buttons = list() 

     for i in range(len(self.numpad_texts)): 
      self.numpad_buttons.append(Button(self.numpad_frame, text=self.numpad_texts[i], command=lambda i=i: self.add_digit(self.numpad_texts[i]))) 
      self.numpad_buttons[i].grid(row=i//3, column=i%3) 
      if self.numpad_texts != 11: 
       master.bind(self.numpad_texts[i], self.add_digit) 

     self.numpad_buttons[-1].config(command=self.equals) 

     self.operations_frame = Frame(master) 
     self.operations_frame.grid(row=1, column=1) 

     self.operation_buttons = list() 

     for i in range(len(self.operation_texts)): 
      self.operation_buttons.append(Button(self.operations_frame, text=self.operation_texts[i], command=lambda i=i: self.add_operation(self.operation_texts[i]))) 
      self.operation_buttons[i].grid(row=i//2, column=i%2) 
      master.bind(self.operation_texts[i], self.add_operation) 

     self.functions_frame = Frame(master) 
     self.functions_frame.grid(row=2, column=1) 

     self.function_buttons = list() 

     for i in range(len(self.function_texts)): 
      self.function_buttons.append(Button(self.functions_frame, text=self.function_texts[i])) 
      self.function_buttons[i].grid(row = 0, column=i%2) 

     self.function_buttons[0].config(command=self.delete) 
     self.function_buttons[1].config(command=self.back) 

     master.bind('<Delete>', self.delete) 
     master.bind('<BackSpace>', self.back) 
     master.bind('<Return>', self.equals) 
     master.bind('<Insert>', self.add_answer) 

     messagebox.showinfo("Guide", "Key bindings include: 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, ., +, -, *, /, (,), Enter, Backspace, Insert and Delete.") 

if __name__ == '__main__': 
    root = Tk() 
    calculator = GUI(root) 
    root.mainloop() 
+0

Der von Ihnen gepostete Code wird nicht ausgeführt ('NameError: Name 'messagebox' ist nicht definiert') –

+0

Alles funktioniert gut für mich, wenn ich den fehlenden Import behebe. Auf welcher Plattform laufen Sie? –

+0

@Bryan: Es funktioniert nicht für mich auf Win 7 auch mit dem fehlenden 'Import' hinzugefügt. Die gebundenen Tasten funktionieren nicht (auch wenn Sie das Tastaturfenster manuell fokussieren). @Sierra Mountain Tech's Antwort behebt das (und nichts anderes). – martineau

Antwort

2

Tkinters messagebox muss separat importiert werden:

from tkinter import messagebox

Dann die folgende unterhalb der Linie für Ihre Bindungen messagebox hinzufügen:

master.focus_force()

Dies wird den Fokus Zurück zum Hauptfenster, nachdem der Benutzer die Nachrichtenbox und alle Ihre Bindungen geschlossen hat wird weiter arbeiten.

+1

Nun, 'master.focus_force()' ist jedoch genug. Es ist nicht nötig, alle in 'self.master' zu ändern. Auch über MessageBox ist es nicht an deinem Ende. So funktioniert das. Folgende Antwort, erklärt es. https://stackoverflow.com/questions/24738104/python-tkinter-8-5-import-messagebox – Lafexlos

+0

Ich dachte, es wäre ein Problem, das Master-Argument zu verwenden, indem man es zuerst als Klassenattribut definiert. Ich nehme an, dass es nur aufgerufen wird, wenn es kein Problem ist. –

+0

Ich denke, diese Antwort wäre besser, wenn Sie sich mehr auf das konzentrieren würden, was notwendig ist, damit der Code funktioniert. Der Wechsel von Master zu self.master ist völlig unabhängig von dem Problem und macht es schwieriger zu sehen, was die wesentlichen Änderungen sind. –