如何正确地将我在计算器中按下的数字插入到最后一个索引处的文本小部件中?

How do I properly insert the numbers that I pressed on in my calculator into the text widget at the last index?

例如,当我按“100”时,在文本框中输出“001”。我尝试在索引中使用 -1 但同样的事情仍然发生,我也尝试执行 .insert(0.end, num) 但它会引发错误。我怎样才能让数字总是在输出的末尾输入。此外,这是使用 tkinter 输出数字的最佳方式还是有其他方式?

from tkinter import *
import operator

window = Tk()
window.title('Calculator')

def click(num):
    output.insert(0.0, num) #numbers not properly inputted (bug)

#output for calculator
output = Text(window, font = 'none 12 bold', height = 4, width = 25, wrap = 'word')
output.grid(row = 0, column = 0, columnspan = 4, pady = 10)

###buttons
#clear and operators
b_clear = Button(window, text = 'C', width = 7, height = 3)
b_clear.grid(row = 1, column = 2, padx = (10, 0))

b_div = Button(window, text = '/', width = 7, height = 3)
b_div.grid(row = 1, column = 3, padx = 10)

b_mult = Button(window, text = '*', width = 7, height = 3)
b_mult.grid(row = 2, column = 3)

b_subt = Button(window, text = '-', width = 7, height = 3)
b_subt.grid(row = 3, column = 3)

b_add = Button(window, text = '+', width = 7, height = 3)
b_add.grid(row = 4, column = 3)

b_equal = Button(window, text = '=', width = 7, height = 3)
b_equal.grid(row = 5, column = 3, pady = (0, 10))

#numbers
b_9 = Button(window, text = '9', width = 7, height = 3, command = lambda: click(9))
b_9.grid(row = 2, column = 2, padx = (10, 0), pady = 10)

b_8 = Button(window, text = '8', width = 7, height = 3, command = lambda: click(8))
b_8.grid(row = 2, column = 1)

b_7 = Button(window, text = '7', width = 7, height = 3, command = lambda: click(7))
b_7.grid(row = 2, column = 0, padx = 10)

b_6 = Button(window, text = '6', width = 7, height = 3, command = lambda: click(6))
b_6.grid(row = 3, column = 2, padx = (10, 0))

b_5 = Button(window, text = '5', width = 7, height = 3, command = lambda: click(5))
b_5.grid(row = 3, column = 1)

b_4 = Button(window, text = '4', width = 7, height = 3, command = lambda: click(4))
b_4.grid(row = 3, column = 0)

b_3 = Button(window, text = '3', width = 7, height = 3, command = lambda: click(3))
b_3.grid(row = 4, column = 2, padx = (10, 0), pady = 10)

b_2 = Button(window, text = '2', width = 7, height = 3, command = lambda: click(2))
b_2.grid(row = 4, column = 1)

b_1 = Button(window, text = '1', width = 7, height = 3, command = lambda: click(1))
b_1.grid(row = 4, column = 0)

b_0 = Button(window, text = '0', width = 7, height = 3, command = lambda: click(0))
b_0.grid(row = 5, column = 0, pady = (0, 10))

b_decimal = Button(window, text = '.', width = 7, height = 3)
b_decimal.grid(row = 5, column = 1, pady = (0, 10))

b_negative = Button(window, text = '-', width = 7, height = 3)
b_negative.grid(row = 5, column = 2, padx = (10, 0), pady = (0, 10))

#run calculator
window.mainloop()

索引“end”表示小部件中最后一个字符之后的位置。

output.insert("end", num) 

来自官方文档:

end - Indicates the character just after the last one in the entry's string. This is equivalent to specifying a numerical index equal to the length of the entry's string.

你太辛苦了。从图形的角度来看,您必须考虑到您的按钮都是完全相同的东西。您只需几行就可以构建整个界面。由于每个按钮都会调用calc,所以只需在calc中编写条件语句来处理各种可能性。您可以在那个函数中构建计算器的全部功能。

import tkinter as tk 

window = tk.Tk()
window.title('Calculator')

