Valentin Mercier
Valentin Mercier

Reputation: 385

how to update command of tkinter button?

I have a function fonc(a,b,c,bool1,bool2) which takes float (a,b,c) and boolean parameters. This function can plot different types of graphics (with matplotlib) depending on the boolean value and these graphics depend on the float value.

I'm trying to make a "graphic interface" for this function in tkinter. In this interface I could change the value of the boolean with a checkbox and float with a spinbox and a button "launch" which launches the function with the current parameters and plots in the interface.

I'll try to make it first with one checkbox and here is the problem, the function put the part command of the button launch is static. I mean that it takes the default parameter that I put and never changes even if use my checkbox to change the value of the parameter.

Here is my code, the function is testpanneau.testpanneau1 and my boolean is toutedir2:

import tkinter as tk
import testpanneau
from functools import partial

"""constantes"""
latitude = 37.77
longitude = -122.42
j = 21
m = 12
a = 2016
timezone = -8
hauteurlieu = 0.282
costheta = False
toutedir1 = False
toutedir2 = True
infonord = False
cst = 32

"""definition de la fonction de changement de booleen"""
def chgtbool1():
    print("Button clicked")
    toutedir2 = True if is_checked.get() else False
    print(toutedir2)

"""creation de ma fenetre"""
mafenetre = tk.Tk()
mafenetre.title('Test irradiance')
mafenetre.geometry('600x200')


"""definition des boolen des checkbox"""
#toutedir2
is_checked = tk.BooleanVar()
#toutedir1
#costheta
#infonord

"""creation des checkbox"""
checkbox = tk.Checkbutton(mafenetre, variable=is_checked, command=chgtbool1)

"""Création d'un widget Button (bouton Quitter)"""
Bouton1 = tk.Button(mafenetre, text = 'Quitter', command = mafenetre.destroy)

""" Création d'un widget Button (bouton Lancer)"""
BoutonLancer = tk.Button(mafenetre, text ='generer', command = partial(testpanneau.testpanneau1,latitude,longitude,j,m,a,timezone,hauteurlieu,cst,costheta,toutedir1,toutedir2,infonord))

"""Positionnement du widget avec la méthode pack()"""
checkbox.pack(side = tk.LEFT, padx = 5, pady = 7)
Bouton1.pack()
BoutonLancer.pack(side = tk.RIGHT, padx = 5, pady = 0)

""" Lancement du gestionnaire d'événements"""
mafenetre.mainloop()

Upvotes: 0

Views: 2844

Answers (3)

Valentin Mercier
Valentin Mercier

Reputation: 385

I resolve my problem by using a function uptade which uptade my command with a new partial function :

def maj():
    global BoutonLancer
    BoutonLancer['command'] = partial(testpanneau.testpanneau1,latitude,longitude,j,m,a,timezone,hauteurlieu,cst,costheta,toutedir1,toutedir2,infotheta,beta,gamma)

Thank you all for help :)

Upvotes: 0

SiHa
SiHa

Reputation: 8411

When you create your partial(), it is created with the values of the variables at the time it is created:

The partial() is used for partial function application which “freezes” some portion of a function’s arguments and/or keywords resulting in a new object with a simplified signature....

As shown in this simple example:

>>> from functools import partial
>>> i = 3
>>> def prt(a):
...     print a
...
>>> x = partial(prt, i)
>>> x()
3
>>> i = 5
>>> x()
3

No amount of clicking your text box can change the value that is seen when you run your command.

What you need to do it pass in is_checked when you create the partial, and then inside your function testpanneau.testpanneau1, do the is_checked.get() to get at the boolean value. You can also do away with your chgtbool1() function.

This code works, I have replaced testpanneau.testpanneau1 with myfun(), and the value of the checkbox is correctly printed when the generer button is pressed.

import tkinter as tk
from functools import partial

"""constantes"""
latitude = 37.77
longitude = -122.42
j = 21
m = 12
a = 2016
timezone = -8
hauteurlieu = 0.282
costheta = False
toutedir1 = False
toutedir2 = True
infonord = False
cst = 32

def myfun(*args):
    print args[10].get()

"""creation de ma fenetre"""
mafenetre = tk.Tk()
mafenetre.title('Test irradiance')
mafenetre.geometry('600x200')


"""definition des boolen des checkbox"""
#toutedir2
is_checked = tk.BooleanVar()
#toutedir1
#costheta
#infonord

"""creation des checkbox"""
checkbox = tk.Checkbutton(mafenetre, variable=is_checked)

"""Creation d'un widget Button (bouton Quitter)"""
Bouton1 = tk.Button(mafenetre, text = 'Quitter', command = mafenetre.destroy)

""" Creation d'un widget Button (bouton Lancer)"""
BoutonLancer = tk.Button(mafenetre, text ='generer', command = partial(myfun,latitude,longitude,j,m,a,timezone,hauteurlieu,cst,costheta,toutedir1,is_checked,infonord))

"""Positionnement du widget avec la methode pack()"""
checkbox.pack(side = tk.LEFT, padx = 5, pady = 7)
Bouton1.pack()
BoutonLancer.pack(side = tk.RIGHT, padx = 5, pady = 0)

""" Lancement du gestionnaire d'evenements"""
mafenetre.mainloop()

My apologies, I had to anglicize your comments as my Python 2.7 interpreter was complaining about the accented characters

Upvotes: 1

Ron Norris
Ron Norris

Reputation: 2690

Still very unsure of the goal, but this code fragment demonstrates how to update the command of a button (dynamically), which is the title of this issue.

def generer() :
    Boutonint = tk.Button(mafenetre, text = 'lancer', command = someAction)
    Boutonint.pack(side = tk.RIGHT, padx = 3, pady = 0)

def noPlot():
    BoutonLancer['command'] = noPlot
    print("Making plot...")

def someAction():
    print('lancer button caused this')

"""definition de la fonction de changement de booleen"""
def chgtbool1():
    print("Button clicked")
    toutedir2 = is_checked.get()
    if toutedir2:
        BoutonLancer['command'] = generer
    else:
        BoutonLancer['command'] = noPlot
    print(toutedir2)

Upvotes: 1

Related Questions