用传统方式调用函数会产生良好的结果,gui tkinter调用函数会引发异常

时间:2019-04-20 22:39:29

标签: python tkinter

我遇到了奇怪的问题。我的自动贩卖机上的tkinter的GUI较为庞大。 Mya商品的ID从30到50。我想通过调用getPriceOfGivenID方法来获取给定ID的价格。我的意思是,如果我按按钮3 + 1,我将正确获得31,因此我想通过单击proceed按钮来获得31个项目的ID。可惜它抛出异常,不知道为什么。如果我从同一文件中调用函数,则从VendingMachine.py中调用它会给我很好的结果。为什么会这样?

VendingMachine.py

from Coin import Coin
from Bank import Bank
from Item import Item
from decimal import *
from Automat import Automat
from tkinter import *
from tkinter import ttk

x1 = Coin(Decimal("0.01"))
x2 = Coin(Decimal("0.02"))
x3 = Coin(Decimal("0.05"))
x4 = Coin(Decimal("0.1"))
x5 = Coin(Decimal("0.2"))
x6 = Coin(Decimal("0.5"))
x7 = Coin(Decimal("1"))
x8 = Coin(Decimal("2"))
x9 = Coin(Decimal("5"))
listOfCoins = [x1, x2, x3, x4, x5, x6, x7, x8, x9]

bank = Bank()
for x in range(15):
    for i in listOfCoins:
        bank.addMoney(i)
Cola = Item(2) #cola prize is 2
Water = Item(1) #water prize is 1 etc.
Pepsi = Item(0.5)
SparklingWater = Item(0.25)
Cola2 = Item(1.3)
Cola3 = Item(2.5)
Cola4 = Item(2.45)
Cola5 = Item(3)
container = Automat(bank)
listOfItems = [Cola, Cola2, Cola3, Cola4, Cola5, Water, Pepsi, SparklingWater]

for i in listOfItems:
    container.add_object(i)

gui = Tk()
gui.geometry('600x500')
gui.title("Vending Machine")

gui.configure(background="light green")
expression = ""
equation = StringVar()
expression_field = Entry(gui, textvariable=equation)
expression_field.grid(row=8, columnspan=4, ipadx=70)
equation.set('enter number of item')

labelOne = ttk.Label(gui, text='')
labelOne.grid(column=1, row=12)

labelTwo = ttk.Label(gui, text='')
labelTwo.grid(column=1, row=18)


def dropCoin(wartosc):
    labelTwo.configure(text='Wrzucono: {0:0.2f}'.format(container.howManyCoinsWereDropped(wartosc)))


def getPriceOfGivenID():
    a = equation.get()
    print(a) # it gives good result, for example 30
    labelOne.configure(text='You need to give: ' + container.find_price_of_given_id(a)) # it throws an exception

print(container.find_price_of_given_id(31)) # it gives good result 

# Function to update expressiom
# in the text entry box
def press(num):
    global expression
    expression = expression + str(num)
    equation.set(expression)
    return expression


##### BUTTONS
button1 = Button(gui, text=' 1 ', fg='black', bg='red',
                 command=lambda: press(1), height=1, width=7)
button1.grid(row=2, column=0)

button2 = Button(gui, text=' 2 ', fg='black', bg='red',
                 command=lambda: press(2), height=1, width=7)
button2.grid(row=2, column=1)

button3 = Button(gui, text=' 3 ', fg='black', bg='red',
                 command=lambda: press(3), height=1, width=7)
button3.grid(row=2, column=2)

button4 = Button(gui, text=' 4 ', fg='black', bg='red',
                 command=lambda: press(4), height=1, width=7)
button4.grid(row=3, column=0)

button5 = Button(gui, text=' 5 ', fg='black', bg='red',
                 command=lambda: press(5), height=1, width=7)
button5.grid(row=3, column=1)

button6 = Button(gui, text=' 6 ', fg='black', bg='red',
                 command=lambda: press(6), height=1, width=7)
button6.grid(row=3, column=2)

button7 = Button(gui, text=' 7 ', fg='black', bg='red',
                 command=lambda: press(7), height=1, width=7)
button7.grid(row=4, column=0)

button8 = Button(gui, text=' 8 ', fg='black', bg='red',
                 command=lambda: press(8), height=1, width=7)
button8.grid(row=4, column=1)

button9 = Button(gui, text=' 9 ', fg='black', bg='red',
                 command=lambda: press(9), height=1, width=7)
button9.grid(row=4, column=2)

button0 = Button(gui, text=' 0 ', fg='black', bg='red',
                 command=lambda: press(0), height=1, width=7)
button0.grid(row=5, column=1)


mainframe = ttk.Frame(gui)

gui.mainloop()

Automat.py

from Item import Item
from NoItemException import NoItemException
from Bank import Bank
from Coin import Coin
from decimal import *

class Automat:
    item_id = 30

    def __init__(self, _bank, objects=None):
        self.bank = _bank
        if objects is None:
            objects = {}
        self.objects = objects
        self._purchaseItemBank = []

    def add_object(self, obj: Item):
        id_to_assign = Automat.item_id
        self.objects.update({id_to_assign: obj})
        Automat.item_id = Automat.item_id + 1
        return id_to_assign

    def get_length(self):
        return len(self.objects)

    def find_price_of_given_id(self, item_id):
        print(item_id) #it gives good passed item_id
        if self.objects.get(item_id) is not None: #throw an exception if call from gui app, if call within normal way print(container.find_price_of_given_id(31)) gives good result
            return self.objects.get(item_id).get_price()
        else:
            raise NoItemException

    def find_amount_of_given_id(self, item_id):
        if self.objects.get(item_id) is not None:
            return self.objects.get(item_id).get_amount()
        else:
            raise NoItemException

如果我在VendingMachine.py做这样的事情

print(container.find_price_of_given_id(31))

那我得到了很好的结果。

Stacktrace:

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\ProgramData\Anaconda3\lib\tkinter\__init__.py", line 1705, in __call__
    return self.func(*args)
  File "C:/Users/Admin/PycharmProjects/vending-machine/VendingMachine.py", line 117, in <lambda>
    command=lambda: getPriceOfGivenID(), height=1, width=7)
  File "C:/Users/Admin/PycharmProjects/vending-machine/VendingMachine.py", line 62, in getPriceOfGivenID
    labelOne.configure(text='Musisz wrzucić: ' + container.find_price_of_given_id(a))
  File "C:\Users\Admin\PycharmProjects\vending-machine\Automat.py", line 32, in find_price_of_given_id
    raise NoItemException
NoItemException.NoItemException

我也粘贴Item.py,不知道是否需要,但是...:

class Item:
    def __init__(self, price, amount=5):
        self.amount = amount
        self.price = price

    def get_price(self):
        return self.price

    def get_amount(self):
        return self.amount

    def decrease(self):
        self.amount -= 1

    def __str__(self):
        return f"{self.amount} @ {self.price}"

1 个答案:

答案 0 :(得分:2)

这是类型不匹配的情况。特别是,您在objects类中的字典Automat使用int作为键。稍后,当您执行查找时,您将使用equation.get()传递的值。现在,equation是一个StringVar,当您对其执行str时,它将返回get()

请注意,在python中,您可以使用带数字或字符串键的字典,但是它们是不同的键:

{'1': 'this key is a string', 1: 'this key is an int'}

进行修复的几种不同方法,但是从本质上讲,您需要确保使用int执行查找。

一个例子是:

def getPriceOfGivenID():
    a = int(equation.get())
    ... # rest of your core

或者,您可以在find_price_of_given_idfind_amount_of_given_id内进行转换,也可以更改add_object方法并将键定义为str