Python 带移位功能的 Tkinter 计算器 类
Python Tkinter Calculator with shift function and Classes
我对 Python 有点陌生,对 class 结构非常陌生。我正在尝试构建一个带有按钮的计算器 GUI,这些按钮将一个值插入到一个条目显示中。我的计算器在不使用 class 结构的情况下工作(功能代码在下面),但我试图在合并 classes 的同时使相同的代码工作。我这样做的原因是添加一个 "shift" 函数来更改按钮上文本的值,以及它们插入显示的值(与文本相同)。您在下面看到的值是 class 变量,为了更改按钮上的文本,按下 shift 按钮会更改变量的值(我已经让它在非 tkinter 中工作没有按钮的文件等)。问题是我得到的 GUI 带有一个条目和两个按钮(好)和条目中的“1”。 (不好)按钮也没有做任何事情。这是我的代码:(第一个起作用的代码)
from tkinter import *
import parser
import math
root = Tk()
root.title('Calculator')
displayb = Entry(root)
displayb.grid(row = 3, columnspan = 6, ipady = 7, ipadx = 100)
def display(e):
global i
i = len(displayb.get())
displayb.insert(i,e)
one = Button(root, text = '1', width = 10, height = 1, command = lambda : display(1))
one.grid(row = 4, column = 0)
root.mainloop()
新代码:
from tkinter import *
import parser
class Calc:
text1 = '1'
shft = 'shft1'
def __init__(self,master):
self.master = master
self.displaya = Entry(master)
self.displaya.grid(row = 1, columnspan = 6)
self.one = Button(master, text = Calc.text1, command = self.display((Calc.text1)))
self.one.grid(row = 4, column = 1)
self.update = Button(master, text = Calc.shft, command = self.update((Calc.shft[4:5])))
self.update.grid(row = 0, column = 0)
def update(self, mode):
if mode == 1:
Calc.text1 = 'A'
Calc.shft = 'shft2'
else:
Calc.text1 = '1'
Calc.shft = 'shft1'
return
def display(self,e):
i = len(self.displaya.get())
self.displaya.insert(i,e)
return
root = Tk()
calc = Calc(root)
root.mainloop()
你能帮我找到使我的代码正常工作的解决方案吗?谢谢
编辑:我尝试使用 StringVar()
和 .set
,但在界面上,shift 按钮没有说 shft1 甚至 shft2,而是说 "PY_VAR1"。一个按钮显示 1,但在显示中插入了 "PY_VAR0"。按下时,shift 按钮引发此错误:
Exception in Tkinter callback
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/tkinter/__init__.py", line 1699, in __call__
return self.func(*args)
File "/Users/ryanflynn/Classesmod.py", line 13, in <lambda>
self.update_button = Button(master, text = self.shft, command = lambda: self.update(int(self.shft[4:5]))) # use int()
TypeError: 'StringVar' object is not subscriptable
当您向命令参数提供函数时,您需要提供实际函数,而不是调用该函数的结果。换句话说,最后不能有 ()
。处理此问题的一种 hacky 方法是像之前那样使用 lambda
:
self.one = Button(master, text = Calc.text1, command = lambda: self.display((Calc.text1)))
一个稍微简单一点的方法是使用 functools.partial
:
from functools import partial
# ...
self.one = Button(master, text = Calc.text1, command = partial(self.display, Calc.text1))
IMO 最好的方法是制作一个真正的方法来使用。
self.one = Button(master, text = Calc.text1, command = self.one_pushed)
# ...
def one_pushed(self):
self.display(Calc.text1)
附带说明:如果您传递 'end' 作为位置,tkinter 将自动为您计算终点:
def display(self,e):
self.displaya.insert('end',e)
您的代码中几乎没有错误,这里是所有错误的列表以及您的代码的修改版本:
1st:您的按钮与您的某个功能同名,请将其更改为唯一的名称。
2nd: 除非必要,否则不要使用 class 的命名空间,而是使用 self。
3rd:调用函数只需要一组括号,否则就多余了
4th: 使用 lambda
或 functools.partial
设置带参数的命令。
5th: 你可以使用 END
(因为你做了 from tkinter import *
,否则 tkinter.END
)来指定结尾而不是做 len(self.displaya.get())
.
6th: Calc.shft[4:5]
return 是 string
而不是 int
。因此,为了获得结果,请使用 int(Calc.shft[4:5])
.
7th:我没有看到你在使用解析器,所以我不明白你为什么需要它。
8th: 不要在 return 什么都没有的函数末尾添加 return,这是多余的。因为这是所有功能的默认设置。
这是您的代码的修改(工作)版本:
from tkinter import *
class Calc:
def __init__(self,master):
self.text1 = '1' # make them self's not Calc's
self.shft = 'shft1'
self.master = master
self.displaya = Entry(master)
self.displaya.grid(row = 1, columnspan = 6)
self.one = Button(master, text = self.text1, command = lambda: self.display(self.text1)) # use lambda and single brackets
self.one.grid(row = 4, column = 1)
self.update_button = Button(master, text = self.shft, command = lambda: self.update(int(self.shft[4:5]))) # use int()
self.update_button.grid(row = 0, column = 0)
def update(self, mode):
if mode == 1:
self.text1 = 'A'
self.shft = 'shft2'
else:
self.text1 = '1'
self.shft = 'shft1'
def display(self,e):
self.displaya.insert(END,e) # use END instead
root = Tk()
calc = Calc(root)
root.mainloop()
此代码确实有效,但按钮文本不应更改
编辑:
如果您想使用字符串变量来更改文本,您还需要一个 StringVar:
from tkinter import *
class Calc:
def __init__(self,master):
self.master = master
self.displaya = Entry(master)
self.displaya.grid(row = 1, columnspan = 6)
self.text1 = StringVar(value = '1') # change to this
self.shft = StringVar(value = 'shft1')
self.one = Button(master, textvariable = self.text1, command = lambda: self.display(self.text1.get())) # Use .get()
self.one.grid(row = 4, column = 1)
self.update_button = Button(master, textvariable = self.shft, command = lambda: self.update(int(self.shft.get()[4:5])))
self.update_button.grid(row = 0, column = 0)
def update(self, mode):
if mode == 1:
self.text1.set('A') # set the variable
self.shft.set('shft2')
else:
self.text1.set('1')
self.shft.set('shft1')
def display(self,e):
self.displaya.insert(END,e) # use END instead
root = Tk()
calc = Calc(root)
root.mainloop()
我对 Python 有点陌生,对 class 结构非常陌生。我正在尝试构建一个带有按钮的计算器 GUI,这些按钮将一个值插入到一个条目显示中。我的计算器在不使用 class 结构的情况下工作(功能代码在下面),但我试图在合并 classes 的同时使相同的代码工作。我这样做的原因是添加一个 "shift" 函数来更改按钮上文本的值,以及它们插入显示的值(与文本相同)。您在下面看到的值是 class 变量,为了更改按钮上的文本,按下 shift 按钮会更改变量的值(我已经让它在非 tkinter 中工作没有按钮的文件等)。问题是我得到的 GUI 带有一个条目和两个按钮(好)和条目中的“1”。 (不好)按钮也没有做任何事情。这是我的代码:(第一个起作用的代码)
from tkinter import *
import parser
import math
root = Tk()
root.title('Calculator')
displayb = Entry(root)
displayb.grid(row = 3, columnspan = 6, ipady = 7, ipadx = 100)
def display(e):
global i
i = len(displayb.get())
displayb.insert(i,e)
one = Button(root, text = '1', width = 10, height = 1, command = lambda : display(1))
one.grid(row = 4, column = 0)
root.mainloop()
新代码:
from tkinter import *
import parser
class Calc:
text1 = '1'
shft = 'shft1'
def __init__(self,master):
self.master = master
self.displaya = Entry(master)
self.displaya.grid(row = 1, columnspan = 6)
self.one = Button(master, text = Calc.text1, command = self.display((Calc.text1)))
self.one.grid(row = 4, column = 1)
self.update = Button(master, text = Calc.shft, command = self.update((Calc.shft[4:5])))
self.update.grid(row = 0, column = 0)
def update(self, mode):
if mode == 1:
Calc.text1 = 'A'
Calc.shft = 'shft2'
else:
Calc.text1 = '1'
Calc.shft = 'shft1'
return
def display(self,e):
i = len(self.displaya.get())
self.displaya.insert(i,e)
return
root = Tk()
calc = Calc(root)
root.mainloop()
你能帮我找到使我的代码正常工作的解决方案吗?谢谢
编辑:我尝试使用 StringVar()
和 .set
,但在界面上,shift 按钮没有说 shft1 甚至 shft2,而是说 "PY_VAR1"。一个按钮显示 1,但在显示中插入了 "PY_VAR0"。按下时,shift 按钮引发此错误:
Exception in Tkinter callback
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/tkinter/__init__.py", line 1699, in __call__
return self.func(*args)
File "/Users/ryanflynn/Classesmod.py", line 13, in <lambda>
self.update_button = Button(master, text = self.shft, command = lambda: self.update(int(self.shft[4:5]))) # use int()
TypeError: 'StringVar' object is not subscriptable
当您向命令参数提供函数时,您需要提供实际函数,而不是调用该函数的结果。换句话说,最后不能有 ()
。处理此问题的一种 hacky 方法是像之前那样使用 lambda
:
self.one = Button(master, text = Calc.text1, command = lambda: self.display((Calc.text1)))
一个稍微简单一点的方法是使用 functools.partial
:
from functools import partial
# ...
self.one = Button(master, text = Calc.text1, command = partial(self.display, Calc.text1))
IMO 最好的方法是制作一个真正的方法来使用。
self.one = Button(master, text = Calc.text1, command = self.one_pushed)
# ...
def one_pushed(self):
self.display(Calc.text1)
附带说明:如果您传递 'end' 作为位置,tkinter 将自动为您计算终点:
def display(self,e):
self.displaya.insert('end',e)
您的代码中几乎没有错误,这里是所有错误的列表以及您的代码的修改版本:
1st:您的按钮与您的某个功能同名,请将其更改为唯一的名称。
2nd: 除非必要,否则不要使用 class 的命名空间,而是使用 self。
3rd:调用函数只需要一组括号,否则就多余了
4th: 使用 lambda
或 functools.partial
设置带参数的命令。
5th: 你可以使用 END
(因为你做了 from tkinter import *
,否则 tkinter.END
)来指定结尾而不是做 len(self.displaya.get())
.
6th: Calc.shft[4:5]
return 是 string
而不是 int
。因此,为了获得结果,请使用 int(Calc.shft[4:5])
.
7th:我没有看到你在使用解析器,所以我不明白你为什么需要它。
8th: 不要在 return 什么都没有的函数末尾添加 return,这是多余的。因为这是所有功能的默认设置。
这是您的代码的修改(工作)版本:
from tkinter import *
class Calc:
def __init__(self,master):
self.text1 = '1' # make them self's not Calc's
self.shft = 'shft1'
self.master = master
self.displaya = Entry(master)
self.displaya.grid(row = 1, columnspan = 6)
self.one = Button(master, text = self.text1, command = lambda: self.display(self.text1)) # use lambda and single brackets
self.one.grid(row = 4, column = 1)
self.update_button = Button(master, text = self.shft, command = lambda: self.update(int(self.shft[4:5]))) # use int()
self.update_button.grid(row = 0, column = 0)
def update(self, mode):
if mode == 1:
self.text1 = 'A'
self.shft = 'shft2'
else:
self.text1 = '1'
self.shft = 'shft1'
def display(self,e):
self.displaya.insert(END,e) # use END instead
root = Tk()
calc = Calc(root)
root.mainloop()
此代码确实有效,但按钮文本不应更改
编辑: 如果您想使用字符串变量来更改文本,您还需要一个 StringVar:
from tkinter import *
class Calc:
def __init__(self,master):
self.master = master
self.displaya = Entry(master)
self.displaya.grid(row = 1, columnspan = 6)
self.text1 = StringVar(value = '1') # change to this
self.shft = StringVar(value = 'shft1')
self.one = Button(master, textvariable = self.text1, command = lambda: self.display(self.text1.get())) # Use .get()
self.one.grid(row = 4, column = 1)
self.update_button = Button(master, textvariable = self.shft, command = lambda: self.update(int(self.shft.get()[4:5])))
self.update_button.grid(row = 0, column = 0)
def update(self, mode):
if mode == 1:
self.text1.set('A') # set the variable
self.shft.set('shft2')
else:
self.text1.set('1')
self.shft.set('shft1')
def display(self,e):
self.displaya.insert(END,e) # use END instead
root = Tk()
calc = Calc(root)
root.mainloop()