[Tutor] Dynamic variables changed via Tkinter button

Alan Gauld alan.gauld at yahoo.co.uk
Sun Apr 19 07:08:48 EDT 2020


On 18/04/2020 15:22, Jon Davies wrote:

> 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)".  

The currency*price value only needs to be calculated one when the
currency is selected. So in your selectCurrency event handler you should
set the currency symbol and a fuel_rate attribute in your controller
class. Then in the fuelling update method use fetch the rate from the
controller and do the multiplication using that rate.


See below for what I've tried to implement.
> 
>     def update(self):
>         self.fuelcount += 0.1
>         self.pricecount += 0.1 * (self.currency * PETROL_PRICE)

The price should not increment it should be calculated.
          self.price = self.controller.fuel_rate * self.fuelcount


>         self.litre_lbl['text'] = "Litres = %f" % self.fuelcount
>         self.price_lbl['text'] = "Price = %f" % self.price
>         self.update_idletasks()
>         if self.state == 'working':
>             self.lever_btn.after(100, self.update)

> The code doesn't seem to recognise self.currency (starting that 
> AttributeError: 'BeginFuellingPage' object has no attribute 'currency'). 

Where did you set the currency? Was it in the fuelling object or in
another class instance? Any data that you want to share between your
objects will need to go into the controller object since it is the
only thing that all the other objects can see. (This is one reason I
don't like this style of GUI design, the controller becomes the owner
of lots of data that should really be in the other objects.)


> 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()

As Peter has pointed out you don't need or want lots of separate methods
to set currency. You just want one that gets called with the appropriate
currency. That method is the one that should notify the controller of
the selected currency and the exchange_rate. The controller can then
calculate the fuel_price based on its
base rate * exchange_rate.

In an ideal world the knowledge about currency and rates would stay in
the Currency object and the controller methods would query it from
there. So you would have a get_exchange_details() method in the
controller, called by the Fuelling object. And that method would fetch
the currency symbol and exchange rate from the currency object.
But that frankly complicates matters, so for now just put the data
in the controller...

-- 
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.amazon.com/author/alan_gauld
Follow my photo-blog on Flickr at:
http://www.flickr.com/photos/alangauldphotos




More information about the Tutor mailing list