1

I am adding rows of widgets to a QGridLayout like this (with a button):

def ajouter_un_mot_vocab(self) :
    '''
    '''

    # Dictionnaire des mots de vocabulaire    
    self.dico_vocab_mot = {}
    # Dictionnaire des définitions des mots de vocabulaire
    self.dico_vocab_def = {}

    # Liste pour chargement des données 
    # (écriture des textes par l'utilisateur)
    self.liste_mots_vocabulaire = []

    print
    print 'self.grille_3_stack_3.rowCount() creation', self.grille_3_stack_3.rowCount()
    print 

    #
    for r in range(self.grille_3_stack_3.rowCount()) :
        # Création des widgets et taille générique
        self.dico_vocab_mot[r] = QTextEdit()
        self.dico_vocab_def[r] = QTextEdit()
        self.dico_vocab_mot[r].setMaximumWidth(180)
        self.dico_vocab_mot[r].setMinimumWidth(180)
        self.dico_vocab_mot[r].setMaximumHeight(54)
        self.dico_vocab_mot[r].setMinimumHeight(54)
        self.dico_vocab_def[r].setMaximumHeight(54)
        self.dico_vocab_def[r].setMinimumHeight(54)
        print 'r', r
        # 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_3.addWidget(self.dico_vocab_mot[r], r+1, 0)
        self.grille_3_stack_3.addWidget(self.dico_vocab_def[r], r+1, 1)
        # Ecriture des n°s de lignes dans la partie mots de vocabulaire
        self.grille_3_stack_3.addWidget(self.dico_vocab_mot[r].setText(str(r+1)+'. '), r+1, 0)
        # Les données sont introduites dans une liste
        self.liste_mots_vocabulaire.append([self.dico_vocab_mot[r], self.dico_vocab_def[r]])
        # =====================================================
        # Signaux
        self.dico_vocab_mot[r].textChanged.connect(self.changements_phase_3)
        self.dico_vocab_def[r].textChanged.connect(self.changements_phase_3)
        # =====================================================

        print 'self.dico_vocab_mot', self.dico_vocab_mot
        print 'self.dico_vocab_def', self.dico_vocab_def

    print self.liste_mots_vocabulaire

And removing the rows of widgets like this:

def supprimer_un_mot_vocab(self) :
    '''
    '''
    index = len(self.liste_mots_vocabulaire)-1
    for r in reversed(range(self.grille_3_stack_3.rowCount())) :
        for c in reversed(range(self.grille_3_stack_3.columnCount())) 
            layout = self.grille_3_stack_3.itemAtPosition(r, c)
            if layout is not None :
                layout.widget().deleteLater()
                #layout_1.widget().hide()
                self.grille_3_stack_3.removeItem(layout)

    self.liste_mots_vocabulaire.pop() 
    del self.dico_vocab_mot[index] 
    del self.dico_vocab_def[index] 

    print
    print "rowCount apres suppr", self.grille_3_stack_3.rowCount()

    print
    print self.dico_vocab_mot
    print self.dico_vocab_def
    print self.liste_mots_vocabulaire
    print

Everything works well the first time, when I add rows of widgets (for example five rows of widgets). Everything works well too if I delete the rows (for example two rows of widgets). But as soon as I decide to add a row again (after deletion), it does not work properly: I end up with six lines, while I should have three.

It must be my code for deleting lines that does not work properly (yet the rows are removed visually). What am I doing wrong?

ekhumoro
  • 115,249
  • 20
  • 229
  • 336
