70 votes

Qt - supprimer tous les widgets de la mise en page?

Cela ne semble pas facile. Fondamentalement, j'ajoute QPushButtons par le biais d'une fonction à une présentation, et lorsque la fonction s'exécute, je souhaite d'abord effacer la présentation (en supprimant tous les QPushButtons et tout le reste), car plusieurs boutons sont simplement ajoutés au défilement.

entête

 QVBoxLayout* _layout;
 

cpp

 void MainWindow::removeButtonsThenAddMore(const QString &item) {

//remove buttons/widgets

QVBoxLayout* _layout = new QVBoxLayout(this);

QPushButton button = new QPushButton(item);
_layout->addWidget(button);

QPushButton button = new QPushButton("button");
_layout->addWidget(button);

QWidget* widget = new QWidget();
widget->setLayout(_layout);

QScrollArea* scroll = new QScrollArea();
scroll->setWidget(widget);
scroll->show();

}
 

55voto

Teemu Leisti Points 2606

J'ai eu le même problème: j'ai un jeu app dont la principale fenêtre de la classe hérite de QMainWindow. Son constructeur semble en partie comme ceci:

m_scene = new QGraphicsScene;
m_scene->setBackgroundBrush( Qt::black );
...
m_view = new QGraphicsView( m_scene );
...
setCentralWidget( m_view );

Lorsque je veux afficher un niveau de jeu, j'instancie un QGridLayout, dans laquelle j'ai ajouté QLabels, et définissez leurs images de certaines images (images avec des parties transparentes). Le premier niveau s'affiche bien, mais lors du passage au deuxième niveau, les images à partir du premier niveau pourrait encore être vu derrière nouvelles (où le pixmap a été transparent).

J'ai essayé plusieurs choses pour supprimer l'ancienne widgets. (a) j'ai essayé de supprimer le QGridLayout et l'instanciation d'une nouvelle, mais alors appris que la suppression d'une disposition ne permet pas de supprimer les widgets ajoutés. (b) j'ai essayé d'appeler QLabel::clear() sur les nouvelles images, mais qui bien sûr n'ont qu'un effet sur les nouveaux, pas le zombie ceux. (c) j'ai même essayé de la suppression de mon m_view et m_scene, et de les reconstruire à chaque fois que j'affiche un nouveau niveau, mais toujours pas de chance.

Puis (d) j'ai essayé l'une des solutions proposées ci-dessus, à savoir

QLayoutItem *wItem;
while (wItem = widget->layout()->takeAt(0) != 0)
    delete wItem;

mais cela ne fonctionne pas, soit.

Toutefois, google plus, j'ai trouvé une réponse qui a travaillé. Ce qui manquait à partir de (d) est un appel à l' delete item->widget(). La suite maintenant fonctionne pour moi:

// THIS IS THE SOLUTION!
// Delete all existing widgets, if any.
if ( m_view->layout() != NULL )
{
    QLayoutItem* item;
    while ( ( item = m_view->layout()->takeAt( 0 ) ) != NULL )
    {
        delete item->widget();
        delete item;
    }
    delete m_view->layout();
}

et puis j'instancie un nouveau QGridLayout comme avec le premier niveau, ajouter un nouveau niveau de widgets, etc.

Qt est grande dans beaucoup de façons, mais je ne pense que c'problèmes montre que les choses pourraient être un peu plus facile ici.

50voto

Darko Maksimovic Points 194

"Mise en page" gestion de la page dans Qt aider les états à:

