IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Tkinter Python Discussion :

feuille de calcul canvas/frame


Sujet :

Tkinter Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre Expert
    Profil pro
    Développeur en systèmes embarqués retraité
    Inscrit en
    Mars 2006
    Messages
    952
    Détails du profil
    Informations personnelles :
    Localisation : France, Bas Rhin (Alsace)

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

    Informations forums :
    Inscription : Mars 2006
    Messages : 952
    Par défaut feuille de calcul canvas/frame
    Salut,

    j'essaie de faire une feuille de calcul et je rencontre un problème. Je pose des entries dans une frame appartenant à un canvas, et arrive le moment du
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    canvas['scrollregion'] = (0, 0, width, height)
    où width et height représentent la taille de ma feuille/frame. Le seul moyen que j'ai trouvé, c'est de prendre par exemple la largeur de ma cellule (le widget Entry) et de la multiplier par le nombre de colonnes:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    width = entry.winfo_reqwidth() * maxcols
    height = entry.winfo_reqheight() * maxrows
    ça marchote, mais ça ne me convient pas du tout, puisqu'on est obligé d'uniformiser la taille des widgets. Ça interdit par exemple d'utiliser des labels (puisque taille variable) pour légender la première ligne et la première colonne. J'ai beau avoir épluché le Tkinter Reference, je n'ai pas trouvé le moyen d'avoir une largeur et une hauteur correcte pour une frame contenant des widgets. Si quelqu'un sait comment faire, je prends.

    A+

    Pfeuh

  2. #2
    Membre Expert Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    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 725
    Par défaut
    Bonsoir,

    Si je ne me trompe tu utilise un .create_window pour positionner un widget Frame contenant des labels qui te servent de cellule.
    Et tu souhaite avoir le width/height du widget pour faire ton scrollregion.
    C'est bien cela ?
    Il me semble que cela correspond à ce sujet.

    Bon code

  3. #3
    Membre très actif
    Avatar de afranck64
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2009
    Messages
    592
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : Cameroun

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2009
    Messages : 592
    Par défaut
    Bonsoir,

    Tu as essayé de regarder du côté de Tix?
    Tix.Grid
    ça pourrait faire l'affaire
    Win 10 64 bits / Linux Mint 18, - AMD A6 Quad: Py27 / Py35
    CONTENU D'UNE QUESTION
    Exemples:
    - Configuration (système d'exploitation, version de Python et des bibliothèques utilisées)
    - Code source du morceau de programme où il y a un bogue
    - Ligne de code sur laquelle le bogue apparaît
    - Erreur complète retournée pas l'interpréteur Python
    - Recherche déjà effectuée (FAQ, Tutoriels, ...)
    - Tests déjà effectués

  4. #4
    Membre Expert Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    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 725
    Par défaut
    Bonsoir,

    Sans doute afranck64, mais je pense qu'un bout de code de pfeuh serait utile.
    C'est rare de voir du code Tkinter avec un create_window sur le forum d'où mon questionnement : C'est bien cela ?
    Mettre un widget Frame dans un Canvas pour utiliser son scrollregion ? Il me semble qu'il existe plus simple.

    Un petit bout de code pfeuh ?

    Bonne soirée

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

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

    Informations forums :
    Inscription : Mars 2006
    Messages : 952
    Par défaut
    Tix, je connais, mais je ne crois pas qu'il y ait de feuille de calcul toute faite?
    Citation Envoyé par PauseKawa Voir le message
    Mettre un widget Frame dans un Canvas pour utiliser son scrollregion ? Il me semble qu'il existe plus simple.
    C'est exactement ce que j'ai essayé de faire. C'est un peu long, désolé, mais voici le bout de code

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
     
    import Tkinter
    import tkMessageBox
     
    def askcells(cells, firstcolumn=[], firstrow=[], **kwds):
        win = Tkcells(cells, firstcolumn, firstrow, **kwds)
        return win.go()
     
    class Tkcells(Tkinter.Toplevel):
        OK = 'OK'
        CANCEL = 'CANCEL'
        REINIT = 'REINIT'
        BT_WIDTH = 12
        CELL_WIDTH = 12
        WIDTH = 400
        HEIGHT= 200
        def __init__(self, cells, firstcolumn=[], firstrow=[], **kwds):
            #arguments dispatching
            can_width = Tkcells.WIDTH
            if 'width' in kwds.keys():
                can_width = kwds['width']
                kwds.pop('width')
            can_height = Tkcells.HEIGHT
            if 'height' in kwds.keys():
                can_height = kwds['height']
                kwds.pop('height')
            if 'title' in kwds.keys():
                title = kwds['title']
                kwds.pop('title')
            else:
                title = None
            if 'parent' in kwds.keys():
                self.parent = kwds['parent']
                kwds.pop('parent')
            else:
                self.parent = None
            #window creation
            Tkinter.Toplevel.__init__(self, parent=self.parent, **kwds)
            self.protocol('WM_DELETE_WINDOW', self.abort)
            if title != None:
                self.title(title)
            self.cells = cells
            self.firstcolumn = firstcolumn
            self.firstrow = firstrow 
            self.tkvars = []
            self.cellfrm = Tkinter.Frame(self, bd=0)
            self.can = Tkinter.Canvas(self.cellfrm, width=can_width, height=can_height, bd=0)
            self.vsb = Tkinter.Scrollbar(self.cellfrm, orient=Tkinter.VERTICAL)
            self.hsb = Tkinter.Scrollbar(self.cellfrm, orient=Tkinter.HORIZONTAL)
            self.sheet = Tkinter.Frame(self.can, bd=0)
            self.can.create_window(0,0, window=self.sheet)
            self.btfrm = Tkinter.Frame(self)
            self.statusbar = Tkinter.StringVar()
            Tkinter.Label(self.btfrm, textvariable=self.statusbar).grid(column=0, row=0)
            Tkinter.Button(self.btfrm, width=Tkcells.BT_WIDTH, text=Tkcells.REINIT, command=self.reinit).grid(column=1, row=0)
            Tkinter.Button(self.btfrm, width=Tkcells.BT_WIDTH, text=Tkcells.OK, command=self.accept).grid(column=2, row=0)
            Tkinter.Button(self.btfrm, width=Tkcells.BT_WIDTH, text=Tkcells.CANCEL, command=self.abort).grid(column=3, row=0)
            #cells filling
            maxcols = len(firstrow)
            if firstcolumn == []:
                for index in range(len(cells)):
                    firstcolumn.append(index+1)
                    cols = len(cells[index])
                    if cols > maxcols:
                        maxcols = cols
            for index, label in enumerate(firstcolumn):
                Tkinter.Label(self.sheet, text=label).grid(column=0, row=index+1)
            if firstrow == []:
                for index in range(maxcols):
                    firstrow.append(self.intToColLabel(index))
            for index, label in enumerate(firstrow):
                Tkinter.Label(self.sheet, text=label).grid(column=index+1, row=0)
            for y, row in enumerate(self.cells):
                tkrow = []
                for x, column in enumerate(row):
                    cell = Tkinter.StringVar()
                    cell.set(column)
                    tkrow.append(cell)
                    entry = Tkinter.Entry(self.sheet, text=label, textvariable=cell)
                    entry.grid(column=x+1, row=y+1)
                    entry.bind("<Enter>", lambda e, x=x, y=y:self.updateStatusbar(x, y))
                    entry.bind("<Leave>", lambda e:self.clearStatusbar())
                self.tkvars.append(tkrow)
            self.bind("<Escape>", self.abort)
            width = entry.winfo_reqwidth() * (maxcols + 1)
            height = entry.winfo_reqheight() * (len(self.cells) + 1)
            self.can['scrollregion'] = (0, 0, width, height)
     
        def go(self):
            self.can['yscrollcommand'] = self.vsb.set
            self.can['xscrollcommand'] = self.hsb.set
            self.vsb.config(command=self.can.yview)
            self.hsb.config(command=self.can.xview)
            self.sheet.grid()
            self.can.grid(column=0, row=0, sticky=Tkinter.W)
            self.vsb.grid(column=1, row=0, sticky=Tkinter.S+Tkinter.N)
            self.hsb.grid(column=0, row=1, sticky=Tkinter.W+Tkinter.E)
            self.cellfrm.grid()
            self.btfrm.grid(sticky=Tkinter.E)
            self.can.create_window(0, 0, window=self.sheet, anchor=Tkinter.NW)
            self.resizable(False, False)
            self.transient(self.parent)
            self.lift()
            self.focus()
            self.wait_visibility()
            self.grab_set()
            self.mainloop()
            self.destroy()
            return self.cells
     
        def isInputOk(self):
            for y, row in enumerate(self.cells):
                for x, cell in enumerate(row):
                    strvar = self.tkvars[y][x]
                    if type(cell) == int:
                        try:
                            tempvar = int(strvar.get())
                        except:
                            return "%s/%s is not an integer!"%(self.firstrow[x], self.firstcolumn[y])
                    elif type(cell) == float:
                        try:
                            tempvar = float(strvar.get())
                        except:
                            return "%s/%s is not a float!"%(self.firstrow[x], self.firstcolumn[y])
            return True
     
        def update(self):
            for y, row in enumerate(self.cells):
                for x, cell in enumerate(row):
                    strvar = self.tkvars[y][x]
                    if type(cell) == int:
                        self.cells[y][x] = int(strvar.get())
                    elif type(cell) == float:
                        self.cells[y][x] = float(strvar.get())
                    else:
                        self.cells[y][x] = strvar.get()
     
        def reinit(self):
            for y, row in enumerate(self.cells):
                for x, cell in enumerate(row):
                    self.tkvars[y][x].set(cell)
     
        def abort(self, event=None):
            self.quit()
     
        def accept(self):
            errmes = self.isInputOk()
            if errmes != True:
                tkMessageBox.showerror(sys.argv[0], errmes)
                return
            self.update()
            self.abort()
     
        def updateStatusbar(self, x, y):
            self.statusbar.set("%s/%s"%(self.firstrow[x], self.firstcolumn[y]))
     
        def clearStatusbar(self):
            self.statusbar.set("")
        def intToColLabel(self, value):
            rest = value % 26
            value = value/26
            var = chr(ord('A') + rest)
            while value != 0:
                rest = value % 26
                value = value/26
                var = chr(ord('A') + rest) + var
            return var
     
    if __name__ == '__main__':
     
        import sys
     
        columns, rows = 40, 50
        cells, firstcolumn, firstrow  = [], [], []
     
        def buildSheet():
            global cells, firstcolumn, firstrow
            #invoke Tkcells
            cells = askcells(cells, firstcolumn, firstrow)
            print cells
     
        # build some data
        for x in range(columns):
            firstrow.append("column #%i"%x)        
        for y in range(rows):
            firstcolumn.append("row #%i"%y)
            row = []
            for x in range(columns):
                if x == 0:
                    row.append(100 + x + y * columns)
                elif x == 1:
                    row.append("label (%u, %u)"%(x,y))
                else:
                    row.append(float(y * columns + x) * 1.1111)
            cells.append(row)
     
        root=Tkinter.Tk()
        Tkinter.Button(root, text='EDIT CELLS', width=40, height=3, command=buildSheet).grid()
        root.mainloop()
    En fait, le titre de mon topic n'est pas assez clair, je cherche à avoir une fenêtre modale (je crois que ça s'appelle comme ça, une fenetre qui bloque l'accès aux autres fenêtres de l'appli tant qu'on a pas pressé abort ou ok) où l'on peut éditer une série de paramètres.

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

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

    Informations forums :
    Inscription : Mars 2006
    Messages : 952
    Par défaut
    J'ai trouvé une solution. Mais je trouve quand même dommage de devoir additionner les largeurs et les hauteurs pour connaitre la taille d'un container. Exemple tout bête, si on veut une hauteur de 2 lignes pour la première colonne, on sabote toute la mise en page.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
     
    import Tkinter
    import tkMessageBox
     
    def askcells(cells, firstcolumn=[], firstrow=[], **kwds):
        win = Tkcells(cells, firstcolumn, firstrow, **kwds)
        return win.go()
     
    class Tkcells(Tkinter.Toplevel):
        """cells are a list of rows, rows are a list of cells, cells are integers, floats or strings, firstcolumn and firstrow are list of labels (strings)"""
        OK = 'OK'
        CANCEL = 'CANCEL'
        REINIT = 'REINIT'
        BT_WIDTH = 12
        CELL_WIDTH = 12
        WIDTH = 400
        HEIGHT= 200
        def __init__(self, cells, firstcolumn=[], firstrow=[], **kwds):
            #arguments dispatching
            can_width = Tkcells.WIDTH
            if 'width' in kwds.keys():
                can_width = kwds['width']
                kwds.pop('width')
            can_height = Tkcells.HEIGHT
            if 'height' in kwds.keys():
                can_height = kwds['height']
                kwds.pop('height')
            if 'title' in kwds.keys():
                title = kwds['title']
                kwds.pop('title')
            else:
                title = None
            if 'parent' in kwds.keys():
                self.parent = kwds['parent']
                kwds.pop('parent')
            else:
                self.parent = None
            #window creation
            Tkinter.Toplevel.__init__(self, parent=self.parent, **kwds)
            self.protocol('WM_DELETE_WINDOW', self.abort)
            if title != None:
                self.title(title)
            self.cells = cells
            self.firstcolumn = firstcolumn
            self.firstrow = firstrow 
            self.tkvars = []
            self.cellfrm = Tkinter.Frame(self, bd=0)
            self.can = Tkinter.Canvas(self.cellfrm, width=can_width, height=can_height, bd=0)
            self.vsb = Tkinter.Scrollbar(self.cellfrm, orient=Tkinter.VERTICAL)
            self.hsb = Tkinter.Scrollbar(self.cellfrm, orient=Tkinter.HORIZONTAL)
            self.sheet = Tkinter.Frame(self.can, bd=0)
            self.can.create_window(0,0, window=self.sheet)
            self.btfrm = Tkinter.Frame(self)
            self.statusbar = Tkinter.StringVar()
            Tkinter.Label(self.btfrm, textvariable=self.statusbar).grid(column=0, row=0)
            Tkinter.Button(self.btfrm, width=Tkcells.BT_WIDTH, text=Tkcells.REINIT, command=self.reinit).grid(column=1, row=0)
            Tkinter.Button(self.btfrm, width=Tkcells.BT_WIDTH, text=Tkcells.OK, command=self.accept).grid(column=2, row=0)
            Tkinter.Button(self.btfrm, width=Tkcells.BT_WIDTH, text=Tkcells.CANCEL, command=self.abort).grid(column=3, row=0)
            #cells filling
            maxcols = len(firstrow)
            if firstcolumn == []:
                for index in range(len(cells)):
                    firstcolumn.append(index+1)
                    cols = len(cells[index])
                    if cols > maxcols:
                        maxcols = cols
            labels = []
            for index, label in enumerate(firstcolumn):
                tmp_label = Tkinter.Label(self.sheet, text=label)
                tmp_label.grid(column=0, row=index+1)
                labels.append(tmp_label)
            firstwidth = max([item.winfo_reqwidth() for item in labels])
            firstheight = labels[0].winfo_reqheight()
            rowlabelheight = tmp_label.winfo_reqheight()
            if firstrow == []:
                for index in range(maxcols):
                    firstrow.append(self.intToColLabel(index))
            for index, label in enumerate(firstrow):
                tmp_label = Tkinter.Label(self.sheet, text=label)
                tmp_label.grid(column=index+1, row=0)
            for y, row in enumerate(self.cells):
                tkrow = []
                for x, column in enumerate(row):
                    cell = Tkinter.StringVar()
                    cell.set(column)
                    tkrow.append(cell)
                    entry = Tkinter.Entry(self.sheet, text=label, textvariable=cell)
                    entry.grid(column=x+1, row=y+1)
                    entry.bind("<Enter>", lambda e, x=x, y=y:self.updateStatusbar(x, y))
                    entry.bind("<Leave>", lambda e:self.clearStatusbar())
                self.tkvars.append(tkrow)
            self.bind("<Escape>", self.abort)
            #sheet size computing
            width = firstwidth + entry.winfo_reqwidth() * (maxcols)
            rowheight = max([rowlabelheight, entry.winfo_reqheight()])
            height = firstheight + rowheight * len(self.cells)
            self.can['scrollregion'] = (0, 0, width, height)
     
        def go(self):
            self.can['yscrollcommand'] = self.vsb.set
            self.can['xscrollcommand'] = self.hsb.set
            self.vsb.config(command=self.can.yview)
            self.hsb.config(command=self.can.xview)
            self.sheet.grid()
            self.can.grid(column=0, row=0, sticky=Tkinter.W)
            self.vsb.grid(column=1, row=0, sticky=Tkinter.S+Tkinter.N)
            self.hsb.grid(column=0, row=1, sticky=Tkinter.W+Tkinter.E)
            self.cellfrm.grid()
            self.btfrm.grid(sticky=Tkinter.E)
            self.can.create_window(0, 0, window=self.sheet, anchor=Tkinter.NW)
            self.resizable(False, False)
            self.transient(self.parent)
            self.lift()
            self.focus()
            self.wait_visibility()
            self.grab_set()
            self.mainloop()
            self.destroy()
            return self.cells
     
        def isInputOk(self):
            for y, row in enumerate(self.cells):
                for x, cell in enumerate(row):
                    strvar = self.tkvars[y][x]
                    if type(cell) == int:
                        try:
                            tempvar = int(strvar.get())
                        except:
                            return "%s/%s is not an integer!"%(self.firstrow[x], self.firstcolumn[y])
                    elif type(cell) == float:
                        try:
                            tempvar = float(strvar.get())
                        except:
                            return "%s/%s is not a float!"%(self.firstrow[x], self.firstcolumn[y])
            return True
     
        def update(self):
            for y, row in enumerate(self.cells):
                for x, cell in enumerate(row):
                    strvar = self.tkvars[y][x]
                    if type(cell) == int:
                        self.cells[y][x] = int(strvar.get())
                    elif type(cell) == float:
                        self.cells[y][x] = float(strvar.get())
                    else:
                        self.cells[y][x] = strvar.get()
     
        def reinit(self):
            for y, row in enumerate(self.cells):
                for x, cell in enumerate(row):
                    self.tkvars[y][x].set(cell)
     
        def abort(self, event=None):
            self.quit()
     
        def accept(self):
            errmes = self.isInputOk()
            if errmes != True:
                tkMessageBox.showerror(sys.argv[0], errmes)
                return
            self.update()
            self.abort()
     
        def updateStatusbar(self, x, y):
            self.statusbar.set("%s/%s"%(self.firstrow[x], self.firstcolumn[y]))
     
        def clearStatusbar(self):
            self.statusbar.set("")
        def intToColLabel(self, value):
            rest = value % 26
            value = value/26
            var = chr(ord('A') + rest)
            while value != 0:
                rest = value % 26
                value = value/26
                var = chr(ord('A') + rest) + var
            return var
     
    if __name__ == '__main__':
     
        import sys
     
        def buildSheet():
            global cells, firstcolumn, firstrow
            #invoke Tkcells
            rows = askcells(cells, firstcolumn, firstrow)
            for row in rows:
                print row
     
        # build some data
        cells = []
        rows = 10
        firstrow = ['serial number', 'offset', 'slope']
        columns = len(firstrow)
        firstcolumn = ["sensor[%u]"%(index+1) for index in range(rows)]
        for y in range(len(firstcolumn)):
            row = []
            for x in range(columns):
                if x == 0:
                    row.append("SN%08u"%(1515+y))
                else:
                    row.append(1.0 + float(y * rows + x) / 100.0)
            cells.append(row)
     
        root=Tkinter.Tk()
        Tkinter.Button(root, text='EDIT CELLS', width=40, height=3, command=buildSheet).grid()
        root.mainloop()

  7. #7
    Membre Expert Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    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 725
    Par défaut
    Bonjour,

    Pas le temps de regarder ton code ce matin mais je n'y manquerais pas.

    Je pense que tu n'as pas regarder mon premier lien. Ou cela ne correspond pas à ta demande ?

    Citation Envoyé par pfeuh Voir le message
    J'ai beau avoir épluché le Tkinter Reference, je n'ai pas trouvé le moyen d'avoir une largeur et une hauteur correcte pour une frame contenant des widgets. Si quelqu'un sait comment faire, je prends.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    import Tkinter
     
    def change():
        lb1['width']=lb1['width']+10
     
    def info():
        frm.update()
        print frm.winfo_reqwidth(), frm.winfo_reqheight()
     
    root=Tkinter.Tk()
    frm=Tkinter.Frame(root)
    lb1=Tkinter.Label(frm, bg='white', width=50, height=10)
    lb1.pack()
    lb2=Tkinter.Label(frm, bg='white', width=50, height=10)
    lb2.pack()
    lb3=Tkinter.Label(frm, bg='white', width=50, height=10)
    lb3.pack()
    Tkinter.Button(frm, text='Update', command=change).pack()
    Tkinter.Button(frm, text='Info', command=info).pack()
    frm.pack()
    root.mainloop()
    Bon code

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

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

    Informations forums :
    Inscription : Mars 2006
    Messages : 952
    Par défaut
    Citation Envoyé par PauseKawa Voir le message
    Je pense que tu n'as pas regarder mon premier lien. Ou cela ne correspond pas à ta demande ?
    Si, j'ai regardé, mais je n'avais tilté la première fois. Je viens de regarder ton dernier code, il me manquait le update(). Il faut apparemment faire un grid() un update() et seulement après configurer le scrollregion... Ça parait logique, mais je suis passé à côté.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
     
    import Tkinter
    import tkMessageBox
     
    def askcells(cells, firstcolumn=[], firstrow=[], **kwds):
        win = Tkcells(cells, firstcolumn, firstrow, **kwds)
        return win.go()
     
    class Tkcells(Tkinter.Toplevel):
        """cells are a list of rows, rows are a list of cells, cells are integers, floats or strings, firstcolumn and firstrow are list of labels (strings)"""
        OK = 'OK'
        CANCEL = 'CANCEL'
        REINIT = 'REINIT'
        BT_WIDTH = 6
        CELL_WIDTH = 20
        def __init__(self, cells, firstcolumn=[], firstrow=[], **kwds):
            #arguments dispatching
            can_width = None
            if 'width' in kwds.keys():
                can_width = kwds['width']
                kwds.pop('width')
            can_height = None
            if 'height' in kwds.keys():
                can_height = kwds['height']
                kwds.pop('height')
            if 'title' in kwds.keys():
                title = kwds['title']
                kwds.pop('title')
            else:
                title = None
            self.parent = None
            if 'parent' in kwds.keys():
                self.parent = kwds['parent']
                kwds.pop('parent')
            #window creation
            Tkinter.Toplevel.__init__(self, self.parent, **kwds)
            self.protocol('WM_DELETE_WINDOW', self.abort)
            if title != None:
                self.title(title)
            self.cells = cells
            self.firstcolumn = firstcolumn
            self.firstrow = firstrow
            self.tkvars = []
            self.cellfrm = Tkinter.Frame(self, bd=0)
            self.can = Tkinter.Canvas(self.cellfrm, width=can_width, height=can_height, bd=0)
            self.vsb = Tkinter.Scrollbar(self.cellfrm, orient=Tkinter.VERTICAL)
            self.hsb = Tkinter.Scrollbar(self.cellfrm, orient=Tkinter.HORIZONTAL)
            self.sheet = Tkinter.Frame(self.can, bd=0)
            self.can.create_window(0,0, window=self.sheet)
            self.btfrm = Tkinter.Frame(self)
            self.statusbar = Tkinter.StringVar()
            Tkinter.Button(self.btfrm, width=Tkcells.BT_WIDTH, text=Tkcells.REINIT, command=self.reinit).grid(column=1, row=0)
            Tkinter.Button(self.btfrm, width=Tkcells.BT_WIDTH, text=Tkcells.OK, command=self.accept).grid(column=2, row=0)
            Tkinter.Button(self.btfrm, width=Tkcells.BT_WIDTH, text=Tkcells.CANCEL, command=self.abort).grid(column=3, row=0)
            #cells filling
            maxcols = max(len(line) for line in cells )
            if firstcolumn == []:
                for index in range(len(cells)):
                    firstcolumn.append(str(index))
            for index, label in enumerate(firstcolumn):
                Tkinter.Label(self.sheet, text=label).grid(column=0, row=index+1)
            if firstrow == []:
                for index in range(maxcols):
                    firstrow.append(self.intToColLabel(index))
            for index, label in enumerate(firstrow):
                Tkinter.Label(self.sheet, text=label).grid(column=index+1, row=0)
            for y, row in enumerate(self.cells):
                tkrow = []
                for x, column in enumerate(row):
                    cell = Tkinter.StringVar()
                    cell.set(column)
                    tkrow.append(cell)
                    entry = Tkinter.Entry(self.sheet, text=label, textvariable=cell)
                    entry.grid(column=x+1, row=y+1)
                self.tkvars.append(tkrow)
            self.bind("<Escape>", self.abort)
            #sheet size computing
            self.can['yscrollcommand'] = self.vsb.set
            self.can['xscrollcommand'] = self.hsb.set
            self.vsb.config(command=self.can.yview)
            self.hsb.config(command=self.can.xview)        
            self.sheet.grid()
            self.can.grid(column=0, row=0, sticky=Tkinter.W)
            self.cellfrm.update()
            self.can['scrollregion'] = (0, 0, self.cellfrm.winfo_reqwidth(), self.cellfrm.winfo_reqheight())
            self.vsb.grid(column=1, row=0, sticky=Tkinter.S+Tkinter.N)
            self.hsb.grid(column=0, row=1, sticky=Tkinter.W+Tkinter.E)
            self.cellfrm.grid()
            self.btfrm.grid(sticky=Tkinter.E)
            self.can.create_window(0, 0, window=self.sheet, anchor=Tkinter.NW)
            self.resizable(False, False)
            self.transient(self.parent)
     
        def go(self):
            self.lift()
            self.focus()
            self.wait_visibility()
            self.grab_set()
            self.mainloop()
            self.destroy()
            return self.cells
     
        def isInputOk(self):
            for y, row in enumerate(self.cells):
                for x, cell in enumerate(row):
                    strvar = self.tkvars[y][x]
                    if type(cell) == int:
                        try:
                            tempvar = int(strvar.get())
                        except:
                            return "%s/%s is not an integer!"%(self.firstrow[x], self.firstcolumn[y])
                    elif type(cell) == float:
                        try:
                            tempvar = float(strvar.get())
                        except:
                            return "%s/%s is not a float!"%(self.firstrow[x], self.firstcolumn[y])
            return True
     
        def update(self):
            for y, row in enumerate(self.cells):
                for x, cell in enumerate(row):
                    strvar = self.tkvars[y][x]
                    if type(cell) == int:
                        self.cells[y][x] = int(strvar.get())
                    elif type(cell) == float:
                        self.cells[y][x] = float(strvar.get())
                    else:
                        self.cells[y][x] = strvar.get()
     
        def reinit(self):
            for y, row in enumerate(self.cells):
                for x, cell in enumerate(row):
                    self.tkvars[y][x].set(cell)
     
        def abort(self, event=None):
            self.quit()
     
        def accept(self):
            errmes = self.isInputOk()
            if errmes != True:
                tkMessageBox.showerror(sys.argv[0], errmes)
                return
            self.update()
            self.abort()
     
        def intToColLabel(self, value):
            rest = value % 26
            value = value/26
            var = chr(ord('A') + rest)
            while value != 0:
                rest = value % 26
                value = value/26
                var = chr(ord('A') + rest) + var
            return var
     
    if __name__ == '__main__':
     
        import sys
     
        def buildSheet():
            global cells, firstcolumn, firstrow
            #invoke Tkcells
            rows = askcells(cells, firstcolumn, firstrow, title='batch configuration', height=100, width=600, parent=root)
     
        # build some data
        cells = []
        rows = 10
        firstrow = ['serial number', 'offset', 'slope', 'window width', 'temperature']
        columns = len(firstrow)
        firstcolumn = ["sensor[%u]"%(index+1) for index in range(rows)]
        for y in range(len(firstcolumn)):
            row = []
            for x in range(columns):
                if x == 0:
                    row.append("SN%08u"%(1515+y))
                else:
                    row.append(1.0 + float(y * rows + x) / 100.0)
            cells.append(row)
     
        root=Tkinter.Tk()
        Tkinter.Button(root, text='EDIT CELLS', width=40, height=3, command=buildSheet).grid()
        root.mainloop()
    Il me reste un petit problème. Quand on rentre une mauvaise donnée dans une cellule (des lettres de l'alphabet dans une cellule pour float par exemple), Un boite de message apparait avec l'intitulé de l'erreur. Quand on accuse cette erreur, la boite disparait et le focus est donné non pas a la feuille de cellules mais à la fenêtre mère.

  9. #9
    Membre Expert Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    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 725
    Par défaut
    Bonjour,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    def showerror(title=None, message=None, **options):
    Donc
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    tkMessageBox.showerror(sys.argv[0], errmes, parent=self)
    Bon code

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

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

    Informations forums :
    Inscription : Mars 2006
    Messages : 952
    Par défaut
    Euh... j'ai le droit d'avoir honte? Merci!

    A+

    Pfeuh

  11. #11
    Membre très actif
    Avatar de afranck64
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2009
    Messages
    592
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : Cameroun

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2009
    Messages : 592
    Par défaut
    Bonjour,

    Pour le problème de focus, ta fonction isInputOk pourrait renvoyer 2 éléments (True,None) lorsqu'il n'y a pas de problème et (errmes,cell) lorsqu'une cellule ne convient ainsi après l'affichage de la boite de dialogue tu auras juste à faire cell.focus_set() pour donner le focus à la cellule en question (ou même la mettre en rouge quelques ms)...

    @+ que le Python soit avec toi
    Win 10 64 bits / Linux Mint 18, - AMD A6 Quad: Py27 / Py35
    CONTENU D'UNE QUESTION
    Exemples:
    - Configuration (système d'exploitation, version de Python et des bibliothèques utilisées)
    - Code source du morceau de programme où il y a un bogue
    - Ligne de code sur laquelle le bogue apparaît
    - Erreur complète retournée pas l'interpréteur Python
    - Recherche déjà effectuée (FAQ, Tutoriels, ...)
    - Tests déjà effectués

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 1
    Dernier message: 23/04/2007, 21h05
  2. Réponses: 5
    Dernier message: 23/11/2006, 15h52
  3. [A2003] - Ouverture de feuille de calcul .ods
    Par DeFCrew dans le forum Access
    Réponses: 9
    Dernier message: 13/09/2006, 11h23
  4. [VBa-E] Feuille de calcul excel Invisible?
    Par gootsu dans le forum Macros et VBA Excel
    Réponses: 6
    Dernier message: 16/06/2006, 11h35
  5. [VBA-E]Supprimer macro (code dans code feuille de calcul)
    Par Elstak dans le forum Macros et VBA Excel
    Réponses: 4
    Dernier message: 07/04/2006, 16h37

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo