Python Facile

Source : tkFrameGrid.py

 
#! /usr/bin/env python
# -*- coding: cp1252 -*-
"""
Nom:
    GLu_tkFrameGrid.py
Description:
    Classe basée sur Tkinter.Frame permettant de positionner un widget par
    rapport à la position de celui précédement placé.

Auteur: Lionel Grolleau <pythonfacile (at) free (dot) fr>
Date: 20/08/2005
Version: 0.1.0
License: GPL
Test: Python 2.3.4 sous Win_XP.

Utilisation:
    Après initialisation de la classe, on utilise la methode gridPosition pour
    placer les différents widgets les uns par rapport aux autres. Si on utilise
    la méthode grid d'un widget de façon classique, celui-ci sera utilisé pour
    positionner le prochain widget par la méthode gridPosition.

    L'option 'colonnes' sert à gérer le retour à la ligne automatique.

    L'option 'etendre' est un mixte de sticky et d'agrandissement des colonnes
    et/ou des lignes.

Attention:
    Ne pas utiliser de méthode pack ou place pour les widgets avec cette classe.

    De plus cette classe ne gére pas l'option 'rowspan' des widgets précédents
    pour calculer la position du prochain widget.
"""

__all__ = ['GLu_tkFrameGrid',
                'A_DROITE', 'LE_RESTE', 'EN_TITRE', 'LIGNE_SV', 'DESSOUS',
                'TITRE']

## Import Tk
import Tkinter
from Tkconstants import *

import sys

## Definition Constantes
A_DROITE = '>' # place le widget a coté du précedent
LE_RESTE = '-' # place le widget sur le reste de la ligne
EN_TITRE = '=' # place le widget sur la totalité de la ligne suivante
LIGNE_SV = '+' # place le widget au début de la ligne suivante
DESSOUS = 'v' # place le widget au dessous sur la ligne suivante
TITRE = 'titre' # Etendre les titres uniquement
#
class TkFrameGrid(Tkinter.Frame):
    """Classe basée sur un widget Tkinter.Frame."""
    def __init__(self, master=None, colonnes=1, etendre=None, cnf={}, **kw):
        """Construit un widget Frame avec parent MASTER

        OPTIONS STANDARD

            Toutes les options d'un widget Frame

        OPTIONS SPECIFIQUES DU WIDGET

            COLONNES = Nombres de colonnes dans le Frame.
            ETENDRE = Etendre les colonnes, lignes et/ou 'titres'.
            None    (None)  Ne rien étendre (valeur par défaut).
            x       (X)     Etendre les colonnes.
            y       (Y)     Etendre les lignes.
            both    (BOTH)  Etendre les colonnes et les lignes.
            titre   (TITRE) Etendre Les titres.
        """
        cnf = Tkinter._cnfmerge((cnf, kw))
        self.__colonnes = colonnes
        self.__etrendre = etendre
        self.__lastrow = -1
        self.__lastcolumn = -1
        Tkinter.Frame.__init__(self, master, cnf)
        if self.__etrendre in [ X, BOTH, TITRE]:
            [ self.columnconfigure(c, weight=1) for c in range(self.__colonnes) ]
    def gridPosition(self, widget, position=None, cnf={}, **kw):
        """Place un WIDGET en fonction de la POSITION du précédent.

        Cette méthode est prévue pour être utilisée à la place ou en complément
        de la méthode grid.

        OPTIONS STANDARD

            Toutes les options de la méthode grid

        OPTIONS SPECIFIQUES DE LA METHODE

            POSITION = défini la position du widget par rapport au précédent :
            >    (A_DROITE) place le widget a coté du précedent.
            -    (LE_RESTE) place le widget sur le reste de la ligne.
            =    (EN_TITRE) place le widget sur toute la ligne suivante.
            +    (LIGNE_SV) place le widget au début de la ligne suivante.
            v    (DESSOUS)  place le widget au dessous sur la ligne suivante.
         """
        if self.grid_slaves():
            last_slaves = self.grid_slaves()[0]
            self.__lastcolumn = int(last_slaves.grid_info()['column']) + \
                int(last_slaves.grid_info()['columnspan']) - 1
            self.__lastrow = int(last_slaves.grid_info()['row'])
        cnf = Tkinter._cnfmerge((cnf, kw))
        if self.__etrendre in [X, TITRE]:
            cnf['sticky'] = W+E
        elif self.__etrendre == Y:
            cnf['sticky'] = N+S
        elif self.__etrendre == BOTH:
            cnf['sticky'] = W+E+N+S
        if position == A_DROITE:
            cnf['column'] = self.__lastcolumn +1
            cnf['row'] = max(self.__lastrow, 0)
            if cnf['column'] == self.__colonnes:
                cnf['column'] = 0
                cnf['row'] = self.__lastrow + 1
        elif position == LE_RESTE:
            cnf['column'] = self.__lastcolumn + 1
            cnf['row'] = max(self.__lastrow, 0)
            cnf['columnspan'] = self.__colonnes - self.__lastcolumn
            if cnf['column'] == self.__colonnes:
                cnf['column'] = 0
                cnf['row'] = self.__lastrow + 1
                cnf['columnspan'] = self.__colonnes
            if self.__etrendre in [Y, BOTH]:
                cnf['sticky'] = W+E+N+S
            else: # None X TITRE
                cnf['sticky'] = W+E
        elif position == EN_TITRE:
            cnf['column'] = 0
            cnf['row'] = self.__lastrow + 1
            cnf['columnspan'] = self.__colonnes
            if self.__etrendre in [Y, BOTH, TITRE]:
                cnf['sticky'] = W+E+N+S
                self.rowconfigure(cnf['row'], weight=2)
            else: # None X
                cnf['sticky'] = W+E
        elif position == LIGNE_SV:
            cnf['column'] = 0
            cnf['row'] = self.__lastrow + 1
        elif position == DESSOUS:
            cnf['column'] = self.__lastcolumn
            cnf['row'] = self.__lastrow + 1
        widget.grid(cnf)
        self.__lastcolumn = int(widget.grid_info()['column']) + \
            int(widget.grid_info()['columnspan']) - 1
        self.__lastrow = int(widget.grid_info()['row'])
        if self.__etrendre in [Y, BOTH] and position <> EN_TITRE:
            self.rowconfigure(self.__lastrow, weight=1)
    def getLastColumn(self):
        """ Retourne la colonne du dernier widget positionné."""
        if self.grid_slaves():
            last_slaves = self.grid_slaves()[0]
            self.__lastcolumn = int(last_slaves.grid_info()['column']) + \
                int(last_slaves.grid_info()['columnspan']) - 1
            return self.__lastcolumn
    def getLastRow(self):
        """ Retourne la ligne du dernier widget positionné."""
        if self.grid_slaves():
            self.__lastrow = int(self.grid_slaves()[0].grid_info()['row'])
            return self.__lastrow