La mise en page sera automatiquement reparent les widgets (à l'aide de QWidget::setParent ()), de sorte qu'ils sont les enfants de la widget sur lequel la mise en page est installé. Ma conclusion: les Widgets doivent être détruits manuellement ou en détruisant le parent du WIDGET, pas de mise en page

Les Widgets dans une mise en page sont des enfants de la widget sur lequel le la mise en page est installé, pas de la mise en page elle-même. Les Widgets peuvent avoir seulement d'autres widgets en tant que parent, pas de mises en page. Ma conclusion: Même que ci-dessus

À @Muelner de "contradiction", "La propriété de l'élément est transféré à la mise en page, et c'est la mise en page de la responsabilité pour le supprimer." - cela ne veut pas dire WIDGET, mais l'ARTICLE qui est nouveau apparenté à la mise en page et sera supprimé plus tard par la mise en page. Les Widgets sont encore des enfants du widget de la mise en page est installé, et ils doivent être retirés soit manuellement, soit par la suppression de l'ensemble du widget parent.

Si l'on a vraiment besoin de supprimer tous les widgets et les éléments de mise en page, la laissant complètement vide, il a besoin de faire un appel récursif à la fonction comme ceci: // faiblement testé, semble fonctionner, mais appliquer la logique

void clearLayout(QLayout* layout, bool deleteWidgets = true)
{
    while (QLayoutItem* item = layout->takeAt(0))
    {
        if (deleteWidgets)
        {
            if (QWidget* widget = item->widget())
                delete widget;
        }
        if (QLayout* childLayout = item->layout())
            clearLayout(childLayout, deleteWidgets);
        delete item;
    }
}

10voto

hmuelner Points 5311

Prévenus: Pourquoi ne pas créer une nouvelle mise en page, il échange avec l'ancienne mise en page et de supprimer l'ancienne mise en page? Cela devrait supprimer tous les éléments qui étaient détenues par la mise en page et de laisser les autres.

Edit: Après avoir étudié les commentaires de ma réponse, la documentation et les sources de Qt, j'ai trouvé une meilleure solution:

Si vous avez encore des Qt3 est activé, vous pouvez utiliser QLayout::deleteAllItems (), qui est essentiellement la même que l'indication dans la documentation de QLayout::takeAt:

Le fragment de code suivant montre un moyen sûr de supprimer tous les éléments d'une mise en page:

QLayoutItem *child;
while ((child = layout->takeAt(0)) != 0) {
  ...
  delete child;
}

Edit: Après de nouvelles recherches, il ressemble à la version ci-dessus sont équivalentes: seulement sublayouts et widget sans leurs parents sont supprimées. Les Widgets avec les parents sont traitées d'une manière spéciale. Il ressemble à TeL solution devrait fonctionner, vous devez être prudent de ne pas supprimer tous les widgets. Une autre solution serait d'utiliser le widget de la hiérarchie pour supprimer des widgets: Créer un widget, sans parent et de créer tous vos mobiles widgets comme enfant de ce widget. Après le nettoyage, la mise en page à supprimer ce widget spécial.

5voto

Liz Points 3835

Vous voulez également vous assurer que vous retirez des entretoises et des choses qui ne sont pas QWidgets. Si vous êtes sûr que les seules choses dans votre mise en page sont QWidgets, la réponse précédente est très bien. Sinon, vous devriez faire ceci:

QLayoutItem *wItem;
while (wItem = widget->layout()->takeAt(0) != 0)
      delete wItem;

Il est important de savoir comment le faire, parce que si la mise en page que vous souhaitez effacer est partie d'une plus grande mise en page, vous ne voulez pas détruire la mise en page. Vous voulez vous assurer que votre mise en page maintient sa place et le reste de votre fenêtre.

Vous devez aussi être prudent, vous êtes la création d'un chargement d'objets chaque fois que vous appelez cette méthode, et ils ne sont pas nettoyés. Tout d'abord, vous devriez probablement créer le QWidget et QScrollArea quelque part d'autre, et de garder une variable de membre de pointage à titre de référence. Puis votre code pourrait ressembler à quelque chose comme ceci:

QLayout *_layout = WidgetMemberVariable->layout();

// If it is the first time and the layout has not been created
if (_layout == 0)
{
  _layout = new QVBoxLayout(this);
  WidgetMemberVariable->setLayout(_layout);
}

// Delete all the existing buttons in the layout
QLayoutItem *wItem;
while (wItem = widget->layout()->takeAt(0) != 0)
    delete wItem;

//  Add your new buttons here.
QPushButton button = new QPushButton(item);
_layout->addWidget(button);

QPushButton button = new QPushButton("button");
_layout->addWidget(button);

2voto

Harald Scheirich Points 7227

Vous n'écrivez pas au sujet de la démarche inverse, mais vous pouvez également utiliser un QStackedWidget et y ajouter deux vues, une pour chaque disposition de boutons dont vous avez besoin. Basculer entre les deux n’est alors pas un problème et beaucoup moins de risque que de jongler avec différentes instances de boutons créés dynamiquement

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X