Partage
  • Partager sur Facebook
  • Partager sur Twitter

[Python] Problème avec tkinter et les bouton

Appelle d'une fonction

Anonyme
14 novembre 2006 à 13:24:33

Salut,

J'ai un petit projet pour mon école à faire, je doit utiliser python et la lib tkinter, pas le droit de changer.
Donc je me fait un générateur de pj pour warhammer

Mais j'ai un petit problème :

- Toute les carrières sont stockée dans un fichier txt
- Je recupère les nom de chaque carriere
- Avec un boucle j'affiche un bouton par carrière
- Je voudrai quand cliquant sur un bouton, cela m'affiche le descriptif de la carrière. Donc en cliquant sur le bouton que ça appele la fonction def_carriere(carriere)

Mon problème c'est que:

1) Si je met un parametre dans l'appelle de la fonction, la fonction se lance automatiquement sitôt le bouton créé (Donc sa me lance 60 fois la fonction -_-), et ensuite ça ne la rapelle pas si je clique dessus.

2) Si je ne passe pas de parametre dans l'apelle de la fonction, lorsque je clique sur un bouton, la fonction s'execute bien, mais sans le nom de carrière impossible de faire quelquechose.

En espérant avoir été clair, et que vous aurez une réponse à m'apporter.

Merci ;)



  • Partager sur Facebook
  • Partager sur Twitter
14 novembre 2006 à 19:14:07

Un petit peu de code du truc qui foire ?
la fonction et la création du widget :)
Sinon, on peut pas faire grand chose, ni tester ni corriger.


Bisous, Nyu
  • Partager sur Facebook
  • Partager sur Twitter
Anonyme
14 novembre 2006 à 19:54:38

A vi j'avais oublié de le mettre en rentrant chez moi, j'ai posté le premier message de mon école


#!/usr/bin/python
# -*- coding: latin-1 -*

from Tkinter import *

def def_carriere():
    i = 0
    nom = 'Bgitateur\n'
    carriere = './carriere/base/'
    while i <= len(nom)-1:
        carriere += nom[i]
        i += 1
       
    print carriere
    if i == len(nom)-1:
        file = open(carriere,'r')   

def start():
    cadre.delete()
    humain = Button(cadre , text='Humain', command= carriere)
    humain.grid(row = 3, column = 1,sticky='EW')
    elfe = Button(cadre , text='Elfe', command= carriere)
    elfe.grid(row = 4, column = 1,sticky='EW')
       