#output for calculator
output = tk.Text(window, font = 'none 12 bold', height=4, width=25, wrap='word')
output.grid(row=0, column=0, columnspan=4, pady=10)

def calc(data):
    if data.isnumeric() or data == '.':
        output.insert('end', data)
    elif data in ['-', '+', '*', '/']:
        #write code for handling operators
        pass #delete this line
    elif data == '=':
        #write code for handling equals
        pass #delete this line
    elif data == 'pos':
        if output.get('1.0', '1.1') == '-':
            output.delete('1.0', '1.1') 
    elif data == 'neg':
        if output.get('1.0', '1.1') != '-':
            output.insert('1.0', '-')
    elif data in 'CE':
        if 'C' in data:
            output.delete('1.0', 'end')
        if 'E' in data:
            #clear your storage
            pass #delete this line

btn = dict(width=7, height=3)
pad = dict(padx=5, pady=5)

#all of your buttons
for i, t in enumerate(['pos', 'neg', 'C', 'CE', '7', '8', '9', '/', '4', '5', '6', '*', '1', '2', '3', '-', '0', '.', '+', '=']):
    tk.Button(window, text=t, command=lambda d=t: calc(d), **btn).grid(row=i//4+1, column=i%4, **pad)

#run calculator
window.mainloop()

我根据刚才给你的例子制作了一个完全可用的 OOP 版本的计算器。它可能并不完美。我只花了 10 分钟。我添加了键绑定,因此您不必单击按钮。你可以扩展它,从中学习,忽略它......任何让你开心的东西。

import tkinter as tk

class App(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
        self.oper   = ['/', '*', '-', '+']
        self.queue  = []
        self.result = 0
        self.equate = False
        
        self.output = tk.Text(self, font='Consolas 18 bold', height=2, width=20, wrap='word')
        self.output.grid(row=0, column=0, columnspan=4, pady=8, padx=4)
        
        btn = dict(width=6, height=3, font='Consolas 12 bold')
        pad = dict(pady=2)
        
        special = dict(neg='<Shift-Key-->',pos='<Shift-Key-+>',C='<Key-Delete>',CE='<Key-End>')
        
        for i, t in enumerate(['pos', 'neg', 'C', 'CE', '7', '8', '9', '/', '4', '5', '6', '*', '1', '2', '3', '-', '0', '.', '+', '=']):
            tk.Button(self, text=t, command=lambda d=t: self.calc(d), **btn).grid(row=i//4+1, column=i%4, **pad)
            if t.isnumeric() or t in self.oper or t == '.':
                self.bind_all(f'<Key-{t}>', lambda e, d=t: self.calc(d))
            elif t == '=':
                self.bind_all('<Return>', lambda e, d=t: self.calc(d))
            else:
                self.bind_all(special[t], lambda e, d=t: self.calc(d))
                
    def calc(self, input):
        print(input)
        if input.isnumeric() or input == '.':
            self.output.insert('end', input)
        elif input == 'pos':
            if self.output.get('1.0', '1.1') == '-':
               self.output.delete('1.0', '1.1') 
        elif input == 'neg':
            if self.output.get('1.0', '1.1') != '-':
               self.output.insert('1.0', '-')
        elif input in self.oper and (t := self.output.get('1.0', 'end-1c')):
            if not self.equate:
                self.queue.append(t)
            self.queue.append(input)
            self.output.delete('1.0', 'end')
            self.equate = False
        elif input == '=' and len(self.queue):
            self.equate = True
            if self.queue[-1] in self.oper:
                self.queue.append(self.output.get('1.0', 'end-1c'))
            elif len(self.queue) > 2:
                self.queue = self.queue+self.queue[-2:]
                    
            self.result = str(eval(' '.join(self.queue)))
            self.output.delete('1.0', 'end')
            self.output.insert('end', self.result)
        elif input in 'CE':
            if 'C' in input:
                self.output.delete('1.0', 'end')
            if 'E' in input:
                self.queue = []
            
                    
if __name__ == '__main__':
    app = App()
    app.title('Calcsturbator')
    app.resizable(width=False, height=False)
    app.mainloop()