Forum Programmation.python Tkinter et scrollbar

Posté par  (Mastodon) . Licence CC By‑SA.
Étiquettes :
2
18
fév.
2025

Je suis content de mon code et je cherche à mettre plus d'équipes dorénavant.
Du coup, j'aurais besoin de rajouter une scrollbar sur la fenêtre principale; quelqu'un saurait faire?

https://framagit.org/vev/elo-lvgsports
"Elo LVGsports.py"

ps: pour faire marcher le code sur gnu/linux il faut changer le \ en / ligne 299
ps2: vous pouvez rajouter des joueurs dans le fichier "joueurs.json"
exemple avec 24 joueurs nommés 0001, 0002 etc..
{"0001": ["1500", "0", "0", "0", "aucun enregistrement"], "0002": ["1500", "0", "0", "0", "aucun enregistrement"], "0003": ["1500", "0", "0", "0", "aucun enregistrement"], "0004": ["1500", "0", "0", "0", "aucun enregistrement"], "0005": ["1500", "0", "0", "0", "aucun enregistrement"], "0006": ["1500", "0", "0", "0", "aucun enregistrement"], "0007": ["1500", "0", "0", "0", "aucun enregistrement"], "0008": ["1500", "0", "0", "0", "aucun enregistrement"], "0009": ["1500", "0", "0", "0", "aucun enregistrement"], "0010": ["1500", "0", "0", "0", "aucun enregistrement"], "0011": ["1500", "0", "0", "0", "aucun enregistrement"], "0012": ["1500", "0", "0", "0", "aucun enregistrement"], "0013": ["1500", "0", "0", "0", "aucun enregistrement"], "0014": ["1500", "0", "0", "0", "aucun enregistrement"], "0015": ["1500", "0", "0", "0", "aucun enregistrement"], "0016": ["1500", "0", "0", "0", "aucun enregistrement"], "0017": ["1500", "0", "0", "0", "aucun enregistrement"], "0018": ["1500", "0", "0", "0", "aucun enregistrement"], "0019": ["1500", "0", "0", "0", "aucun enregistrement"], "0020": ["1500", "0", "0", "0", "aucun enregistrement"],"0021": ["1500", "0", "0", "0", "aucun enregistrement"], "0022": ["1500", "0", "0", "0", "aucun enregistrement"], "0023": ["1500", "0", "0", "0", "aucun enregistrement"], "0024": ["1500", "0", "0", "0", "aucun enregistrement"]}

  • # Commentaire supprimé

    Posté par  . Évalué à 4 (+2/-0).

    Ce commentaire a été supprimé par l’équipe de modération.

    • [^] # Re: / tout le temps ?

      Posté par  (Mastodon) . Évalué à 2 (+1/-0).

      merci, je virerai les antislashs

    • [^] # Re: / tout le temps ?

      Posté par  . Évalué à 5 (+2/-0).

      Je confirme, ça fait des années que j'utilise le /

      1) parce que c'est plus facile d'accès sur des claver averti azerty
      2) parce que c'est chiant de devoir les protéger par un \ ou de devoir préciser que la chaîne est littérale; surtout quand il faut réévaluer des variables dedans
      2bis) parce que c'est enquiquinant au possible de devoir protéger les \ lors de réévaluation, path\ton\noreille risque a grès des évaluation de se transformer en \n, qui est un retour à la ligne (\t une tabulation) et donc faut path\\ton\\noreille ; et
      3) on ne sais jamais si on va avoir des interprétation, typiquement chemin.vers.cave=${USER}\nicolas risque de poser problème
      4) ça faut gagner un caractère à tapper en C, C++, java, et donc ça simplifie les grep
      5) on sait jamais quand ça va être interprété (\b bell, \t tabulation \r retour chariot…)

      bref, il n'y a aucune raison d'user le \ comme séparateur de dossiers, utiliser / fonctionne dans l'explorateur windows, fonctionne comme paramètres chemin.vers.cave=${USER}/nicolas, n'a pas de soucis d'interprétation ou réinterprétation…). Il y'a par contre toutes les raisons de le bannir en tant que séparateur de fichiers (et ce serait pas mal que ms change l'affichage des \ en / dans la barre d'adresse de l'explorateur (et non l'inverse)

      Il ne faut pas décorner les boeufs avant d'avoir semé le vent

  • # on ne peut pas en l'état

    Posté par  . Évalué à 2 (+1/-0).

    On ne peut mettre un scroll que sur les widgets Text et Canvas, il va donc falloir que tu revoies et réagence le tout. Je pense qu'un canvas en y intégrant tes labels et radios avec la méthode create_window devrait convenir.

    En revanche chez moi ton script jette plusieurs erreurs, le json des joueurs n'est pas en utf8 mais en iso-8859-1, et comme tu n'as pas spécifié l'encodage dans open.
    Les smileys dans ton code ne passent chez moi :

    _tkinter.TclError: character U+1f60a is above the range (U+0000-U+FFFF) allowed by Tcl

    Préfère aussi les espaces que les tabulations pour indenter ton code.

    • [^] # Re: on ne peut pas en l'état

      Posté par  (Mastodon) . Évalué à 1 (+0/-0).

      merci gled pour toutes ces infos;
      donc, a priori, gros travail pour passer en canvas(faudra que je regarde), je vais peut etre devoir changer les radiobuttons en listbox :s

      • [^] # Re: on ne peut pas en l'état

        Posté par  . Évalué à 2 (+1/-0). Dernière modification le 19 février 2025 à 17:45.

        Un truc fait à l'arrache avec une frame et un simple canvas.
        Il faudrait quand même revoir ton script, et utiliser des frames pour grouper les widgets de ta fenêtre, là, c'est un peu le bazar.

        can_frame = tk.Frame(cadre, bd=2, highlightbackground='grey')
        can_frame.grid(padx=10, pady=10)
        line_height = 40
        can = tk.Canvas(
            can_frame,
            width=280,
            height=line_height * 10,
            highlightthickness=0,
            yscrollincrement=line_height,
        )
        can.grid(row=0, column=0)
        scroll = tk.Scrollbar(
            can_frame, width=20, orient=tk.VERTICAL, highlightthickness=0,
        )
        scroll.grid(row=0, column=1, sticky=tk.NSEW)
        can.config(yscrollcommand=scroll.set)
        scroll.config(command=can.yview)
        colors = 'lightGreen', 'lightBlue'
        radios_base_options = dict(
            fg='grey',
            highlightthickness=0,
        )
        for i in range(nb_joueurs):
            radios_options = dict(
                text=liste_joueurs[i],
                value=liste_joueurs[i],
                bg=colors[i % 2],
            )
            can.create_rectangle(
                0,
                i * line_height,
                can['height'],
                (i + 1) * line_height,
                fill=radios_options['bg'],
                width=0,
            )
            radio = tk.Radiobutton(
                can, variable=j1a, **radios_base_options, **radios_options
            )
            can.create_window(
                0,
                i * line_height + line_height / 2,
                window=radio,
                anchor=tk.W,
            )
            radio = tk.Radiobutton(
                can, variable=j1b, **radios_base_options, **radios_options
            )
            can.create_window(
                int(can['width']) / 2,
                i * line_height + line_height / 2,
                window=radio,
                anchor=tk.W,
            )
        can.configure(scrollregion=(0, 0, 0, i * line_height))

        Reste plus qu'à intégrer cela dans ton interface {º_º}

        Bonne continuation.

        • [^] # Re: on ne peut pas en l'état

          Posté par  (Mastodon) . Évalué à 1 (+0/-0).

          merci gled, je regarderai ça
          saurais tu changer mes radiobuttons en listbox? j'aime moins mais ça me permettrait de l'utiliser

          • [^] # Avec deux listbox

            Posté par  . Évalué à 1 (+0/-0).

            Un autre code fait à l'arrache =D

            import tkinter as tk
            from tkinter import font as tk_font
            import json
            
            SCROLL_WIDTH = 18
            LISTBOX_HEIGHT = 12
            
            def players_load(path):
                with open(path) as f:
                    return json.load(f)
            
            def player_select(list_box):
                i = list_box.curselection()
                if not i:
                    return
                value = list_box.get(i)
                if players_selected[not list_box.id] == value:
                    return
                players_selected[list_box.id] = value
                players_label.config(
                    text=f'{players_selected[0]} - {players_selected[1]}'
                )
            
            players_selected = {0:'', 1:'',}
            players = dict(sorted(players_load('joueurs.json').items()))
            list_box_width = max(len(p) for p in players) + 2
            
            window = tk.Tk()
            font = tk_font.Font(family='mono', size=18)
            
            frame_box = tk.Frame(window, bg='#000')
            frame_box.grid()
            
            left_scroll = tk.Scrollbar(
                frame_box, orient=tk.VERTICAL, width=SCROLL_WIDTH,
            )
            left_scroll.grid(row=0, column=0, sticky=tk.NSEW,)
            left_list = tk.Listbox(
                frame_box,
                font=font,
                width=list_box_width,
                height=LISTBOX_HEIGHT,
                xscrollcommand=left_scroll.set,
                yscrollcommand=left_scroll.set,
            )
            left_list.grid(row=0, column=1, padx=(10, 5),)
            left_scroll.config(command=left_list.yview)
            left_list.id = 0 # C'est crade !
            
            right_scroll = tk.Scrollbar(
                frame_box, orient=tk.VERTICAL, width=SCROLL_WIDTH,
            )
            right_scroll.grid(row=0, column=3, sticky=tk.NSEW,)
            right_list = tk.Listbox(
                frame_box,
                font=font,
                width=list_box_width,
                height=LISTBOX_HEIGHT,
                xscrollcommand=right_scroll.set,
                yscrollcommand=right_scroll.set,
            )
            right_list.grid(row=0, column=2, padx=(5, 10),)
            right_scroll.config(command=right_list.yview)
            right_list.id = 1 # C'est crado !
            
            players_label = tk.Label(
                frame_box, height=3, font=font, bg='#000', fg='#fff',
            )
            players_label.grid(row=1, column=0, columnspan=4,)
            
            left_list.insert(0, *players)
            right_list.insert(0, *players)
            
            left_list.bind(
                '<<ListboxSelect>>', lambda e: player_select(left_list)
            )
            right_list.bind(
                '<<ListboxSelect>>', lambda e: player_select(right_list)
            )
            
            window.mainloop()

            Y a des trucs un peu moches, notamment d'insérer des attributs id aux listbox (permettant de savoir si la sélection courante n'est pas la même que celle de l'autre listbox), il serait préférable de créer une classe dérivée de Listbox et y intégrer un id via un attribut de classe.

Envoyer un commentaire

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.