2017-07-24 121 views
1

我正在使用計算器,並且遇到了有關我的鍵綁定的問題。在我的GUI類的啓動結束時,會創建一個消息框來解釋對用戶的綁定。具有諷刺意味的是,這會導致所有綁定在消息框關閉之前不作出響應,並且tkinter窗口被取消選擇然後重新選擇。綁定編碼是這樣的:Tkinter鍵綁定在消息框後不工作

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

我試圖使用focus_set()但它沒有幫助。消息框關閉後,我能做些什麼來使鍵盤綁定立即響應?

這是我的上下文的完整代碼。

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

您發佈的代碼無法運行('NameError:name'messagebox'is not defined') –

+0

當我修復缺少的導入時,它對我來說工作正常。你在哪個平臺上運行? –

+0

@Bryan:即使添加了缺少的「輸入」,Win 7也不適用於我。綁定的鍵不起作用(即使您手動將鍵盤窗口變爲焦點)。 @Sierra Mountain Tech的答案解決了這個問題(也沒有別的)。 – martineau

回答

2

Tkinters消息框需要分別輸入:

from tkinter import messagebox

然後添加以下爲您的綁定信息框的下面那條線:

master.focus_force()

這將焦點移至在用戶關閉消息箱和所有綁定之後回到根窗口將繼續工作。

+1

那麼''master.focus_force()'就夠了。不需要全部改爲'self.master'。另外,關於messagebox,它不在你的最後。這就是它的工作原理。答案如下,解釋它。 https://stackoverflow.com/questions/24738104/python-tkinter-8-5-import-messagebox – Lafexlos

+0

我認爲這將是一個問題,首先將它定義爲類屬性使用主參數。我覺得只有在它不是問題時纔會被調用。 –

+0

我認爲如果你更專注於使代碼工作的必要性,這個答案會更好。將主人更改爲self.master與問題完全無關,並且很難看出重大變化。 –