Tkinter - ScrolledCanvas - Les objets dépassents du Canevas

Résolu
Chris3392 Messages postés 2 Date d'inscription jeudi 4 août 2011 Statut Membre Dernière intervention 12 août 2011 - 12 août 2011 à 16:24
fireman0865 Messages postés 6 Date d'inscription jeudi 1 septembre 2011 Statut Membre Dernière intervention 7 octobre 2011 - 7 oct. 2011 à 21:01
Bonjour,

Je suis en train de coder une console qui surveille des abus d'utilisation d'armes sur des jeux en réseau (FPS). A cet effet j'ai codé un ScrolledCanvas qui doit accueillir plusieurs objets (contrôles d'utilisation abusive d'armes). Chacun de ces objets est un objet composite dont les éléments sont réunis par un Frame.

Le problème est que quand je fais un scroll, les objets composites dépassent du canevas (parfois en haut, parfois en bas)

Voici la partie du code qui pose problème :

##############################################################################
# Objets d'interface graphique spécifiques à la gestion des armes

class ScrolledCanvas(Frame):
    def __init__(self, boss, width=100, height=100, bg=None, bd=2, scrollregion=(0, 0, 300, 300), relief=SUNKEN):
        Frame.__init__(self, boss, bd=bd, relief =relief)
        self.can = Canvas(self, width=width-20, height=height-20, bg=bg, scrollregion=scrollregion, bd=1)
        self.can.grid(row=0, column=0)
        scrolv = Scrollbar(self, orient=VERTICAL, command=self.can.yview, bd=1)
        scrolh = Scrollbar(self, orient=HORIZONTAL, command=self.can.xview, bd=1)
        self.can.configure (xscrollcommand=scrolh.set, yscrollcommand=scrolv.set)
        scrolv.grid(row=0, column=1, sticky=NS)
        scrolh.grid(row=1, column=0, sticky=EW)

class ControleArme(Frame):
    """Ligne de contrôle de limitation d'armes"""
    def __init__(self, boss =None, objArme=None, strArme=None):
        Frame.__init__(self, bd =2)
        #Variables de l'objet
        self.objArme = objArme
        self.nomArme = strArme
        self.intSeuil = int(self.objArme.Liste[strArme][0])
        self.CtrleArme = Frame()
        #Instanciation des objets du contrôle
        self.lblClasse = Label(self.CtrleArme, text=self.objArme.Liste[strArme][1], width=7, anchor=W)
        self.lblNature = Label(self.CtrleArme, text=self.objArme.Liste[strArme][2], width=7, anchor=W)
        self.lblArme = Label(self.CtrleArme, text=strArme, width=20, anchor=W)
        self.entSeuil = Entry(self.CtrleArme, width=4)
        self.entSeuil.delete (0, END)
        self.entSeuil.insert(END, self.objArme.Liste[strArme][0])
        self.butAppliquer = Button(self.CtrleArme, text='Appliquer',command=self.ActualiserListeArmes)
        #Mise en place des objets
        self.lblClasse.pack(side=LEFT, anchor=N, padx=1, pady=1)
        self.lblNature.pack(side=LEFT, anchor=N, padx=1, pady=1)
        self.lblArme.pack(side=LEFT, anchor=N, padx=1, pady=1)
        self.entSeuil.pack(side=LEFT, anchor=N, padx=1, pady=1)
        self.butAppliquer.pack(side=LEFT, anchor=N, padx=1, pady=1)
        
    def ActualiserListeArmes(self):
        self.intSeuil = int(self.entSeuil.get())
        self.objArme.ModifierSeuil(self, self.nomArme, self.intSeuil)
        
class ControlesArmes(Frame):
    """Bloc de contrôle des limitations d'armes"""
    def __init__(self, boss=None, objArme=None, width=400, height=300):
        Frame.__init__(self, bd =2, relief =SUNKEN)
        #Reclassement du dictionnaire des armes par numéro d'ordre
        intCompteur = 0
        ListeArmes ={}
        print('Tri de la liste des armes avant mise en place des controles')
        for strArme in objArme.Liste.keys():
            ListeArmes [objArme.Liste[strArme][3]] = (strArme, objArme.Liste[strArme][0], objArme.Liste[strArme][1], objArme.Liste[strArme][2])
            intCompteur += 1
            print (str(objArme.Liste[strArme][3]) + ':' + strArme + ':' + str(objArme.Liste[strArme][0]) + ':' + objArme.Liste[strArme][1] + ':' + objArme.Liste[strArme][2])

        #Instanciation d'un bloc et d'un ascenseur en vue d'y stocker les objets de contrôle d'arme
        ligne = 0
        hauteur = 30
        CadreLC = ScrolledCanvas(self, width=400, height=300, relief=SOLID, scrollregion=(0, 0, 400, (hauteur * intCompteur)))
        CadreLC.pack(expand=NO, fill=BOTH, padx=6, pady=6)
               
        #Instanciation des controles du bloc
        Ctrle = {} #Reset du dictionnaire regroupant les définitions d'objet
        self.CtrleCadre = {}
        for intOrdre in ListeArmes.keys(): #Remplissage du dictionnaire avec les objets + instanciation de ces derniers
            Ctrle [ListeArmes[intOrdre][0]] = ControleArme(CadreLC.can, objArme, ListeArmes[intOrdre][0])
            self.CtrleCadre [ListeArmes[intOrdre][0]] = CadreLC.can.create_window(0, ligne, anchor=NW, window=Ctrle[ListeArmes[intOrdre][0]].CtrleArme)
            ligne += hauteur