ekdmekdm
  • 171
  • 1
  • 9
  • If you want us to help you, you must provide a [Minimal, Complete, and Verifiable example](https://stackoverflow.com/help/mcve), that is to say that it can be reproduced but yours needs more code to execute it, personally I am lazy to complete your code – eyllanesc Nov 19 '17 at 18:58
  • Hello eyllanesc, sorry, I'm trying to send a more complete answer very soon. This is my very first message here (I would like to post the complete code which is 689 lines, but in the code tags, ... not so good ...). – ekdmekdm Nov 19 '17 at 19:05
  • You must provide a **Minimal**, Complete, and **Verifiable** example. If your code is very long then create another project with only the functionality that generates the error. – eyllanesc Nov 19 '17 at 19:09

1 Answers1

0

A QGridLayout does not delete any rows when its widgets are removed - but the empty rows do not take up any space, so you won't usually notice them. If you add widgets beyond the current row-count, the layout will simply grow to the required size. So if the current row-count is 5, and you add a widget at row 10, the row-count will immediately change to 10, and five empty intervening rows will be created.

A grid-layout always starts with a row-count of one. But in your code, you use r + 1 when adding widgets:

for r in range(self.grille_3_stack_3.rowCount()):
    ...
    self.grille_3_stack_3.addWidget(self.dico_vocab_mot[r], r+1, 0)
    self.grille_3_stack_3.addWidget(self.dico_vocab_def[r], r+1, 1)
    # Ecriture des n°s de lignes dans la partie mots de vocabulaire
    self.grille_3_stack_3.addWidget(self.dico_vocab_mot[r].setText(str(r+1)+'. '), r+1, 0)

This will skip the first row, and start adding widgets a row index 1. So after adding five rows of widgets, the row-count will be six, rather than five. And every time you delete and re-add the widgets, the row-count will grow by one.

Your code should instead look like this:

for r in range(self.grille_3_stack_3.rowCount()):
    ...
    self.grille_3_stack_3.addWidget(self.dico_vocab_mot[r], r, 0)
    self.grille_3_stack_3.addWidget(self.dico_vocab_def[r], r, 1)
    self.dico_vocab_mot[r].setText(str(r+1)+'. ')

(Note that I have also fixed the last line here, which previously made no sense).

EDIT:

As per the comments, here are the changes needed so that one row is added for each click of the first button, and all rows are cleared when clicking the second button.

class EssaiQStackedWidget_Seq_Prof(QWidget) :
    def __init__(self, parent=None):
        ...
        self.dico_vocab_mot = {}
        self.dico_vocab_def = {}    
        self.liste_mots_vocabulaire = []

        self.liste_menu.currentIndexChanged.connect(self.affiche_phases)

    def ajouter_un_mot_vocab(self) :
        r = len(self.liste_mots_vocabulaire)
        self.dico_vocab_mot[r] = QTextEdit()
        self.dico_vocab_def[r] = QTextEdit()
        self.dico_vocab_mot[r].setMaximumWidth(180)
        self.dico_vocab_mot[r].setMinimumWidth(180)
        self.dico_vocab_mot[r].setMaximumHeight(54)
        self.dico_vocab_mot[r].setMinimumHeight(54)
        self.dico_vocab_def[r].setMaximumHeight(54)
        self.dico_vocab_def[r].setMinimumHeight(54)
        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)
        self.grille_3_stack_3.addWidget(self.dico_vocab_mot[r], r, 0)
        self.grille_3_stack_3.addWidget(self.dico_vocab_def[r], r, 1)
        self.dico_vocab_mot[r].setText(str(r+1)+'. ')
        self.liste_mots_vocabulaire.append([self.dico_vocab_mot[r], self.dico_vocab_def[r]])
        self.dico_vocab_mot[r].textChanged.connect(self.changements_phase_3)
        self.dico_vocab_def[r].textChanged.connect(self.changements_phase_3)

    def supprimer_un_mot_vocab(self) :
        row = len(self.liste_mots_vocabulaire) - 1
        if row >= 0:
            for column in range(self.grille_3_stack_3.columnCount()):
                item = self.grille_3_stack_3.itemAtPosition(row, column)
                if item is not None:
                    item.widget().deleteLater()
            del self.liste_mots_vocabulaire[row]
            del self.dico_vocab_mot[row]
            del self.dico_vocab_def[row]
ekhumoro
  • 115,249
  • 20
  • 229
  • 336
  • Thank you for the answer ekhumoro but if I replace by this code there is only one line that is created ... each time the button is pressed, only line 1 is created. – ekdmekdm Nov 19 '17 at 21:49
  • ekhumoro you can view the entire code here : https://pastebin.com/EqsTVgrs – ekdmekdm Nov 19 '17 at 22:53
  • @ekdmekdm. Why do you expect that code to create more than one row? Where are the other rows supposed to come from? – ekhumoro Nov 19 '17 at 23:08
  • I'm sorry, I'm certainly doing very badly (and maybe I'm confused in my explanations) ... actually I want every time the button is pressed ... an extra line is added. – ekdmekdm Nov 19 '17 at 23:16
  • @ekdmekdm. So in fact you don't want a loop in `ajouter_un_mot_vocab`, and you don't want to keep resetting `dico_vocab_mot` etc to an empty `dict` each time. – ekhumoro Nov 19 '17 at 23:23
  • Yes. When the user presses the button (Add vocabulary line) the first time, a QTextEdit will be added in 0, 0, another in 0, 1, ... when the user presses a second time on the button a QTextEdit will be added in 1, 0, another in 1, 1, ... so on every time the user presses the button a new line of QTextEdit will be added ... Yes I don't want to keep resetting dico_vocab_mot (and also dico_vocab_def). In fact a vocabulary line includes two QTextEdit (one for the vocabulary word itself and the other for the vocabulary word definition). – ekdmekdm Nov 19 '17 at 23:46
  • ekhumoro, I'm going to bed, here in France it's late, and I get up early tomorrow (where are you from?). I will test your code tomorrow. (-> where is the tick symbol?). If you agree, I'll let you know if it works for me. – ekdmekdm Nov 20 '17 at 00:00
  • Hi ekhumoro, I just tried your code, the creation of the lines works fine but at the time of delete each line (one after the other and not all at the same time) and well the button "Delete a line of vocabulary " removes all the lines of a shot. What I would like is that every time you press this button it is the last line of widgets that is deleted. – ekdmekdm Nov 20 '17 at 17:58
  • Wow !, your later code work perfectly !!! Thanks a lot ekhumoro ! I sometimes consulted stackoverflow, but I admit that it's really great here. If I can help one of these days ... – ekdmekdm Nov 20 '17 at 18:52