Fenêtre superposant une autre fenêtre
Phidippides
Messages postés
13
Statut
Membre
-
Phidippides Messages postés 13 Statut Membre -
Phidippides Messages postés 13 Statut Membre -
Bonjour,
Tout d'abord je n'ai pas beaucoup d'expérience avec Python, cela fait seulement quelques mois que je l'ai découvert.
Je suis en train de développer un solveur de sudoku mais j'ai un problème que je n'arrive pas à résoudre.
J'ai créé une première fenêtre pour ma grille de Sudoku qui est divisée en cellules.
Parfois évidemment, il peut y avoir plusieurs possibilités pour une même cellule jusqu'à ce que l'on déduise le seul chiffre possible.
Pour cela, j'ai créé une petite fenêtre aux dimensions de la cellule qui est elle-même divisée en 9 mini-cellules et dans laquelle l'utilisateur peut entrer les chiffres possibles.
Tout cela marche très bien mais si je clique sur le '-' (en haut à droite) de la fenêtre principale, celle-ci est iconifiée mais pas la ou les petites mini-grilles superposées aux cellules de mon Sudoku (ma fenêtre principale). De la même façon, si je superpose une autre fenêtre (par exemple mon moteur de recherche) à ma grille de Sudoku, cette dernière est effectivement cachée mais pas les petites fenêtres (mini-grilles) qui apparaissent toujours.
J'ai essayé de détecter un 'event' qui est 'Unmap' pour résoudre le problème. Cela marchait effectivement très bien quand j'étais sous Windows 7 mais maintenant que je tourne sous Linux (Ubuntu avec GNOME shell), cela ne marche plus. J'ai essayé des tas d'autres 'events' mais je n'arrive pas à m'en sortir.
Mes questions sont :
1) Quel est l'événement déclenché quand je clique gauche sur le '-' (en haut à droite) de la fenêtre principale, pour iconifier celle-ci ? Et comment récupérer cet événement pour lancer une fonction qui cacherait mes mini-grilles ?
2) Quand je recouvre ma grille de Sudoku (fenêtre principale) par une autre fenêtre (extérieure à mon logiciel), comment faire en sorte que mes mini-grilles soient aussi recouvertes ?
Je serais vraiment reconnaissant à ceux qui pourraient me donner un coup de pouce.
Tout d'abord je n'ai pas beaucoup d'expérience avec Python, cela fait seulement quelques mois que je l'ai découvert.
Je suis en train de développer un solveur de sudoku mais j'ai un problème que je n'arrive pas à résoudre.
J'ai créé une première fenêtre pour ma grille de Sudoku qui est divisée en cellules.
Parfois évidemment, il peut y avoir plusieurs possibilités pour une même cellule jusqu'à ce que l'on déduise le seul chiffre possible.
Pour cela, j'ai créé une petite fenêtre aux dimensions de la cellule qui est elle-même divisée en 9 mini-cellules et dans laquelle l'utilisateur peut entrer les chiffres possibles.
Tout cela marche très bien mais si je clique sur le '-' (en haut à droite) de la fenêtre principale, celle-ci est iconifiée mais pas la ou les petites mini-grilles superposées aux cellules de mon Sudoku (ma fenêtre principale). De la même façon, si je superpose une autre fenêtre (par exemple mon moteur de recherche) à ma grille de Sudoku, cette dernière est effectivement cachée mais pas les petites fenêtres (mini-grilles) qui apparaissent toujours.
J'ai essayé de détecter un 'event' qui est 'Unmap' pour résoudre le problème. Cela marchait effectivement très bien quand j'étais sous Windows 7 mais maintenant que je tourne sous Linux (Ubuntu avec GNOME shell), cela ne marche plus. J'ai essayé des tas d'autres 'events' mais je n'arrive pas à m'en sortir.
Mes questions sont :
1) Quel est l'événement déclenché quand je clique gauche sur le '-' (en haut à droite) de la fenêtre principale, pour iconifier celle-ci ? Et comment récupérer cet événement pour lancer une fonction qui cacherait mes mini-grilles ?
2) Quand je recouvre ma grille de Sudoku (fenêtre principale) par une autre fenêtre (extérieure à mon logiciel), comment faire en sorte que mes mini-grilles soient aussi recouvertes ?
Je serais vraiment reconnaissant à ceux qui pourraient me donner un coup de pouce.
A voir également:
- Fenêtre superposant une autre fenêtre
- Fenetre windows - Guide
- Fenêtre hors écran windows 11 - Guide
- Fenetre de navigation privée - Guide
- Mcafee fenetre intempestive - Accueil - Piratage
- Fermer une fenetre de force - Guide
1 réponse
Après une recherche sur le terme Unmap, j'en déduis que vous utilisez Tkinter, ce qui est primordial à préciser.
Si vous lisez l'anglais et cette discussion, il semble que le terme "unmap" n'a pas le même sens sous Linux, et en particulier ce n'est pas l'événement qui ce déclenche en cliquant sur le "-".
Sur la même discussion, une solution avec wmctrl et xprop est proposée, mais vous allez vous retrouver avec du code non portable (différent selon s'il est sous Linux ou Windows).
Pour déterminer si un autre événement pourrait vous intéresser, je vous suggère de créer un petit programme tout simple qui imprime tous les événements reçus 1 fois par seconde. Vous cliquez sur - et vous regarder ce qui a été affiché à l'écran.
Je n'ai pas bien compris comment était organisée votre interface graphique et vos mini grilles. Elles sont de quelles classes vos mini grilles ? Classe Tk ?
Si vous lisez l'anglais et cette discussion, il semble que le terme "unmap" n'a pas le même sens sous Linux, et en particulier ce n'est pas l'événement qui ce déclenche en cliquant sur le "-".
Sur la même discussion, une solution avec wmctrl et xprop est proposée, mais vous allez vous retrouver avec du code non portable (différent selon s'il est sous Linux ou Windows).
Pour déterminer si un autre événement pourrait vous intéresser, je vous suggère de créer un petit programme tout simple qui imprime tous les événements reçus 1 fois par seconde. Vous cliquez sur - et vous regarder ce qui a été affiché à l'écran.
Je n'ai pas bien compris comment était organisée votre interface graphique et vos mini grilles. Elles sont de quelles classes vos mini grilles ? Classe Tk ?
Je n'ai pas pu détecter l'"event" quand on clique sur le '-' pour iconifier la fenêtre principale.
J'ai en fait essayer d'afficher les "events" quand on clique gauche au niveau de la fenêtre Tk mais rien n'est affiché quand on clique sur le '-'. Par contre il m'affiche bien tous les "events" quand je clique n'importe où dans la fenêtre. Je vous donne un code de test ci-dessous :
import tkinter as tk from tkinter.font import Font from collections import namedtuple RC = namedtuple('RC', 'rows columns') BBox = namedtuple('BBox', 'x y width height') class HintWindow(tk.Toplevel): # fenêtre utilisée pour afficher les mini-grilles def __init__(self, bbox, bg='yellow', alpha=0.3, state='normal'): super().__init__(bg=bg) if state == 'withdrawn': self.withdraw() self.overrideredirect(True) self.geometry("%dx%d+%d+%d" % (bbox.width, bbox.height, bbox.x, bbox.y)) self.wm_attributes('-alpha', alpha) class Cell: # Tout ce qui concerne les 81 (= 9 x 9) cellules de la grille de Sudoku _iid = None _square_cfg = dict(fill='white', width=1, outline='white', activeoutline='red', activewidth=3, tag='cell') _hintcell = None @property def iid(self): return self._square def __init__(self, canvas, rc, coords, text_color='black'): self.canvas = canvas self.rc = rc self.coords = coords self.center = (coords[0] + coords[2]) // 2, (coords[1] + coords[3]) // 2 self._square = canvas.create_rectangle( coords, self._square_cfg) self._label = canvas.create_text(self.center, fill=text_color, text='', font=canvas.font, tag='cell') self.value = 0 def set_value(self, value): itemconfig = self.canvas.itemconfigure s = str(value) if value else '' itemconfig(self._label, text=s) self.value = value def create_hintcell(self, values): # crée la fenêtre et la mini-grille incluse dans celle-ci '''hint as reusable toplevel''' w = None if self._hintcell is None: bbox = self.canvas.root_bbox(self.iid, 1, 1) w = HintWindow(bbox, bg='white', alpha=0.7) hints = self._hintcell = HintsGrid(w, self) hints.pack(fill='both', padx=2, pady=2) self._hintcell.load(values) return w class Grid(tk.Canvas): # classe parent de la grille SudokuGrid et de la mini-grille HintsGrid qui effectue tout ce qui est commun aux 2 classes filles _cfg = None cellsize = None font = None RC = None SPACING = None font_config = None def __init__(self, parent=None): self._cfg['width'] = self.RC[0] * (self.cellsize + self.SPACING) self._cfg['height'] = self.RC[1] * (self.cellsize + self.SPACING) super().__init__(parent, self._cfg) self.font = Font(**self.font_config) self._cells = {} # maps (r, c) to cell for r in range(self.RC.rows): y0 = r * (self.cellsize + self.SPACING) y1 = y0 + self.cellsize for c in range(self.RC.columns): x0 = c * (self.cellsize + self.SPACING) x1 = x0 + self.cellsize rc = (r+1, c+1) self._cells[rc] = self.create_cell(rc, (x0, y0, x1, y1)) def cell(self, r, c): if (r, c) in self._cells: return self._cells[(r, c)] def root_bbox(self, iids, dx=0, dy=0): if not isinstance(iids, list): iids = (iids,) x0, y0, x1, y1 = self.bbox(*iids) w = x1 - x0 h = y1 - y0 x = self.winfo_rootx() + x0 y = self.winfo_rooty() + y0 return BBox(x+dx, y+dy, w-dx, h-dy) class SudokuGrid(Grid): # ma grille de Sudoku _cfg = dict(bd=0, highlightthickness=False, background='grey') cellsize = 63 RC = RC(9, 9) SPACING = 2 font_config = dict(family='Helvetica', size=(cellsize // 3)) _toplevel = None _model = None def __init__(self, parent): self.create_cell = lambda rc, coords: Cell(self, rc, coords) super().__init__(parent) self._hints = [] def load(self, initial_values): for r, values in enumerate(initial_values, 1): [ self.cell(r, c).set_value(v) for c, v in enumerate(values, 1) if v ] def update(self): toplevel = self.toplevel toplevel.bind('<Unmap>', self.on_minimize, '+') # c'est ici que cela coince super().update() @property def toplevel(self): if self._toplevel is None: self._toplevel = self.winfo_toplevel() return self._toplevel def on_minimize(self, event): for h in self._hints: h.withdraw() def hint_cell(self, r, c, values): self._hints.append(self.cell(r, c).create_hintcell(values)) class HintsGrid(Grid): # ma mini-grille incluse dans ma fenêtre HintWindow _cfg = dict(bd=0, highlightthickness=False, background='white') cellsize = 17 RC = RC(3, 3) SPACING = 4 font_config = dict(family='Helvetica', size=11) def __init__(self, parent, cell, values=None): self.create_cell = lambda rc, coords: Cell(self, rc, coords, text_color='blue') self._cell = cell super().__init__(parent) if values: self.load(values) def load(self, values): z = 1 for r in range(self.RC.rows): for c in range(self.RC.columns): cell = self.cell(r+1, c+1) if z in values: cell.set_value(z) else: cell.set_value(0) z += 1 if __name__ == '__main__': G = [ (0, 2, 0, 5, 0, 1, 0, 9, 0), (8, 0, 0, 2, 0, 3, 0, 0, 6), (0, 3, 0, 0, 6, 0, 0, 7, 0), (0, 0, 1, 0, 0, 0, 6, 0, 0), (5, 4, 0, 0, 0, 0, 0, 1, 9), (0, 0, 2, 0, 0, 0, 7, 0, 0), (0, 9, 0, 0, 3, 0, 0, 8, 0), (2, 0, 0, 8, 0, 4, 0, 0, 7), (0, 1, 0, 9, 0, 7, 0, 6, 0), ] app = tk.Tk() app.resizable(False, False) app.tk_focusFollowsMouse() grid = SudokuGrid(app) grid.load(initial_values=G) grid.pack(fill='both') grid.update() grid.hint_cell( 1, 1, (1, 2, 5, 6)) app.mainloop()Les fenêtres toplevel dont les bordures ont été enlevées ne peuvent plus être gérées via le gestionnaire de fenêtre du système d'exploitation.
https://www.tcl.tk/man/tcl8.4/TkCmd/wm.htm#M37
Il serait donc sans doute plus simple d'insérer ces toplevels dans le canvas avec create_window pour ne pas se compliquer la vie.
Je vais tester pour voir si ça me satisfait.
Encore grand merci à toi jokler.