[Tutor] Dynamic variables changed via Tkinter button
Peter Otten
__peter__ at web.de
Sat Apr 18 11:52:33 EDT 2020
Jon Davies wrote:
> Hi Alan,
>
> As always, thanks for your insight - that gives me exactly the sort of
> base I was hoping to build on. I had researched on the web on whether it
> was possible, but given your note that typically this wouldn't considered
> as standard GUI behavior, explains why I maybe didn't find much (or
> perhaps I didn't look hard enough!).
>
> I've now adapted the below and implemented something similar as part of my
> wider Petrol Pump program code and I've managed to get it functioning.
>
> However, now I am looking to enhance this further (using the selected
> currency as input to a calculation, which you are already aware of).
>
> Given I need two labels (one for Fuel Price, one for Litres), I've
> implemented two counts (fuelcount and pricecount) and separated these
> within the "update" function. For the pricecount, I am looking to enable
> an increase based on "fuelcount * (currency * petrol_price)". See below
> for what I've tried to implement.
>
> def update(self):
> self.fuelcount += 0.1
> self.pricecount += 0.1 * (self.currency * PETROL_PRICE)
> self.litre_lbl['text'] = "Litres = %f" % self.fuelcount
> self.price_lbl['text'] = "Price = %f" % self.pricecount
Don't use two independent counters; count the litres of fuel only, and
calculate the price from that:
price = self.fuelcount * self.currency * PETROL_PRICE
self.price_lbl["text"] = "Price = %f" % price
(I'm not sure, but self.currency might actually have to be
self.controller.currency)
> self.update_idletasks()
> if self.state == 'working':
> self.lever_btn.after(100, self.update)
>
> I tried to configure the calculation to use the fuelcount value directly
> i.e. (0.1), but I found that this started to increase the pricecount
> exponentially, so for now I have just aligned the values at 0.1. The code
> doesn't seem to recognise self.currency (starting that AttributeError:
> 'BeginFuellingPage' object has no attribute 'currency'). If I replaced
> self.currency with a number, then it works.
>
> I am trying to reference the currency variable that was set earlier on in
> the GUI via the SelectCurrencyPage. class SelectCurrencyPage(tk.Frame):
> def __init__(self, parent, controller):
> tk.Frame.__init__(self, parent)
> self.controller = controller
>
> self.currency_lbl = tk.Label(self, text = _("PLEASE SELECT
> CURRENCY"), font = LARGE_FONT) self.currency_lbl.pack(pady = 10,
> padx = 10)
>
> self.GBP_btn = tk.Button(self, text = "£ GBP",
> command = lambda c = "£": self.setGBP(c))
> self.GBP_btn.pack()
>
> self.USD_btn = tk.Button(self, text = "$ USD",
> command = lambda c = "$": self.setUSD(c))
> self.USD_btn.pack()
>
> self.EUR_btn = tk.Button(self, text = "€ EUR",
> command = lambda c = "€": self.setEUR(c))
> self.EUR_btn.pack()
>
> self.restart_btn = tk.Button(self, text = _("RESTART"),
> command = lambda:
> self.controller.setState('restart'))
> self.restart_btn.pack()
There's a lot of redundancy here. You can simplify that with a helper
method:
def makeCurrencyButton(self, code, symbol, conversion):
button = tk.Button(
self,
text=f"{symbol} {code}",
command=lambda: self.setCurrency(conversion)
)
button.pack()
return button
>
> def setGBP(self, currency):
> self.controller.setCurrency(GBP)
> self.controller.setState('fuel')
>
> def setUSD(self, currency):
> self.controller.setCurrency(USD)
> self.controller.setState('fuel')
>
> def setEUR(self, currency):
> self.controller.setCurrency(EUR)
> self.controller.setState('fuel')
Replace these with
def setCurrency(self, conversion):
self.controller.setCurrency(conversion)
self.controller.setState("fuel")
Now
> self.GBP_btn = tk.Button(self, text = "£ GBP",
> command = lambda c = "£": self.setGBP(c))
> self.GBP_btn.pack()
>
> self.USD_btn = tk.Button(self, text = "$ USD",
> command = lambda c = "$": self.setUSD(c))
> self.USD_btn.pack()
>
> self.EUR_btn = tk.Button(self, text = "€ EUR",
> command = lambda c = "€": self.setEUR(c))
> self.EUR_btn.pack()
becomes
self.GBP_btn = self.makeCurrencyButton("GBP", "£", GBP)
self.USD_btn = self.makeCurrencyButton("USD", "$", USD)
self.EUR_btn = self.makeCurrencyButton("EUR", "€", EUR)
If you go one step further and use a list to store the (code, symbol,
conversion-rate) triples
CURRENCIES = [("EUR", "€", 1.14), ...]
and the buttons
self.currency_buttons = [
self.makeCurrencyButton(*currency)
for currency in CURRENCIES
]
it will become very easy to add or remove currencies.
Regarding your actual question, I guess that you are making a mess by using
the currency attribute for two different purposes -- but my idea of your
program is not concrete enough to tell you how to fix that, or if that even
is the correct diagnosis. You have to wait for Alan or someone else to chime
in -- or provide the complete runnable source code somewhere.
More information about the Tutor
mailing list