ekdmekdm
ekdmekdm

Reputation: 167

Add a QSrollArea on a group of widgets

I am coding an interface with stackedwidgets and QGridLayout in which are some widgets which for some are added on the fly ... I'd like to add a QSrolledArea for each group of widgets (see the screenshot attached showing one of the groups of widgets that can be added on the fly) but I don't know how, can you help me ?

...

def ajouter_ref_artistique(self) :
    '''
    '''
    #
    r = len(self.liste_ref_artistiques)
    #if r >= 0 : self.label_annonce_vocab.hide()
    # Création des QTextEdit
    self.dico_chem_ref_art[r] = QTextEdit()
    self.dico_com_ref_art[r] = QTextEdit()
    self.dico_chem_ref_art[r].setMaximumWidth(170)
    self.dico_chem_ref_art[r].setMinimumWidth(170)
    self.dico_chem_ref_art[r].setMaximumHeight(84)
    self.dico_chem_ref_art[r].setMinimumHeight(84)
    self.dico_com_ref_art[r].setMaximumWidth(398)
    self.dico_com_ref_art[r].setMinimumWidth(398)
    self.dico_com_ref_art[r].setMaximumHeight(84)
    self.dico_com_ref_art[r].setMinimumHeight(84)
    # Création des boutons de chargement
    self.dico_bout_charg_ref_art[r] = QPushButton(u"Ouvrir ref {}".format(r+1))
    '''
    # Conditions de redimensionnement
    if r > 5 :
        self.dico_vocab_mot[r].setMaximumHeight(34)
        self.dico_vocab_mot[r].setMinimumHeight(34)
        self.dico_vocab_def[r].setMaximumHeight(34)
        self.dico_vocab_def[r].setMinimumHeight(34)
    '''
    # Répartition dans la grille
    self.grille_3_stack_5.addWidget(self.dico_chem_ref_art[r], r, 0)
    self.grille_3_stack_5.addWidget(self.dico_com_ref_art[r], r, 1)
    self.grille_3_stack_5.addWidget(self.dico_bout_charg_ref_art[r], r, 2)
    # Ecriture des n°s de lignes dans la partie mots de vocabulaire
    self.dico_chem_ref_art[r].setText(str(r+1)+'. ')
    # Les données sont introduites dans une liste
    self.liste_ref_artistiques.append([self.dico_chem_ref_art[r], self.dico_com_ref_art[r], self.dico_bout_charg_ref_art[r]])
    # =====================================================
    # Signaux
    # ---------- Récup des données textuelles
    self.dico_chem_ref_art[r].textChanged.connect(self.changements_phase_5)
    self.dico_com_ref_art[r].textChanged.connect(self.changements_phase_5)
    # ---------- Récup du libellé du bouton sélectionné par l'utilisateur
    self.dico_bout_charg_ref_art[r].released.connect(self.libelle_bouton_ref_art)
    # =====================================================

def supprimer_ref_artistique(self) :
    '''
    '''
    row = len(self.liste_ref_artistiques) - 1
    if row >= 0:
        for column in range(self.grille_3_stack_5.columnCount()):
            item = self.grille_3_stack_5.itemAtPosition(row, column)
            if item is not None:
                item.widget().deleteLater()
        del self.liste_ref_artistiques[row]
        del self.dico_chem_ref_art[row]
        del self.dico_com_ref_art[row] 
        del self.dico_bout_charg_ref_art[row]

def changements_phase_5(self) :
    """
    """
    self.liste_ref_artistiques_finale = [[unicode(refart[0].toPlainText()), unicode(refart[1].toPlainText()), unicode(refart[2])] for refart in self.liste_ref_artistiques]

    print
    print "self.liste_ref_artistiques_finale :"
    print
    print self.liste_ref_artistiques_finale
    print