Cette section de code est appelée dans une fenêtre principale :
class Application(Frame):
    """Application principale"""
    def __init__(self, boss =None):
        Frame.__init__(self)
        #Chargement des données de limitation d'armes
        self.objArmes = ListeArmes(self)
        self.ChargerArmes()
        print('Verification du chargement des armes')
        for strArme in self.objArmes.Liste.keys():
            print(strArme + ',' + str(self.objArmes.Liste[strArme][0]) + ',' + self.objArmes.Liste[strArme][1]  + ',' + self.objArmes.Liste[strArme][2])
        #Initialisation de la fenêtre de l'application principale
        self.master.title("""Limiteur d'armes - v 1.0""")
        self.mBar = MenuBar(self)
        self.mBar.grid(row=0, column=0, columnspan=2, sticky=W, padx=8, pady=8)
        self.frmArmes = ControlesArmes(self, self.objArmes)
        self.frmArmes.grid (row=1, column=0, sticky=W, padx=8, pady=8)
        #self.frmJoueurs = ControlesJoueurs(self)               #A coder
        #self.frmJoueurs.grid (row=1, column=1, sticky=W)       #A coder
        self.st =ScrolledText(self, baseFont="System 8 normal", width =100, height =5)
        self.st.grid(row=2, column=0, columnspan=2, sticky=W, padx =8, pady =8)


D'avance je remercie quiconque qui aurait une solution à cette question.

Chris

2 réponses

Chris3392 Messages postés 2 Date d'inscription jeudi 4 août 2011 Statut Membre Dernière intervention 12 août 2011
12 août 2011 à 22:42
J'ai finalement trouvé la réponse à mon problème (un peu par hasard!). Peut-être mon analyse est-elle inexacte, dans ce cas j'espère que les modérateurs voudront bien m'en excuser ; toutefois, si quelqu'un rencontre le même problème, voici ma compréhension de celui-ci :

En fait la frame qui regroupe les objets composites doit être un objet esclave du canvas. Il faut donc rajouter le mot boss lors de son instanciation. En outre, j'ai pu lire qu'il est déconseillé de mélanger des méthodes pack() et grid(), j'ai donc remplacé chaque méthode pack() par une méthode grid(). Avec ces deux opérations, celà fonctionne.


Voici par ailleurs la partie de code modifiée :
[quote=Code Python]
class ControleArme(Frame):
"""Ligne de contrôle de limitation d'armes"""
def __init__(self, boss =None, objArme=None, strArme=None):
Frame.__init__(self, bd =2)
#Variables de l'objet
self.objArme = objArme
self.nomArme = strArme
self.intSeuil = int(self.objArme.Liste[strArme][0])
self.CtrleArme = Frame(boss)
#Instanciation des objets du contrôle
self.lblClasse = Label(self.CtrleArme, text=self.objArme.Liste[strArme][1], width=7, anchor=W)
self.lblNature = Label(self.CtrleArme, text=self.objArme.Liste[strArme][2], width=7, anchor=W)
self.lblArme = Label(self.CtrleArme, text=strArme, width=20, anchor=W)
self.entSeuil = Entry(self.CtrleArme, width=4)
self.entSeuil.delete (0, END)
self.entSeuil.insert(END, self.objArme.Liste[strArme][0])
self.butAppliquer = Button(self.CtrleArme, text='Appliquer',command=self.ActualiserListeArmes)
#Mise en place des objets
self.lblClasse.grid(row=0, column=0, padx=1, pady=1)
self.lblNature.grid(row=0, column=1, padx=1, pady=1)
self.lblArme.grid(row=0, column=2, padx=1, pady=1)
self.entSeuil.grid(row=0, column=3, padx=1, pady=1)
self.butAppliquer.grid(row=0, column=4, padx=1, pady=1)

def ActualiserListeArmes(self):
self.intSeuil = int(self.entSeuil.get())
self.objArme.ModifierSeuil(self, self.nomArme, self.intSeuil)/quote
3
fireman0865 Messages postés 6 Date d'inscription jeudi 1 septembre 2011 Statut Membre Dernière intervention 7 octobre 2011
7 oct. 2011 à 21:01
salut,surveille bien tes premieres lignes de codes:scrolv.grid(row=0, column=1, sticky=NS)
scrolh.grid(row=1, column=0, sticky=EW)
0
Rejoignez-nous