Frage

I have a WidgetA widget, which is an owner-drawn widget. It's currently placed in QMainWindow's QVBoxLayout. After clicking a button, I'd like to "detach" WidgetA from this QVBoxLayout, insert QSplitter into this QVBoxLayout and "readd" WidgetA to this QSplitter. All this without destroying WidgetA, so it will preserve its drawing context, etc.

So, currently I have this (only one widget in a window):

only one widget in a window

I'd like to put a QSplitter between WidgetA and QMainWindow, and create a new widget, WidgetB, so I'd end up with:

two widgets, split by QSplitter

Later I'd like it to split even further, so both WidgetA and WidgetB would still allow themselves to be detached and placed in a new QSplitter, so it would be possible to create f.e. this hierarchy:

three widgets, split by two QSplitters

And, to be complete, one more step:

four widgets, split by three QSplitters

I'm not very experienced in Qt, so what I'm trying to do may seem pretty obvious, but I couldn't find how to "reparent" widgets. Is this possible in Qt?

War es hilfreich?

Lösung

Please, see reparent example, may be it helps you:

//MyMainWindow.h
#include <QWidget>
#include <QPainter>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QPushButton>
#include <QSplitter>

class MyWidget: public QWidget
{
public:
  MyWidget(QWidget* parent, int number)
    : QWidget(parent),
      m_number(number)
  {

  }

private:
  virtual void paintEvent(QPaintEvent* e)
  {
    QWidget::paintEvent(e);

    QPainter p(this);
    p.fillRect( rect(), Qt::red);
    p.drawText( rect(), Qt::AlignCenter, QString::number(m_number) );
  }

private:
  int m_number;
};

class MyMainWindow: public QWidget
{
  Q_OBJECT

public:
  MyMainWindow()
  {
    setFixedSize(300, 200);

    m_mainLayout = new QVBoxLayout(this);
    QHBoxLayout* buttonLayout = new QHBoxLayout;
    m_mainLayout->addLayout(buttonLayout);

    m_button = new QPushButton("Button", this);
    buttonLayout->addWidget(m_button);

    connect(m_button, SIGNAL(clicked()), this, SLOT(onButtonClickedOnce()));

    m_initWidget = new MyWidget(this, 1);
    m_mainLayout->addWidget(m_initWidget);
  }

private slots:
  void onButtonClickedOnce()
  {
    m_button->disconnect(this);

    m_mainLayout->removeWidget(m_initWidget);
    QSplitter* splitter = new QSplitter(Qt::Horizontal, this);
    m_mainLayout->addWidget(splitter);

    splitter->addWidget(m_initWidget);
    MyWidget* newWidget = new MyWidget(splitter, 2);
    splitter->addWidget(newWidget);
  }

private:
  QVBoxLayout* m_mainLayout;
  QWidget* m_initWidget;
  QPushButton* m_button;
};

//main.cpp

#include <QtWidgets/QApplication>
#include "MyMainWindow.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    MyMainWindow mainWindow;
    mainWindow.show();

    return a.exec();
}

Andere Tipps

When you operate with widget which is part of layout, then you need to use appropriate methods of QLayout (parent of QVBoxLayout) to detach the item from layout:

QLayout::removeWidget (removeItem if it is not widget, but spacer item or another layout) QLayout::addWidget (addItem --/--)

Btw: even when widget moves between layouts, its parent may even stay same. I guess you have no need to call QWidget::setParent() as the calls of addWidget/removeWidget will do all work for you.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top