phucker
phucker

Reputation: 19

Python 3.4 GUI if statement with buttons

I'm trying to learn coding with python 3.4. I built this mini GUI and I'm having trouble getting it to work. It prints out 2 every time even though I press the button 1 . All I want to do is to get 1 printed out in the label when I click the button on and 2 with button two with an if statement.

from tkinter import *
root = Tk()
root.geometry("500x500")
root.title("Test")


def button_press():
    if one:
        x = 1
        display.configure(text=x)
    if two:
        x = 2
        display.configure(text=x)

display = LabelFrame(root, bg="red", width="462", height="60")
display.pack()

one = Button(root, text="1", width="15", height="5",command=button_press)
one.pack(side="left")


two = Button(root, text="2", width="15", height="5", command=button_press)
two.pack(side="left")

root.mainloop()

Upvotes: 1

Views: 10001

Answers (3)

rbaleksandar
rbaleksandar

Reputation: 9691

I haven't done any Tkinter to be honest. That said the code snippet below

if one:
    x = 1
    display.configure(text=x)
if two:
    x = 2
    display.configure(text=x)

looks like a weird thing to do. Basically you are checking if one and than two are equal or not to None. This doesn't make sense since an if VARIABLE is always True for VARIABLE that is unequal 0, False or None.

Well, they are most certainly not equal to None, False or 0 since both variables represent an instance of a Button. So what you are doing is:

  1. Check if one != None
  2. Set label if 1. is True - this happens and you set the label to "1" but then...
  3. Check if two != None
  4. Set label if 3. is True - this also happens and it also overwrites the previous value of the label set by 2 which was "1" to "2". All this happens instantly so you are unable to see the transition and are left with the impression that only "2" is displayed.

We can go further and rewrite your code in order to expose this error:

  def button_press():
    if one:
        x = 1
        display.configure(text=x)
    elif two:
        x = 2
        display.configure(text=x)

or even

  def button_press():
    if one:
        x = 1
        display.configure(text=x)
    else:
        x = 2
        display.configure(text=x)

In both of the above cases the first statement will be executed and you will get 1 all the time and never 2. Once you check for the first logical expression in your if-else block and it is True, you go in there and then leave the whole block not touching the elif or else at all.

There are various ways how to fix this. You can assign a name to the button (so that you can distinguish each button based on its name) in case you still want to handle both buttons with a single function and then do a comparison whether the name of the object that called your event handling function is == "one" or == "two". However in most (all?) UI frameworks it is a common practice to have a separate function for each UI component that handles an event that the component supports (multiple functions if the component supports multiple event).

one = Button(root, text="1", width="15", height="5",command=button_press1)
one.pack(side="left")

two = Button(root, text="1", width="15", height="5",command=button_press2)
two.pack(side="left")

This solution is similar to @Clodion's but without the lambdas since I'm not sure if you are familiar with the concept and throwing that in might be a bit confusing.

I would suggest following some basic principles when working with an UI. If your component has support for - let's say - value changes, resized, clicked, pressed down, pressed up etc. (don't know the name of these in Tkinter but I would guess it supports at at least some of them) - you will create a separate function for each event. This not only makes your code more readable but also forces you to learn a way of doing things that is de facto standard no matter if you write your UI with Tkinter, Qt, .NET, Swing, AngularJS and so on.

Upvotes: 1

user3788339
user3788339

Reputation: 31

This is what you want. May be new syntax but its the kinda thing you will get used to seeing. Dont be daunted.

from tkinter import *
root = Tk()

class BuildGui():
    def __init__(self, parent):
        self.parent = parent
        self.parent.geometry("500x500")
        self.parent.title("Building a Gui")
        self.parent.configure(background="steel blue")
        self.parent.resizable(0,0)
        self.parent.grid()
        self.CreateFrames()
        self.AddButtons()

    def CreateFrames(self):
        """Create The Frames"""
        self.Frm = Frame(self.parent, bg = "steel blue")
        self.Frm.grid(row = 0, column = 0)

    def AddButtons(self):
        self.Btn1 = Button(self.Frm, text = "Button1", height = 2, width = 10, fg = "black", activebackground = "yellow", bg = "light blue", command = self.Button1Pressed)
        self.Btn2 = Button(self.Frm, text = "Button2", height = 2, width = 10, fg = "black", activebackground = "yellow", bg = "light blue", command = self.Button2Pressed)
        self.Btn1.grid(row = 0, column = 0, padx = 40, pady = 40)
        self.Btn2.grid(row = 0, column = 1, padx = 40, pady = 40)


    def Button1Pressed(self):
        self.Lbl1 = Label(self.Frm, text = "Button1pressed!", font = ("Calibri", 12))
        self.Lbl1.grid(row = 1, column = 0, padx = 20, pady = 20)


    def Button2Pressed(self):
       self.Lbl2 = Label(self.Frm, text = "Button2pressed!", font = ("Calibri", 12))
       self.Lbl2.grid(row = 1, column = 1, padx = 20, pady = 20)



buildgui = BuildGui(root)
root.mainloop()

Upvotes: -1

Clodion
Clodion

Reputation: 1017

You have two ways:

Or using a different function for each button

Or pass a lambda with one parameter.

bt … command = fct1
bt … command = fct2

Or use a lambda…

from tkinter import *
root = Tk()
root.geometry("500x500")
root.title("Test")


def button_press(var):
    display.configure(text=var)

display = LabelFrame(root, bg="red", width="462", height="60")
display.pack()

one = Button(root, text="1", width="15", height="5",command=lambda : button_press(1))
one.pack(side="left")


two = Button(root, text="2", width="15", height="5", command=lambda : button_press(2))
two.pack(side="left")

root.mainloop()

Upvotes: 1

Related Questions