def libelle_bouton_ref_art(self) :
    '''
    Sélectionner l'id du bouton pressé en vue de 
    l'affichage du chemin de l'image sélectionnée
    dans le QTextEdit dédié
    '''

    #
    message_bouton_ref_art = self.sender()

    # Le texte du bouton (par ex pour le bouton n°2) est 
    # de la forme : Ouvrir ref 2
    texte_bouton = message_bouton_ref_art.text()

    # On ne sélectionne que le texte comprenant le numéro
    # du bouton
    numero_bouton = texte_bouton.right(2) # Lecture à partir de la droite

    # Si il y a un espace ds la sélection, c'est à dire, 
    # par exemple, pour le 3ème bouton on obtiendra " 3", 
    # ... si il y 10 boutons, on aura "10" (on se laisse 
    # la possibilité de pouvoir sélectionner de 1 à 99 
    # boutons)
    if numero_bouton[0:1] == " ": numero_bouton = numero_bouton[1:2]

    # Le numéro du bouton prend le type integer
    numero_bouton = int(numero_bouton)

    # Attribution de l'indice du bouton
    i = numero_bouton - 1

    # =====================================================
    # Signal
    # ---------- Affichage des images/vignettes et chemins images
    self.dico_bout_charg_ref_art[i].clicked.connect(lambda: self.ouvrir_image_boite_ref_art(i))
    # =====================================================

def ouvrir_image_boite_ref_art(self, n) :
    ''' Fonction pour la boîte de dialogue d'ouverture 
    pour charger les différentes oeuvres (références artistiques) '''

    # La boîte
    ouv_fichier = QFileDialog.getOpenFileName(self, 'Ouvrir une image', os.path.expanduser('~'), 'Images (*.jpg *.jpeg *.JPG *.JPEG *.png *.gif)')

    # Récup du chemin et nom de fichier
    chemin_fichier_ref_art = unicode(ouv_fichier)

    # === Redimensionnnement de l'image pour affichage dans le QTextEdit ======
    # Largeur de la future vignette
    nouv_w_1 = 120
    # Ouverture de l'image  
    obImg_1 = Image.open(chemin_fichier_ref_art)
    # Recup dimensions de l'image 1)
    w_1, h_1 = obImg_1.size
    # Calcul du ratio de l'image 1)
    ratio_1 = float(w_1)/float(h_1)
    # Calcul de future hauteur avec les dimensions donnees par l'utilisateur
    calcHauteur_img_1 = int(float(nouv_w_1)/ratio_1)
    # =========================================================================

    # Affichage de l'image dans le QTextEdit
    self.dico_chem_ref_art[n].setHtml('<center><img src="{}" width="{}" height="{}" title="{}" /></center><h6><b>{}</b></h6>'.format(chemin_fichier_ref_art, nouv_w_1, calcHauteur_img_1, chemin_fichier_ref_art, chemin_fichier_ref_art))

    # La liste finale des données est réactualisée avec les
    # nouvelles données (le chemin et nom de l'image chargée) 
    del self.liste_ref_artistiques_finale[n][0]
    self.liste_ref_artistiques_finale[n].insert(0, chemin_fichier_ref_art)

The entire code is here:

https://pastebin.com/igVv6dcw

The screenshot attached

Upvotes: 0

Views: 69

Answers (1)

eyllanesc
eyllanesc

Reputation: 243907

What you have to do is place the QGridLayout inside a QWidget, and this one inside QScrollArea, then this scrollarea inside another layout, and finally place this layout inside the QGroupBox:

def stack_phase_5(self) :
    [...]
    self.grille_2_stack_5.setSpacing(174)

    """
    Changes
    """
    scrollArea = QScrollArea(self)
    scrollArea.setWidgetResizable(True)

    wid = QWidget(self)
    scrollArea.setWidget(wid)
    self.grille_3_stack_5 = QGridLayout(wid)
    self.grille_3_stack_5.setSpacing(0)
    [...]
    groupe_2.setLayout(self.grille_2_stack_5)

    # changes
    groupe_3.setLayout(QVBoxLayout())
    groupe_3.layout().addWidget(scrollArea)

    layout = QGridLayout()
    [...]

Note: I recommend separating your code into several widgets and these are several files so you can debug your code better.

You can download the complete code from the following link.

enter image description here

Upvotes: 1

Related Questions