#
def main():
    root = Tkinter.Tk()
    frm = TkFrameGrid(root,
        colonnes=3,
        etendre=TITRE, bd=2)
    frm.grid(sticky=W+E+N+S)
    root.rowconfigure(0, weight=1)
    root.columnconfigure(0, weight=1)
    w = Tkinter.Label(frm,
        text='EN_TITRE [0]',
        relief=RAISED,
        bg = 'light steel blue',
        width=14,
        bd=2)
    frm.gridPosition(w, position=EN_TITRE, ipady=5)
    for i in range(1, 6):
        w = Tkinter.Label(frm,
            text='A_DROITE [%s]' % i,
            relief=SUNKEN,
            width=14,
            bd=2)
        frm.gridPosition(w, position=A_DROITE, ipady=5)
    w = Tkinter.Label(frm,
        text='LIGNE_SV [6]',
        relief=RAISED,
        width=14,
        bd=2)
    frm.gridPosition(w, position=LIGNE_SV, ipady=5)
    for i in range(7, 11):
        w = Tkinter.Label(frm,
            text='A_DROITE [%s]' % i,
            relief=SUNKEN,
            width=14,
            bd=2)
        frm.gridPosition(w, position=A_DROITE, ipady=5)
    w = Tkinter.Label(frm,
        text='DESSOUS [11]',
        relief=RAISED,
        width=14,
        bd=2)
    frm.gridPosition(w, position=DESSOUS, ipady=5)
    w = Tkinter.Label(frm,
        text='EN_TITRE [12]',
        relief=RAISED,
        bg = 'light steel blue',
        width=14,
        bd=2)
    frm.gridPosition(w, position=EN_TITRE, ipady=5)
    for i in range(13, 17):
        w = Tkinter.Label(frm,
            text='A_DROITE [%s]' % i,
            relief=SUNKEN,
            width=14,
            bd=2)
        frm.gridPosition(w, position=A_DROITE, ipady=5)
    w = Tkinter.Label(frm,
        text='LE_RESTE [17]',
        relief=RAISED, 
        width=14,
        bd=2)
    frm.gridPosition(w, position=LE_RESTE, ipady=5)
    root.title('GLu_tkFrameGrid')
    root.mainloop()
#
if __name__ == '__main__':
    if sys.stdout.encoding:
        print __doc__.decode('cp1252').encode(sys.stdout.encoding)
    else:
        print __doc__
    main()