Python Forum
Checkbuttons Variables Truth Value
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Checkbuttons Variables Truth Value
#1
Debug Help Request:
My checkbuttons don't seem to have any effect on my associated variables. If I click "display bill" without selecting anything it still shows a total of everything on the menu. I tried initializing a variable as "False", but that didn't help.

# Jimmy, "Order Up" demonstration of Dawson Chapter10 Tkinter concepts.

from tkinter import *

class Application(Frame):
    def __init__(self, master):
        """ Initialize frame. """
        super(Application, self).__init__(master)
        self.grid()
        self.create_widgets()

    def create_widgets(self):
        Label(self, text = "Please select a drink:").grid(row = 0, column = 0)

        # create water check buttons
        self.water = BooleanVar()
        Checkbutton(self,
                    text = "Water, $1",
                    variable = self.water,
                    ).grid(row = 0, column = 1)

        # create orange juice check button.
        self.orange_juice = BooleanVar()
        #self.orange_juice = False
        Checkbutton(self,
                    text = "Freshly Squeezed Orange Juice, $2",
                    variable = self.orange_juice
                    ).grid(row = 0, column = 2)

        # create button to display bill.
        Button(self,
               text = "Click to display bill.",
               command = self.display_bill,
               ).grid(row = 1, column = 0, columnspan = 3)

        # create box ti display bill in.
        self.bill_txt = Text(self, width = 75, height = 10, wrap = WORD)
        self.bill_txt.grid(row = 100, column = 0, columnspan = 4)


    def display_bill(self):
        self.calculate_bill()
        self.bill_txt.delete(0.0, END)
        self.bill_txt.insert(0.0, self.total)

    def calculate_bill(self):
        self.total = 0
        if self.water:
            self.total += 1
        if self.orange_juice:
            self.total += 2

root = Tk()
root.title("Jimmy's Diner")
app = Application(root)
root.geometry("3000x3000")
root.mainloop()
Thank you!
Reply
#2
self.water is a BoolVar. self.water.get() is the value of the BoolVar. self.water is not None, so "if self.water" will always be true.
Reply
#3
Thanks so much!

Update:
As an exercise, I tried to recreate the program without using OPP (without creating my own special class "Application"). Now it always displays the total as $0. Can I not make command = display_bill() like I did? (Line 40)

# Jimmy B, "Order Up" demonstration of Dawson Chapter10 Tkinter concepts.
# order_up_alternate experiments without using OOP.

from tkinter import *

root = Tk()
root.geometry("2000x2000")
app = Frame(root)
app.grid()
root.title("Order_Up_Alternate")

# display drinks
Label(app,
      text = "Please select a drink: ",
      ).grid(column = 0, row = 0)

water = BooleanVar()
Checkbutton(app, text = "Water: $1", variable = water).grid(row = 1, column = 0)

oj = BooleanVar()
Checkbutton(app, text = "Freshly squeezed OJ: $2").grid(row = 2, column = 0)

bill_txt = Text(app, width = 10, height = 10)
bill_txt.grid(row = 3, column = 0)


def display_bill():
      total = calculate_bill()
      bill_txt.delete(0.0, END)
      bill_txt.insert(0.0, total)

def calculate_bill():
      total = 0
      if water.get():
            total += 1
      if oj.get():
            total += 2
      return total

Button(app, text = "Calculate Your Bill", command = display_bill()).grid(row = 4, column = 0)


root.mainloop()
Reply
#4
Your code never calls display_bill because you buund the button incorrectly. command=display_bill, not command=display_bill(). The oj checkbutton does not work because you did not bind it to the oj variable.

These are really simple problems to find. You need to develop some debugging skills so you aren't waiting for someone to answer questions on the forum.

The first thing I did with your program was add a print statement to calculate_bill
def calculate_bill():
    total = 0
    if water.get():
        total += 1
    if oj.get():
         total += 2
    print('calculate bill', water, water.get(), oj.get(), total)
    return total
When I ran the program I saw this right away, before pressing any buttons.
Output:
calculate bill PY_VAR0 False False 0
Then I pressed some buttons and I could not see the message again.

That provided some information. Why was the calculate_bill called immediately? Why didn't pressing the "Calculate Your Bill" button call calculate_bill? The reason for both of these is because of this:
Button(app, text = "Calculate Your Bill", command = display_bill()).grid(row = 4, column = 0)
This is a really easy error to make. You are using a function and it is very natural to add the brackets, but what does adding brackets after the function name do? It calls the function and returns the result. The result of display_bill is None (you can verify that with a print statement too). So your Button command was actually:
Button(app, text = "Calculate Your Bill", command = None)).grid(row = 4, column = 0)
Next I played with the check boxes. Water works, but OJ does not. My print statement shows oj is False even when the OJ check button was checked. I look at where the check button is created and I see this:
oj = BooleanVar()
Checkbutton(app, text = "Freshly squeezed OJ: $2").grid(row = 2, column = 0)
You create a variable for oj, but there is no "variable=oj" when you make the Checkbutton.

As for OOP or no OOP, using a class does not make object oriented programming. OOP is a design philosophy. You can write OOP machine language code. I wrote OOP C programs before OOP became a thing. It felt natural to organize my code into entities (objects) that had data (attributes/properties) and operations (functions/methods). If my entities did similar thing it made sense to reuse code and data structures (inheritance). If I had collections of similar entities it made sense to treat them generically based on their similarities (interface).

OOP makes sense for many kinds of problems. For your problem your objects would be your inventory. Solving your problem in a more OOP way I would create a class for each type of thing you sell. The item would know it's name and price so I could write a generic menu function that displays available items and prices, and a generic order function that calculates the cost of the order. I would drop the check boxes because I want to sell more than 1.

I could write this OOP version of your program without using a single class. My inventory items could be implemented using a dictionary. My inventory a list of inventory dictionaries, my menu and orders being a window and a function. No classes to be seen, but it would still be OOP.
Reply
#5
Thank you for the debugging help. I didn't know that print statements like you demonstrated would show up in the terminal window. I will work on generalizing it more like you suggested.
Cheers
Reply
#6
I've attempted to make everything more general, where all one has to do is add a new entry into the dictionary of item:cost to update the program.

However, I'm having an interesting issue with for loops. I'm trying to iterate over each item in the dictionary, and then create an Entry widget (for the users to enter how many of that item they would like) but in the example below Python doesn't understand that I want my entry widget to have the name of the particular dictionary item of that iteration:

 self.menu = {"Water": 1, "OJ": 2}
        row = 1
        for item in self.menu:
            Label(self, text = item + ": $" + str(self.menu[item]),
                  ).grid(row = row, column = 0, sticky = W)

            self.item = Entry(self)
            self.item.grid(row = row, column = 0)
            row += 1
       


In my text editor when I hover over the text "item" in self.item it doesn't highlight the same "item" in for item in self.menu so I know it's not relating the two. Any ideas how on to create all my Entry widgets using a for loop?
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Trying to get help with checkbuttons pythonprogrammer 1 1,738 Mar-25-2020, 05:09 PM
Last Post: deanhystad

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020