activation (rond noirci) d'un radiobouton + thread ?

Bonjour,
je veux lancer des programmes à l’aide de radiobouton. Dans le cas d’un flatpak, il faut un certain temps pour l’ouvrir. Dans ce cas le radiobouton ne s’active qu’après la fermeture du flatpak correctement lancé. J’ai pensé que c’était une histoire de thread mais je n’y arrive visiblement pas. Un petit coup de main serait le bienvenu.

def task():
	if var.get() == 1:
		var.set(1)
	elif var.get() == 2:
		var.set(2)

def run_app():
	if var.get() == 1:
		wr_ge='flatpak run org.gimp.GIMP'
		subprocess.run(wr_ge, shell=True)
	elif var.get() == 2:
		subprocess.Popen('/usr/bin/pdfarranger')

fen = Tk()
fen.geometry('350x100+1200+300')
var = IntVar()
c1 = Radiobutton(fen, text='GIMP : éditeur graphique',variable=var, bg="bisque", command=run_app, value = 1)
c1.place(x=10,y=10)
c2 = Radiobutton(fen, text='PDFarranger : gestionnaire PDF',variable=var, bg="bisque", command=run_app, value = 2)
c2.place(x=10,y=40)
t1 = Thread(target=task)
t1.start()
fen.mainloop()
t1.join()

Bonjour @mapommfj !

Je ne suis pas un habitué de tk mais j’aime beaucoup utiliser le module queue pour dialoguer entre des threads.

Dans cet exemple le “main thread” géré par tk utilise queue.put pour donner des instructions au worker_thread, le queue.put n’est pas bloquant donc le thread tk n’est jamais bloqué.

Le worker thread lui utilise queue.get pour attendre du travail (c’est bloquant, donc tant que la queue est vide, le worker thread ne fait rien).

J’ai implémenté deux tâches : run et exit, la première pour exécuter une commande et la seconde pour faire quitter le thread proprement.

Par contre vu que c’est des radio-button j’imagine qu’il faut tuer l’application qui s’exécute lorsqu’elle est dé-selectionnée ? Je n’ai pas implémenté ce comportement dans le doute.

import subprocess
from tkinter import Tk, IntVar, Radiobutton
from threading import Thread

from queue import Queue

task_queue = Queue()


def worker_thread():
    while True:
        print("Waiting for tasks...")
        task, *task_args = task_queue.get()
        if task == "exit":
            task_queue.task_done()
            return
        elif task == "run":
            print("Running", task_args)
            subprocess.run(task_args)
            task_queue.task_done()


def run_app():
    if var.get() == 1:
        task_queue.put(("run", 'flatpak', 'run', 'org.gimp.GIMP'))
    elif var.get() == 2:
        task_queue.put(("run", '/usr/bin/pdfarranger'))



fen = Tk()
fen.geometry('350x100+1200+300')
var = IntVar()
c1 = Radiobutton(fen, text='GIMP : éditeur graphique',variable=var, bg="bisque", command=run_app, value = 1)
c1.place(x=10,y=10)
c2 = Radiobutton(fen, text='PDFarranger : gestionnaire PDF',variable=var, bg="bisque", command=run_app, value = 2)
c2.place(x=10,y=40)
t1 = Thread(target=worker_thread)
t1.start()
fen.mainloop()

task_queue.put(("exit",))
task_queue.join()
t1.join()

Merci @mdk , je vais regarder ta proposition.

cela marche super bien (je croyais qu’il fallait installer un module queue, mais non).
Je présume que “run” aurait pû être remplacé par un nom quelconque
et idem pour task_args ?

Exact, run et exit sont juste des chaînes de caractères, task_args c’est juste un nom de variable, tu fais ce que tu veux avec.

Par contre attention a bien toujours exécuter un appel à queue.task_done() pour chaque appel à queue.get(), sinon la file perd le fil (haha) de ce qui est fait et pas fait, et tu ne pourras plus jamais la queue.join().

OK et merci pour ton aide précieuse

Bonjour,

ayant toujours quelques soucis avec cette activation, j’ai finalement trouvé une solution qui fonctionne à merveille (il faut régénérer la fenetre tkinter) :

fen = Tk()

def RB_selec():
    fen.update_idletasks()
    if RB_val.get() == 1:
        ...

Bonnes fêtes à tous

Comment ca a l’air horrible a gérer les threads…

Franchement faudrais pouvoir ouvrir une fenêtre et les avoirs dans une liste pendant les tests (avec leurs consoles respectif).

Car a part les print() en vrais y a rien qui faciliterais la découverte (j’ai vu une fois un direct la-dessus alors c’était en gdscript et non en python mais y avait tellement de points communs et de trucs a faire et ne pas faire…).

je reconnais que le traitement des threads est compliqué pour moi.

1 « J'aime »

Après ce serais peut-être plus simple et logique de faire en sorte

  • soit que les boutons radios ne fassent rien jusqu’a ce qu’on clique sur ‘OK‘ et dans ce cas l’action est faite en fonction du bouton selectionné
  • soit remplacer les boutons radios par des boutons classiques et les griser tent que le thread n’est pas finis (ou les remplacer par une barre de chargement + “Annuler l’action en cours).

Je dit ca surtout dans le cas ou tu veut partager ton appli avec des utilisateurs qui ont l’habitude du fonctionnement normal des boutons radios (entre autre).

Après de ce que je vois ca ressemble bien a un launcher donc au pire tu fais une liste, tu ajoute un champ de texte non editable qui decrit l’appli et un bouton qui s’appellerais '“Telecharger“ ou “Lancer“ suivant la présence ou non du logiciel + “Annuler“ ou “Forcer la fermeture“ une fois l’action lancé (ainsi qu’un bouton d’option pour choisir de réinstaller ou désinstaller l’app par exemple).

Et mieux: plutôt que d’avoir les applis dans le code les avoir dans un fichier éditable au bloc-note pour pouvoir facilement mêttre a jour ou ajouter des applis suivant l’évolution de ton launcher (si c’est bien un launcher a l’heure actuel :smiley: ).

Merci @Musclor13 pour tes remarques mais ce n’est qu’un script perso et qui fonctionne sans complication . Je développe juste des scripts en fonction de mes propres besoins pour une utilisation quasi journalière. Je les améliore au fil de mes découvertes et de mon apprentissage.

1 « J'aime »