简体   繁体   中英

How to make tkinter button raised before executing command

Am trying to make GUI app which compulsory you have to select one of predict button before the number entered will be printed to the terminal,if none of predict button is selected the should print out select predict button to proceed .

In pseudecode something like:

def check:
    now = new.get()
    if no lotto_button is selected:
        print("select predict button to proceed")
    else:
        print(now)

But having challenges:

1:when i select one predict button both buttons raised.

2:How to make the predict compulsory to be selected before the content in the entry will be printed.

import tkinter as tk



def terminal():
    now = new.get()
    print(now)

def start_func():
    lotto_button.configure(relief=tk.SUNKEN, state=tk.DISABLED)
    lotto_button1.configure(relief=tk.SUNKEN, state=tk.DISABLED)



def stop_func():
    lotto_button.configure(relief=tk.RAISED, state=tk.ACTIVE)
    lotto_button1.configure(relief=tk.RAISED, state=tk.ACTIVE)


root = tk.Tk()
root.geometry("400x400")


new = tk.StringVar()
en = tk.Entry(root, textvariable=new).pack()


lotto_button = tk.Button(root, text="predict one", command=start_func)
lotto_button.pack(side="left")
lotto_button1 = tk.Button(root, text="predict two", command=start_func)
lotto_button1.pack()


tk.Button(root, text="print number", command=lambda :[stop_func(), 
terminal()]).place(x=150, y=300)

root.mainloop()

Thank you and your advice to do is welcome.

As for making it compulsory for picking, you can define a flag in outermost scope (in same level as root = tk.Tk() ) so that you can see in your functions if it's set or not like:

isPredicted = False

And as for disabling each button when one is picked, you can define your your start_func such that it takes button object ( lotto_button or lotto_button1 ) as argument:

def start_func(button_object):

    global isPredicted
    isPredicted = True

    button_object.configure(relief=tk.SUNKEN, state=tk.DISABLED)

To be able to use this function, you need to configure your buttons in the following way, so that they pass themselves as the argument:

lotto_button.configure(command=lambda button_object=lotto_button: start_func(button_object))

lotto_button1.configure(command=lambda button_object=lotto_button1: start_func(button_object))

You should have isPredicted flag in your stop_func as well so that it unsets it:

def stop_func():

    global isPredicted
    isPredicted = False

    lotto_button.configure(relief=tk.RAISED, state=tk.ACTIVE)
    lotto_button1.configure(relief=tk.RAISED, state=tk.ACTIVE)

As for your terminal function, you'd want to act based on the state of isPredicted so it needs to be defined as:

def terminal():

    global isPredicted

    if isPredicted:
        now = new.get()
        print(now)

    else:
        print("select predict button to proceed")

finally in your "print number" button you need to swap the order of the functions in lambda or isPredicted is always False as far as that button's command is concerned:

tk.Button(root, text="print number", command=lambda :[terminal(),
stop_func()]).place(x=150, y=300)

Your final code should look like:

import tkinter as tk
from tkinter import messagebox



def terminal():

    global isPredicted

    if isPredicted:
        now = new.get()
        print(now)

    else:
        print("select predict button to proceed")

def start_func(button_object):

    global isPredicted
    isPredicted = True

    button_object.configure(relief=tk.SUNKEN, state=tk.DISABLED)



def stop_func():

    global isPredicted
    isPredicted = False

    lotto_button.configure(relief=tk.RAISED, state=tk.ACTIVE)
    lotto_button1.configure(relief=tk.RAISED, state=tk.ACTIVE)


root = tk.Tk()
root.geometry("400x400")


new = tk.StringVar()
en = tk.Entry(root, textvariable=new).pack()

isPredicted = False


lotto_button = tk.Button(root, text="predict one")
lotto_button.configure(command=lambda button_object=lotto_button: start_func(button_object))
lotto_button.pack(side="left")
lotto_button1 = tk.Button(root, text="predict two")
lotto_button1.configure(command=lambda button_object=lotto_button1: start_func(button_object))
lotto_button1.pack()


tk.Button(root, text="print number", command=lambda :[terminal(),
stop_func()]).place(x=150, y=300)

root.mainloop()

When you're clicking on one of the button prediction, both are raised because in your function start_func, you're configuring both. Instead of configuring both of them you can bind an event click and getting the widget in start_func like this:

lotto_button = tk.Button(root, text="predict one")
lotto_button.bind('<1>', start_func)
lotto_button.pack(side="left")

And then in your start_func :

def start_func(event):
    w = event.widget 
    w.configure(relief=tk.SUNKEN, state=tk.DISABLED)

About your second point, I'm not sure to understand what you mean.

Using Radiobutton widgets tends to be better for this sort of multiple choice processing.

Radiobutton s belong to "groups" which means that you can set them up so that one always needs to be selected by default. This means that you don't need to have any kind of error catching or display any sort of instruction to the user, it just intuitively works.

from tkinter import *

root = Tk()

def command(v, entry):
    print(v.get(), entry.get())

v = StringVar()
v.set(1)

entry = Entry(root)
rb1 = Radiobutton(root, text="Predict One", variable=v, value=1, indicatoron=0)
rb2 = Radiobutton(root, text="Predict Two", variable=v, value=2, indicatoron=0)
button = Button(root, text="Print Number", command=lambda:command(v, entry))

entry.pack()
rb1.pack()
rb2.pack()
button.pack()

root.mainloop()

So we create a StringVar() which we use to define which Radiobutton widgets should be linked together and then we set it's value to 1 which is the value of the "Predict One" button. If the user presses the other Radiobutton then the value changes to 2 which means the first button "unpresses" and the value of the StringVar() is changed to 2 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM