Publicité
+ Répondre à la discussion
Affichage des résultats 1 à 8 sur 8
  1. #1
    Membre Expert
    Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    mars 2006
    Messages
    827
    Détails du profil
    Informations personnelles :
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : Industrie

    Informations forums :
    Inscription : mars 2006
    Messages : 827
    Points : 1 145
    Points
    1 145

    Par défaut [tkinter] redimensionnement fenêtre

    Salut,

    j'ai une fenêtre qui contient 3 objets tk.Text et j'aimerais qu'un redimensionnement vertical de cette fenêtre se répercute sur le 3ème objet Text. Or on donne la hauteur de ces objets en nombre de lignes au lieu de pixels. Ce qui fait qu'un paramètre non maitrisé se rajoute, c'est la hauteur d'une ligne en fonction de la police. Dans le bout de code ci-dessous, la ligne 18 utilise empiriquement un diviseur de 16 pour redimensionner le tout... Y aurait une façon plus propre et plus universelle d'y arriver?

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
     
    import Tkinter as tk
    import sys
     
    def addTextBox(parent, text, height, row):
        widget = tk.Text(parent, height=height)
        widget.insert('end', text)
        sbar = tk.Scrollbar(parent, orient='vertical')
        widget["yscrollcommand"] = sbar.set
        sbar['command']=widget.yview
        widget.grid(sticky='ew',column=0, row=row)
        sbar.grid(column=1, row=row, sticky='ns')
        widget.update_idletasks()
        return widget
     
    def resize(event):
        height = win.winfo_height() - win.offset
        win.widget['height'] = height / 16
        widget.update_idletasks()
     
    win = tk.Tk()
    text = open(sys.argv[0]).read(-1)
    # creates 3 Text objects
    for row, height in enumerate([6, 6, 20]):
        widget = addTextBox(win, text, height, row)
    # prepare data for resize
    win.widget = widget
    win.offset = win.winfo_height() - widget.winfo_height()
    win.bind('<Configure>', resize)
    # infinite loop
    win.resizable(height=True, width=False)
    win.mainloop()
    A+

    Pfeuh

  2. #2
    Expert Confirmé Avatar de PauseKawa
    Homme Profil pro Patrice BLANGARIN
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    juin 2006
    Messages
    2 712
    Détails du profil
    Informations personnelles :
    Nom : Homme Patrice BLANGARIN
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : juin 2006
    Messages : 2 712
    Points : 3 899
    Points
    3 899

    Par défaut

    Bonsoir pfeuh,

    Pour cela j'utilise pack:
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    import Tkinter as tk
    import sys
     
     
    def addTextBox(parent, text, height, exp):
        frm = tk.Frame(win)
        frm.pack(fill=tk.BOTH, expand=exp)
        widget = tk.Text(frm, height=height)
        widget.insert('end', text)
        sbar = tk.Scrollbar(frm, orient='vertical')
        widget["yscrollcommand"] = sbar.set
        sbar['command'] = widget.yview
        widget.pack(side=tk.LEFT, fill=tk.Y)
        sbar.pack(side=tk.LEFT, fill=tk.Y)
     
     
    win = tk.Tk()
    text = open(sys.argv[0]).read(-1)
    for height, exp in ((6, 0), (6, 0), (20, 1)):
        widget = addTextBox(win, text, height, exp)
    win.resizable(height=True, width=False)
    win.mainloop()
    @+
    Merci d'utiliser le forum pour les questions techniques.

  3. #3
    Expert Confirmé Avatar de PauseKawa
    Homme Profil pro Patrice BLANGARIN
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    juin 2006
    Messages
    2 712
    Détails du profil
    Informations personnelles :
    Nom : Homme Patrice BLANGARIN
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : juin 2006
    Messages : 2 712
    Points : 3 899
    Points
    3 899

    Par défaut

    La solution grid au passage:
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    import Tkinter as tk
    import sys
     
     
    def addTextBox(parent, text, height, row):
        widget = tk.Text(parent, height=height)
        widget.insert('end', text)
        sbar = tk.Scrollbar(parent, orient='vertical')
        widget["yscrollcommand"] = sbar.set
        sbar['command'] = widget.yview
        widget.grid(sticky='nsew', column=0, row=row)
        sbar.grid(column=1, row=row, sticky='nsew')
     
     
    win = tk.Tk()
    with open(sys.argv[0]) as source:
        text = source.read()
    # creates 3 Text objects
    for row, height in enumerate((6, 6, 20)):
        addTextBox(win, text, height, row)
    win.grid_rowconfigure(2, weight=1)  # <<<<
    # infinite loop
    win.resizable(height=True, width=False)
    win.mainloop()
    Mais cela s'applique à tous les Widgets de la column/du row (grid_columnconfigure/grid_rowconfigure)
    et il nécessaire de penser à l'utiliser pour les différents niveaux.
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    import Tkinter as tk
    import sys
     
     
    def addTextBox(parent, text, height, row, col):
        frm = tk.Frame(parent)
        frm.grid(column=col, row=row, sticky='nsew')
        widget = tk.Text(frm, height=height)
        widget.insert('end', text)
        sbar = tk.Scrollbar(frm, orient='vertical')
        widget["yscrollcommand"] = sbar.set
        sbar['command'] = widget.yview
        widget.grid(column=0, row=0, sticky='nsew')
        sbar.grid(column=1, row=0, sticky='nsew')
        frm.grid_rowconfigure(0, weight=1)
     
     
    win = tk.Tk()
    with open(sys.argv[0]) as source:
        text = source.read()
    # creates 6 Text objects
    for col in range(2):
        for row, height in enumerate((6, 6, 20)):
            addTextBox(win, text, height, row, col)
    win.grid_rowconfigure(2, weight=1)
    # infinite loop
    win.resizable(height=True, width=False)
    win.mainloop()
    Merci d'utiliser le forum pour les questions techniques.

  4. #4
    Membre Expert
    Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    mars 2006
    Messages
    827
    Détails du profil
    Informations personnelles :
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : Industrie

    Informations forums :
    Inscription : mars 2006
    Messages : 827
    Points : 1 145
    Points
    1 145

    Par défaut

    Salut,

    Merci pour cette réponse, c'est exactement ce que je cherchais. En plus, quand je t'ai vu utiliser "with open", j'ai eu le déclic sur le fonctionnement de cette commande.

    A+

    Pfeuh

  5. #5
    Membre Expert
    Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    mars 2006
    Messages
    827
    Détails du profil
    Informations personnelles :
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : Industrie

    Informations forums :
    Inscription : mars 2006
    Messages : 827
    Points : 1 145
    Points
    1 145

    Par défaut

    Salut,

    Autant j'arrive à me débrouiller avec un objet simple, autant j'ai du mal avec le widget Canvas... Mon but est d'afficher une liste d'objets avec une scrollbar, et de pouvoir modifier la hauteur de la fenêtre contenant la liste d'objets... Pas facile! Enfin, j'ai déjà un début dans le sens où le Labelframe contenant la liste s'ajuste bien aux changements de hauteur...

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
     
    import Tkinter as tk
    import sys
     
    def buttonCallback(y, text):
        print "button %s[%i] pressed"%(text, y)
     
    def cellCallback(event, x, y, text):
        print "cell[%i, %i]=%s"%(x, y, text)
     
    class FIXED_OBJECT(tk.LabelFrame):
        def __init__(self, container, title='', text='', **kwds):
            tk.LabelFrame.__init__(self, container, text=title, **kwds)
            self.editor = tk.Text(self, **kwds)
            self.editor.insert('end', text)
            self.editor.grid(column=0, row=0, sticky='nsew')
            self.scrollbar = tk.Scrollbar(self, orient='vertical')
            self.scrollbar.grid(column=1, row=0, sticky='ns')
            self.editor['yscrollcommand'] = self.scrollbar.set
            self.scrollbar.config(command=self.editor.yview)
     
    class RESIZABLE_OBJECT(tk.LabelFrame):
        def __init__(self, container, title='', data=None, **kwds):
            tk.LabelFrame.__init__(self, container, text=title, **kwds)
            self.canvas = tk.Canvas(self, height=250)
            self.frm = tk.Frame(self.canvas)
            self.canvas.create_window(0, 0, window=self.frm)
            self.placeData(data)
            self.frm.grid()
            self.canvas.grid(column=0, row=0, sticky='nsew')
            self.scrollbar = tk.Scrollbar(self, orient='vertical')
            self.scrollbar.grid(column=1, row=0, sticky='ns')
            self.canvas['yscrollcommand'] = self.scrollbar.set
            self.scrollbar['command'] = self.canvas.yview
     
        def placeData(self, data):
            for y, line in enumerate(data):
                if y & 1:
                    color = 'green'
                else:
                    color = 'white'
                for x in range(6):
                    if x < len(line):
                        cell = line[x]
                    else:
                        cell = '. . . .'
                    cellgui = tk.Label(self.frm, text=cell, width=16, bg=color, cursor='hand2')
                    cellgui.grid(column=x, row=y)
                    cellgui.bind("<Button-1>", lambda event=None, x=x, y=y, label2=cell:cellCallback(event, x, y, label2))
                tk.Button(self.frm, text='read', width=3, command=lambda y=y, label='read':buttonCallback(y, label)).grid(column=6, row=y)
                tk.Button(self.frm, text='write', width=3, command=lambda y=y, label='write':buttonCallback(y, label)).grid(column=7, row=y)
     
    class WINDOW(tk.Toplevel):
        def __init__(self, container, *args, **kwds):
            tk.Toplevel.__init__(self, container, *args, **kwds)
            with open(sys.argv[0]) as fp:
                default_text= fp.read(-1)
            with open(sys.argv[0]) as fp:
                lines= fp.readlines()[:30]
            data = [line.split()[:5] for line in lines]
            self.widget1 = FIXED_OBJECT(self, title='RAW PDO', text=default_text, width=40, height=2)
            self.widget2 = FIXED_OBJECT(self, title='PDO OBJECTS', text=default_text, width=80, height=4)
            self.widget3 = RESIZABLE_OBJECT(self, "EDS OBJECTS", data)
            self.widget1.grid()
            self.widget2.grid()
            self.widget3.grid(sticky='nsew')
            self.grid_rowconfigure(2, weight=1)
            self.offset = self.winfo_height() - self.widget3.canvas.winfo_height()
            self.resizable(height=True, width=False)
     
    if __name__ == "__main__":
     
        win = tk.Tk()
        node = WINDOW(win)
        win.mainloop()
    A+

    Pfeuh

  6. #6
    Expert Confirmé Avatar de PauseKawa
    Homme Profil pro Patrice BLANGARIN
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    juin 2006
    Messages
    2 712
    Détails du profil
    Informations personnelles :
    Nom : Homme Patrice BLANGARIN
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : juin 2006
    Messages : 2 712
    Points : 3 899
    Points
    3 899

    Par défaut

    Bonjour,

    En fait je ne comprend pas ce jeu de matriochkas: LabelFrame > Canvas > Frame avec un .create_window().
    Pourquoi utiliser self.canvas et non directement self.frm ? Après tout c'est lui qui nous intéresses (Du moins dans placeData).
    Note: Rien n'interdit de mixer les géométry manager si ce n'est pas pour un même niveau de widget et que cela apporte un avantage.

    @+
    Merci d'utiliser le forum pour les questions techniques.

  7. #7
    Membre Expert
    Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    mars 2006
    Messages
    827
    Détails du profil
    Informations personnelles :
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : Industrie

    Informations forums :
    Inscription : mars 2006
    Messages : 827
    Points : 1 145
    Points
    1 145

    Par défaut

    Citation Envoyé par PauseKawa Voir le message
    Pourquoi utiliser self.canvas et non directement self.frm ?
    Parce qu'il me semble que c'est la seule façon de gérer une scrollbar pour les lignes de data. J'ai toujours trouvé ça lourd, mais je ne sais pas comment faire autrement. je viens de vérifier, l'objet Frame n'a pas de yscrollcommand.

  8. #8
    Membre Expert
    Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    mars 2006
    Messages
    827
    Détails du profil
    Informations personnelles :
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : Industrie

    Informations forums :
    Inscription : mars 2006
    Messages : 827
    Points : 1 145
    Points
    1 145

    Par défaut

    Suite à tes précieux conseils, j'ai réussi à rendre un canvas redimensionable... Entre parenthèse que c'est compliqué de faire du code simple! Je pense que toute l'astuce est dans le sheet['scrollregion'] par contre pour quelque chose comme mon placeData, qui utilise grid, impossible d'arriver au même résultat. Je continue quand même.

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
     
    import Tkinter as tk
    import random as random
    import sys
    colors = ['red', 'blue', 'green', 'yellow']
     
    def drawEllipses(widget):
        for iter in range(200):
            x1 = random.randrange(0, 2000)
            y1 = random.randrange(0, 2000)
            x2 = x1 + random.randrange(100, 300)
            y2 = y1 + random.randrange(100, 300)
            idx_color = random.randrange(0, 4)
            widget.create_oval(x1, y1, x2, y2, fill=colors[idx_color])
     
    def getScrollableObject(parent):
        sheet = tk.Canvas(parent)
        drawEllipses(sheet)
        sbarv = tk.Scrollbar(parent,command=sheet.yview)
        sbarh = tk.Scrollbar(parent,command=sheet.xview, orient='horizontal')
        sheet.grid(column=0, row=0, sticky='nsew')
        sbarv.grid(column=1, row=0, sticky='ns')
        sbarh.grid(column=0, row=1, sticky='ew')
        sheet['yscrollcommand'] = sbarv.set
        sheet['xscrollcommand'] = sbarh.set
        sbarv['command'] = sheet.yview
        sbarh['command'] = sheet.xview
        sheet['scrollregion'] = sheet.bbox("all")
     
    win = tk.Tk()
    getScrollableObject(win)
    win.grid_rowconfigure(0, weight=1)
    win.grid_columnconfigure(0, weight=1)
    win.mainloop()

Liens sociaux

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •