如何在 QGridLayout 中删除后添加多行小部件

How to add rows of widgets after deletion in a QGridLayout

我正在将小部件行添加到 QGridLayout,就像这样(带有按钮):

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

并像这样删除小部件行:

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

当我添加多行小部件(例如五行小部件)时,第一次一切正常。如果我删除行(例如两行小部件),一切也都很好。但是一旦我决定再次添加一行(删除后),它就无法正常工作:我最终得到了六行,而我应该有三行。

一定是我的代码删除了不能正常工作的行(但这些行在视觉上被删除了)。我做错了什么?

A QGridLayout 在删除其小部件时不会删除任何行 - 但空行不会占用任何 space,因此您通常不会注意到它们。如果您添加超出当前行数的小部件,布局将简单地增长到所需的大小。因此,如果当前行数为 5,并且您在行 10 处添加了一个小部件,行数将立即更改为 10,并且将创建五个空的中间行。

网格布局始终以行数 1 开头。但是在您的代码中,您在添加小部件时使用 r + 1

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)

这将跳过第一行,并开始向行索引 1 添加小部件。因此,添加五行小部件后,行数将为 ,而不是五行。每次您删除并重新添加小部件时,行数都会增加一个。

您的代码应该如下所示:

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)+'. ')

(注意,我在这里也修复了最后一行,之前没有意义)。

编辑:

根据评论,这里是需要进行的更改,以便每次单击第一个按钮时添加一行,并在单击第二个按钮时清除所有行。

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]