Cerrar una ventana Tk en proceso
Diablo76 Mensajes publicados 344 Fecha de registro Estado Miembro Última intervención -
Hola,
Tengo un pequeño programa con una interfaz Tkinter que muestra una lista de
palabras en un widget Text, después de un bucle de búsqueda de unos minutos
Para interrumpir la búsqueda, hago clic en la x en la esquina superior derecha de la
barras de título, pero no es muy limpio: me aparece el habitual
"Python no responde Cerrar el programa, ...."
¿Cómo hacer esto de forma más adecuada?
Gracias de antemano
7 respuestas
-
Hola Phil,
No sé si eso cubrirá tus necesidades, pero con el método update() y un binding en la cruz de la ventana, vería algo así:
import tkinter as tk flag = True def loop(): i = 0 while flag: i += 1 print(f"Loop n° {i}") root.update() print("Loop off") def on_exit(): global flag flag = False root.destroy() root = tk.Tk() but_search = tk.Button(root, text="Search", command=loop) but_search.pack() but_quit = tk.Button(root, text="Quit", command=on_exit) but_quit.pack() root.protocol('WM_DELETE_WINDOW', on_exit) root.mainloop() -
yg_be Mensajes publicados 23437 Fecha de registro Estado Colaborador Última intervención Embajador 1 588
hola,
¿esto da un mensaje de error cuando cierras la ventana?
import tkinter raíz = tkinter.Tk() etiqueta = tkinter.Label(raíz, text="¡Me encanta Python!") etiqueta.pack() raíz.mainloop() print("terminado") -
Hi.
Indeed, tkinter or any GUI won’t be able to close if we don’t hand control back to it.
So, the solution isn’t in tkinter but in your search method, which seems to be blocking. Roughly, how is it performed?
Couldn't you put that in a thread?
In a very rough summary:
import tkinter import threading class Search(threading.Thread): def __init__(self, text): super().__init__() self._text = text self._stopped = threading.Event() def run(self): # simulation de qqchose qui prend du temps import time while not self._stopped.is_set(): self._text.insert(tkinter.END, f'{round(time.time())}\n') time.sleep(2) def stop(self): self._stopped.set() def wait_done(ms, window, search): if search.is_alive(): print('waiting...') window.after(ms, wait_done, ms, window, search) else: window.destroy() def on_close(window, search): search.stop() wait_done(100, window, search) def search_run(search, text, button): button.destroy() search.start() window = tkinter.Tk() text = tkinter.Text(window) text.grid() search = Search(text) button = tkinter.Button(window, text='rechercher') button.grid() button.configure(command=lambda: search_run(search, text, button)) window.protocol('WM_DELETE_WINDOW', lambda: on_close(window, search)) window.mainloop()?
-
Gracias a todos, Los códigos de Diablo y yg_be funcionan ¿Cómo se realiza mi método de búsqueda? Es un doble bucle para comparar dos listas elemento por elemento, el número de combinaciones puede ser muy grande El código:
# -*- coding:Utf-8 -*- # 19/04/2024 13:25:08 import itertools as it from tkinter import * def show_result(evt): words_list = [] t1.delete(0.0, END) # Builds anagrams list anag_list = set("".join(e) for e in it.permutations(e1.get(), len(e1.get()))) main_win.update() # Search for el in anag_list: for word in dico: if(el == word): words_list.append(word) if(words_list != []): for el in words_list: t1.insert(END, el+'\n') else: t1.insert(END, 'Rien') def on_exit(): main_win.destroy() WIDTH, HEIGHT = 320, 200 # Makes a list from the dictionnary file dico = [] with open('dico.txt', 'r') as f: for line in f: dico.append(line[:-1]) main_win = Tk() main_win.title('Décoder une anagramme') main_win.geometry(str(WIDTH)+'x'+str(HEIGHT)+'+400+100') main_win.protocol('WM_DELETE_WINDOW', on_exit) l1 = Label(main_win, text='Anagramme :') l1.place(x = 10,y = 20) e1 = Entry(main_win, width = 10) e1.place(x = 100,y = 20) e1.bind("<return>", show_result) e1.focus() t1 = Text(main_win, width = 30, height = 7) t1.place(x = 10, y = 50) main_win.mainloop()</return>dico.txt contient 125623 mots un mot de 6 lettres a 720 anagrammes-
-
No es necesario comparar así todas las parejas de elementos de las dos listas. Es preferible ordenar las dos listas y recorrerlas juntas, para hallar los elementos comunes.
import itertools as it from tkinter import * def show_result(evt): words_list = [] t1.delete(0.0, END) # Builds anagrams list anag_list = list("".join(e) for e in it.permutations(e1.get(), len(e1.get()))) anag_list.sort() main_win.update() # Search ll1,ll2=len(anag_list),len(dico) i1,i2=0,0 while i1<ll1 and i2<ll2: x1,x2=anag_list[i1],dico[i2] if x1>x2: i2 += 1 elif x1<x2: i1 += 1 else: words_list.append(x1) i1 += 1 i2 += 1 if(words_list != []): for el in words_list: t1.insert(END, el+'\n') else: t1.insert(END, 'Rien') def on_exit(): main_win.destroy() WIDTH, HEIGHT = 320, 200 # Makes a list from the dictionnary file dico = [] with open('dico.txt', 'r') as f: for line in f: dico.append(line[:-1]) dico.sort() main_win = Tk() main_win.title('Décoder une anagramme') main_win.geometry(str(WIDTH)+'x'+str(HEIGHT)+'+400+100') main_win.protocol('WM_DELETE_WINDOW', on_exit) l1 = Label(main_win, text='Anagramme :') l1.place(x = 10,y = 20) e1 = Entry(main_win, width = 10) e1.place(x = 100,y = 20) e1.bind("<Return>", show_result) e1.focus() t1 = Text(main_win, width = 30, height = 7) t1.place(x = 10, y = 50) main_win.mainloop()
-
-
Hola yg_be,
Así es: hice la prueba antes de leer tu respuesta, pero después de leer
la de las 11:52
Funciona muy bien
Gracias de nuevo a todos, ¡problema resuelto!
-
Creo que también se puede optimizar el código creando un diccionario a partir de la lista de palabras, tomando como clave la longitud, y creando ana_set a medida que se itera para controlar los boúblons:
import itertools as it from tkinter import * def show_result(evt): t1.delete(0.0, END) it_perm = it.permutations(e1.get()) anag_set = set() for perm in it_perm: word = "".join(perm) if not len(word) in dico.keys(): break if word in dico[len(word)] and word not in anag_set: t1.insert(END, word+"\n") anag_set.add(word) if not anag_set: t1.insert(END, 'Rien') def on_exit(): main_win.destroy() WIDTH, HEIGHT = 320, 200 dico = {} with open('dico.txt', 'r') as f: for line in f: line = line.strip() longueur_mot = len(line) if longueur_mot not in dico: dico[longueur_mot] = [line] else: dico[longueur_mot].append(line) main_win = Tk() main_win.title('Décoder una anagrama') main_win.geometry(f"{WIDTH}x{HEIGHT}+400+100") main_win.protocol('WM_DELETE_WINDOW', on_exit) l1 = Label(main_win, text='Anagramme :') l1.place(x=10, y=20) e1 = Entry(main_win, width=10) e1.place(x=100, y=20) e1.bind("<Return>", show_result) e1.focus() t1 = Text(main_win, width=30, height=7) t1.place(x=10, y=50) main_win.mainloop()je pense que ça peut être encore optimiser
-
Todas las permutaciones de la misma longitud:
def show_result(evt): t1.delete(0.0, END) it_perm = it.permutations(e1.get()) lenw=len(e1.get()) anag_set = set() if lenw in dico.keys(): dicol=dico[lenw] for perm in it_perm: word = "".join(perm) if word in dicol: t1.insert(END, word+"\n") anag_set.add(word) if not anag_set: t1.insert(END, 'Rien')
-
-
J'ai fini par faire ceci, et ça marche pas mal:
# -*- coding=Utf-8 -*- # 19/04/2024 13:25:08 import itertools as it from time import perf_counter from tkinter import * def time_format(_time): units = 's' if(_time > 60.0): _time, units = _time/60.0, 'mn' return(_time,units) def show_result(evt): # Makes a list from the dictionnary file dico = [] with open('dico.txt', 'r') as f: for line in f: if(len(line[:-1]) == len(e1.get())): dico.append(line[:-1]) words_list = [] t1.delete(0.0, END) l3['text'] = 'Temps passé : ' # Builds anagrams list avoiding doubles anag_list = set("".join(e) for e in it.permutations(e1.get(), len(e1.get()))) estimated_t, units = time_format((len(anag_list) * len(dico))/LOOPS_PER_SECOND) l2['text'] = 'Temps estimé : {:.2f} {}'.format(estimated_t, units) # Search t1.configure(cursor = 'wait') start = perf_counter() for el in anag_list: main_win.update() if(el in dico): t1.insert(END, el+'\n') end = perf_counter() t1.configure(cursor = '') elapsed_t, units = time_format(end-start) l3['text'] = f'Temps passé: {elapsed_t: 0.2f} {units} ' def on_exit(): main_win.destroy() LOOPS_PER_SECOND = 16056487 VOWELS = 'aeiouy' WIDTH, HEIGHT = 320, 200 main_win = Tk() main_win.title('Décoder une anagramme') main_win.geometry(str(WIDTH)+'x'+str(HEIGHT)+'+400+100') main_win.protocol('WM_DELETE_WINDOW', on_exit) l1 = Label(main_win, text='Anagramme :') l1.place(x = 10,y = 20) e1 = Entry(main_win, width = 10) e1.place(x = 100,y = 20) e1.bind("<Return>", show_result) e1.focus() l2 = Label(main_win, text='Temps estimé :') l2.place(x = 170,y = 20) t1 = Text(main_win, width = 30, height = 7) t1.place(x = 10, y = 50) l3 = Label(main_win, text='Temps passé :') l3.place(x = 10,y = 170) main_win.mainloop()-
En mi caso no funciona.
Trazas:
Traceback (most recent call last): File "/usr/lib/python3.10/tkinter/__init__.py", line 1921, in __call__ return self.func(*args) File "/home/diablo76/Bureau/Test_Python/pythonTest/bon.py", line 39, in show_result t1.configure(cursor = 'wait') File "/usr/lib/python3.10/tkinter/__init__.py", line 1675, in configure return self._configure('configure', cnf, kw) File "/usr/lib/python3.10/tkinter/__init__.py", line 1665, in _configure self.tk.call(_flatten((self._w, cmd)) + self._options(cnf)) _tkinter.TclError: bad cursor spec "wait" -
-