def carriere():
    file = open('carriere.txt','r')
    fichier = file.readlines()
    colone = 0
    ligne = 2
   

    #Ici pour la création des boutons, si je laisse un paramètre dans l'appelle de def_carriere
    la fonction s'exécute toute seule

    for textligne in fichier:
        ligne += 1
        bouton= Button(cadre, text=textligne, command = def_carriere)
        bouton.grid(row = ligne, column = colone,sticky='
EW')
        if ligne == 12 :
            ligne = 2
            colone += 1
    file.close()



ecran = Tk()

pj = Button(ecran, text='
Créer PJ',command=start)
pj.grid(row = 1, column = 0)

carriere = Button(ecran, text='
Carrière',command=carriere)
carriere.grid(row = 1, column = 2)

quitter = Button(ecran, text='
Quitter',command=ecran.quit)
quitter.grid(row = 1, column = 5)

cadre = Canvas(ecran, bg='
white', width=640, height=400)
cadre.grid(row = 2, column = 0, columnspan = 6)

ecran.mainloop()
ecran.destroy()

 


Voila en espérant que ça vous aide à m'aider ^^
  • Partager sur Facebook
  • Partager sur Twitter
15 novembre 2006 à 15:17:00

Bon j'y suis arrivé à coup de lambda et de exec :s .
C'est pas propre mais ça marche ;)
#!/usr/bin/python
# -*- coding: latin-1 -*

from Tkinter import *

nom = []
def call_carr(n):
    global nom
    return def_carriere(nom[n])
def def_carriere(name):
    i = 0
    carriere = './carriere/base/'+name
    print carriere
    if i == len(name)-1:
        fp = open(carriere,'r')

def start():
    cadre.delete()
    humain = Button(cadre , text='Humain', command= carriere)
    humain.grid(row = 3, column = 1,sticky='EW')
    elfe = Button(cadre , text='Elfe', command= carriere)
    elfe.grid(row = 4, column = 1,sticky='EW')
       
def carriere():
    global nom
    fp = open('carriere.txt','r')
    fichier = fp.readlines()
    colone = 0
    ligne = 2
   

    #Ici pour la création des boutons, si je laisse un paramètre dans l'appelle de def_carriere
    #la fonction s'exécute toute seule
    i = 0
    for textligne in fichier:
        ligne += 1
        nom.append(textligne)
        exec('func'+str(i)+' = lambda: call_carr('+str(i)+')')
        exec('bouton= Button(cadre, text=textligne, command = func'+str(i)+')')
        bouton.grid(row = ligne, column = colone,sticky='EW')
        if ligne == 12 :
            ligne = 2
            colone += 1
        i += 1
    fp.close()



ecran = Tk()

pj = Button(ecran, text='Créer PJ',command=start)
pj.grid(row = 1, column = 0)

carriere = Button(ecran, text='Carrière',command=carriere)
carriere.grid(row = 1, column = 2)

quitter = Button(ecran, text='Quitter',command=ecran.quit)
quitter.grid(row = 1, column = 5)

cadre = Canvas(ecran, bg='white', width=640, height=400)
cadre.grid(row = 2, column = 0, columnspan = 6)

ecran.mainloop()
ecran.destroy()




Bisous, Nyu
  • Partager sur Facebook
  • Partager sur Twitter
Anonyme
15 novembre 2006 à 20:45:56

Merci ^^
Mais en fait j'ai déplacé mon problème j'ai réussi à le résoudre d'une manière que je trouve plus jolie ^^

Mais maintenant j'ai un autre problème T_T



def carriere_base():
    global choix
    change()
    file = open('carriere.txt','r')
    fichier = file.readlines()
    count = 0
    listecarriere = []
    for textligne in fichier:
        carriere = ''
        i = 0
        while i <= len(textligne)-2:
            carriere += textligne[i]
            i += 1
        listecarriere.append((count,carriere))
        count += 1
    file.close()
   
    colone = 0
    ligne = 2
    choix = IntVar()
    choix.set('1')
    for num,nom in listecarriere:
        ligne += 1
        choix = IntVar()
        bouton=Radiobutton(cadre, text=nom, variable=choix, value=num,command=test, indicatoron = FALSE)
        bouton.grid (row = ligne, column = colone,sticky='EW')
        if ligne == 12 :
             ligne = 2
             colone += 1   


def test():
    val = choix.get()
    print "tu à choisit", val



Maintenant le problème est que la valeur de choix que j'envoie à test() est de :
- 0 pour les 59 premiers boutons (au lieu de 0 à 58)
- 59 pour le dernier

Une idée ?
  • Partager sur Facebook
  • Partager sur Twitter
15 novembre 2006 à 21:00:07

Je comprend pas le principe de comment tu as résolue ton problème :s
Tu pourais me l'epxpliquer ?
A quoi servent ces intvar ?


Bisous, Nyu
  • Partager sur Facebook
  • Partager sur Twitter
Anonyme
15 novembre 2006 à 21:30:58

Bas en fait mon problème venait du fait que je n'arrivait pas a envoyer une variable en paramètre de ma fonction sans que la fonction ne se lance automatiquement (sans clic sur le bouton).

Pour cela je suis passé par un radibutton, qui lui permet d'envoyer une variable sans la passer en paramètre de ma fonction et de la récupérer via variable.get(), tout ceci sans mettre de variable dans l'appelle de fonction donc plus de problème pour ce qui est de l'exécution automatique.

Pour ce qui est du IntVar(), j'avoue moi même ne pas sur de ce que c'est, ni même de leur utilité.
Cependant dans tout les cours que j'ai pu voir il est présent.
  • Partager sur Facebook
  • Partager sur Twitter
15 novembre 2006 à 21:54:25

Car avec ma solution, en fait on créé dynamiquement une fonction en utilisant lambda donc de ce point de vue... c'est plus propre que ta solution et ya pas ce problème.
Donc bon, moi je fais avec ce que je connais et ça marche ;) .
Après, je veux pas me lancer sur des trucs que je connais pas :o
Tu fais comme tu veux.


Bisous, Nyu
  • Partager sur Facebook
  • Partager sur Twitter
Anonyme
16 novembre 2006 à 2:16:09

Merci de ton aide , je vais faire avec ta méthode pour l'instant.
Je garde ma méthode dans un coin de mon pc, avec mes autre script qui buggent, en espérant comprendre un jour pourquoi ça marche pas.

Si quelqu'un à un idée, je suis toujours à votre écoute ;)
  • Partager sur Facebook
  • Partager sur Twitter
Anonyme
16 novembre 2006 à 6:39:36

Byidi> Tu ne peux effectivement pas écrire 'command = foo(bar)' parce que ça appelera foo immédiatement. En fait, le paramètre command attend que tu lui donnes un objet fonction, c'est à dire une fonction qu'il pourra appeler - pour ça il faut écrire son nom uniquement. La solution semble être d'utiliser lambda comme Dutiona l'a fait (par contre le exec c'est pas très beau, on peut normalement s'en passer). Swinnen en parle dans son cours, aux chapitres avancés (autour de la page 214 de la version que j'ai).
  • Partager sur Facebook
  • Partager sur Twitter
Anonyme
16 novembre 2006 à 10:21:49

Citation : Bigloo

Byidi> Tu ne peux effectivement pas écrire 'command = foo(bar)' parce que ça appelera foo immédiatement. En fait, le paramètre command attend que tu lui donnes un objet fonction, c'est à dire une fonction qu'il pourra appeler - pour ça il faut écrire son nom uniquement. La solution semble être d'utiliser lambda comme Dutiona l'a fait (par contre le exec c'est pas très beau, on peut normalement s'en passer). Swinnen en parle dans son cours, aux chapitres avancés (autour de la page 214 de la version que j'ai).



Oki merci pour l'explication, c'est bien ce que je pensait donc ^^
Je vais aller voir dans le cour de Swinnen des que je rentre chez moi.
  • Partager sur Facebook
  • Partager sur Twitter
28 avril 2021 à 11:34:37 - Message modéré pour le motif suivant : Merci d'utiliser le bouton code du forum pour insérer votre code


28 avril 2021 à 12:16:03

@nicolasFISCHER6 Bonjour, merci de ne pas déterrer d'ancien sujet, créer le votre dans le respect des règles du forum à savoir qu'un message commence par des règles de politesses (un bonjour ou des salutations à la communauté et ce termine par des remerciements par avance pour les futures réponses) un descriptif de votre problématique et le code que vous avez écrit insérer sur le forum grâce au bouton code </> prévu pour.

Déterrage

Citation des règles générales du forum :

Avant de poster un message, vérifiez la date du sujet dans lequel vous comptiez intervenir.

Si le dernier message sur le sujet date de plus de deux mois, mieux vaut ne pas répondre.
En effet, le déterrage d'un sujet nuit au bon fonctionnement du forum, et l'informatique pouvant grandement changer en quelques mois il n'est donc que rarement pertinent de déterrer un vieux sujet.

Au lieu de déterrer un sujet il est préférable :

  • soit de contacter directement le membre voulu par messagerie privée en cliquant sur son pseudonyme pour accéder à sa page profil, puis sur le lien "Ecrire un message"
  • soit de créer un nouveau sujet décrivant votre propre contexte
  • ne pas répondre à un déterrage et le signaler à la modération

Je ferme ce sujet. En cas de désaccord, me contacter par MP.

  • Partager sur Facebook
  • Partager sur Twitter