Here is my class MainWindow :
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
menu* v = new menu(this);
setCentralWidget(v);
}
And my menu class :
menu::menu(MainWindow* parent){
QLabel l = new QLabel("123");
QVBoxLayout* lay = new QVBoxLayout;
lay->addWidget(l);
this->setLayout(lay);
QWidget* a = new QWidget;
QVBoxLayout* lay2 = new QVBoxLayout;
QLabel* ll = new QLabel("456");
lay2->addWidget(ll);
a->setLayout(lay2);
parent->setCentralWidget(a);
}
When I run the program, the window shows 123 but I would like it to show 456.
Is the method setCentralWidget not working?
setCentralWidget works ok.
You are mixing up your widget menu construction with its position in an external widget (MainWindow). You should keep these thing well separated, or you won't be able, for example, to use menu inside other widgets.
So, you should set the appearance of menu in the constructor, and call setCentralWidget only in MainWindow.
It should look like:
file.h
menu::menu(QWidget* parent = 0);
file.cpp
menu::menu(QWidget* parent) : QWidget(parent)
{
// Create items
QLabel* l = new QLabel("123", this);
QLabel* ll = new QLabel("456", this);
// Put items in layout
QVBoxLayout* lay = new QVBoxLayout();
lay->addWidget(l);
lay->addWidget(ll);
// Set "lay" as the layout of this widget
setLayout(lay);
}
UPDATE
Since the wanted behavior is to have an interface that switch view according to button clicks:
the best option is to use a QStackedWidget.
Here a sample code the will produce this interface using QStackedWidget.
widget1.h
#ifndef WIDGET1
#define WIDGET1
#include <QWidget>
#include <QPushButton>
#include <QVBoxLayout>
class Widget1 : public QWidget
{
Q_OBJECT
public:
Widget1(QWidget* parent = 0) : QWidget(parent) {
QPushButton* btn = new QPushButton("Button Widget 1", this);
QVBoxLayout* layout = new QVBoxLayout();
layout->addWidget(btn);
setLayout(layout);
connect(btn, SIGNAL(clicked()), SIGNAL(buttonClicked()));
}
signals:
void buttonClicked();
};
#endif // WIDGET1
widget2.h
#ifndef WIDGET2
#define WIDGET2
#include <QWidget>
#include <QPushButton>
#include <QVBoxLayout>
class Widget2 : public QWidget
{
Q_OBJECT
public:
Widget2(QWidget* parent = 0) : QWidget(parent) {
QPushButton* btn1 = new QPushButton("Button 1 Widget 2", this);
QPushButton* btn2 = new QPushButton("Button 2 Widget 2", this);
QVBoxLayout* layout = new QVBoxLayout();
layout->addWidget(btn1);
layout->addWidget(btn2);
setLayout(layout);
connect(btn2, SIGNAL(clicked()), SIGNAL(button2Clicked()));
}
signals:
void button1Clicked();
void button2Clicked();
};
#endif // WIDGET2
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QStackedWidget>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
void buttonWidget1Clicked();
void button2Widget2Clicked();
private:
QStackedWidget* m_sw;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include <QVBoxLayout>
#include <QLabel>
#include "widget1.h"
#include "widget2.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
// Create Widgets
Widget1* w1 = new Widget1(this);
Widget2* w2 = new Widget2(this);
QLabel* w3 = new QLabel("Result", this);
m_sw = new QStackedWidget(this);
m_sw->addWidget(w1);
m_sw->addWidget(w2);
m_sw->addWidget(w3);
setCentralWidget(m_sw);
connect(w1, SIGNAL(buttonClicked()), this, SLOT(buttonWidget1Clicked()));
connect(w2, SIGNAL(button2Clicked()), this, SLOT(button2Widget2Clicked()));
}
void MainWindow::buttonWidget1Clicked()
{
m_sw->setCurrentIndex(1); // Will show Widget2
}
void MainWindow::button2Widget2Clicked()
{
m_sw->setCurrentIndex(2); // Will show Widgee3
}
MainWindow::~MainWindow() {}
Related
I have set a dark theme on my QWidget. In that widget I call a QDialog. The dialog appears in default palette which is light.
This is my custom dialog (Which in this case is for choosing colors for palette! Twisted right?) .cpp file:
#include "custompalettedialog.h"
CustomPaletteDialog::CustomPaletteDialog(QPalette palette, QWidget *parent) : QDialog(parent),
m_palette(palette)
{
QVBoxLayout* mainLayout = new QVBoxLayout(this);
mainLayout->setSpacing(0);
mainLayout->setMargin(0);
QFormLayout* mainFormLayout = new QFormLayout;
mainFormLayout->setHorizontalSpacing(0);
mainFormLayout->setVerticalSpacing(0);
mainLayout->addLayout(mainFormLayout);
for (int var = 0; var < QPalette::ColorRole::NColorRoles; ++var) {
QPushButton* bandButton = new QPushButton;
bandButton->setFlat(true);
bandButton->setAutoFillBackground(true);
QPalette pal = bandButton->palette();
pal.setColor(QPalette::Button, m_palette.color(static_cast<QPalette::ColorRole>(var)));
bandButton->setPalette(pal);
connect(bandButton, &QPushButton::clicked, this, [this, bandButton, var]() {
QColor color = QColorDialog::getColor();
if (color.isValid()) {
m_palette.setColor(static_cast<QPalette::ColorRole>(var), color);
QPalette pal = bandButton->palette();
pal.setColor(QPalette::Button, color);
bandButton->setPalette(pal);
}
});
mainFormLayout->addRow(QVariant::fromValue(static_cast<QPalette::ColorRole>(var)).toString(), bandButton);
}
QPushButton* doneButton = new QPushButton("Done");
connect(doneButton, &QPushButton::clicked, this, &QDialog::accept);
mainLayout->addWidget(doneButton);
}
QPalette CustomPaletteDialog::getPalette()
{
return m_palette;
}
QPalette CustomPaletteDialog::getPalette(bool* ok, const QPalette palette, QWidget *parent, const QString title)
{
CustomPaletteDialog* dialog = new CustomPaletteDialog(palette, parent);
dialog->setFont(parent->font());
dialog->setModal(true);
dialog->setWindowTitle(title);
dialog->exec();
QPalette pal = dialog->getPalette();
*ok = dialog->result();
dialog->deleteLater();
return pal;
}
and the .h file:
#ifndef CUSTOMPALETTEDIALOG_H
#define CUSTOMPALETTEDIALOG_H
#include <QDialog>
#include <QFormLayout>
#include <QPushButton>
#include <QLineEdit>
#include <QColorDialog>
#include <QComboBox>
class CustomPaletteDialog : public QDialog
{
Q_OBJECT
public:
explicit CustomPaletteDialog(QPalette palette, QWidget *parent = nullptr);
static QPalette getPalette(bool* ok, const QPalette palette, QWidget *parent = nullptr, const QString title = QString());
QPalette getPalette();
private:
QPalette m_palette;
};
#endif // CUSTOMPALETTEDIALOG_H
I call the static method getPalette from a parent widget.
I have tried adding this:
dialog->setPalette(parent->palette());
before dialog->setFont(parent->font()); in that static method and not working. My question is how to propagate QPalette from parent QWidget to child QDialog?
This is how I used it:
QPushButton* paletteAddButton = new QPushButton("Add...");
mainGroupBoxLayout->addWidget(paletteAddButton);
connect(paletteAddButton, &QPushButton::clicked, this, [this, customThemeItemModel]() {
bool ok = false;
QPalette palette = CustomPaletteDialog::getPalette(&ok, this->palette(), this, "Chosse UI Palette");
if (ok) {
QStandardItem* item = new QStandardItem("newPalette");
item->setToolTip("Double Click to Change Name, Right Click for More");
item->setData(palette);
customThemeItemModel->appendRow(item);
saveThemes(customThemeItemModel);
}
});
I have a list of themes, user can add custom themes to that list.
please guide me in finding the problem of this simplified code in reading text from qlineedit. My code exit in editUser->text() line. Every thing else is ok when I remove this line.
#include ...
QString USERID_LOG="SomeThing";
logDialog::logDialog(QWidget *parent)
: QDialog(parent)
, ui(new Ui::logDialog)
{
ui->setupUi(this);
QLineEdit* editUser= new QLineEdit( this );
QPushButton* okButton = new QPushButton(tr("OK"));
connect(okButton, SIGNAL(clicked()), this,SLOT(okSlot()));
...
}
void logDialog::okSlot()
{ USERID_LOG=editUser->text(); //////// Error is here
logDialog::accept();
return; }
QString logDialog::GetUser()
{
return(USERID_LOG);
}
////////////////////////////logdialog.h/////////////////////////
QT_BEGIN_NAMESPACE
namespace Ui { class logDialog; }
QT_END_NAMESPACE
class logDialog : public QDialog
{
Q_OBJECT
public:
logDialog(QWidget *parent = nullptr);
~logDialog();
QString GetUser();
public slots:
void okSlot();
private:
QLineEdit* editUser;
QPushButton* okButton;
Ui::logDialog *ui;
};
Consider your constructor...
logDialog::logDialog(QWidget *parent)
: QDialog(parent)
, ui(new Ui::logDialog)
{
ui->setupUi(this);
QLineEdit* editUser= new QLineEdit( this );
QPushButton* okButton = new QPushButton(tr("OK"));
connect(okButton, SIGNAL(clicked()), this,SLOT(okSlot()));
...
}
The lines...
QLineEdit* editUser= new QLineEdit( this );
QPushButton* okButton = new QPushButton(tr("OK"));
redeclare/redefine two locally scoped variables editUser and okButton that shadow the member variables of the same names. Instead you should simply initialize the member variables themselves...
editUser= new QLineEdit( this );
okButton = new QPushButton(tr("OK"));
Or, perhaps better, perform the initialization in the ctor's initializer list...
logDialog::logDialog(QWidget *parent)
: QDialog(parent)
, editUser(new QLineEdit(this))
, okButton(new QPushButton(tr("OK")))
, ui(new Ui::logDialog)
{
ui->setupUi(this);
connect(okButton, SIGNAL(clicked()), this,SLOT(okSlot()));
...
I would like to create custom QT dialog (non-modal). Problem with my implementation is that it shows only dialog window with title, and no widgets that I've added to it.
Code below (I've ommited most of it, added just dialog and main window parts).
MainWindow.h
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
/// some other stuff
private:
std::unique_ptr<ui::DialogAddUpdateItem> addItemDialog;
/// some other stuff
}
MainWindow.cpp
/// some stuff
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
/// some stuff
addItemButton = new QPushButton(tr("Add item"));
QObject::connect(addItemButton, &QPushButton::pressed, this, &MainWindow::openAddItemDialog);
navLay->addWidget(addItemButton);
addItemDialog = make_unique<ui::DialogAddUpdateItem>(this);
/// some stuff
}
void MainWindow::openAddItemDialog() {
addItemDialog->show();
//addItemDialog->raise(); does not work with or without those functions
//addItemDialog->activateWindow();
//QApplication::processEvents();
}
DialogAddUpdateItem.h
namespace ui {
class DialogAddUpdateItem : public QDialog
{
Q_OBJECT
public:
DialogAddUpdateItem(QWidget *parent = nullptr);
private:
QPushButton *buttonAcc, *buttonRevert, *buttonCancel;
QGroupBox *centralWidget, *buttonsWidget;
QLabel *labelName, *labelDescription;
QLineEdit *textName;
QPlainTextEdit *textDescription;
}
}
DialogAddUpdateItem.cpp
namespace ui {
DialogAddUpdateItem::DialogAddUpdateItem(QWidget *parent) : QDialog(parent)
{
if (!item) {
setWindowTitle(tr("New object"));
}
centralWidget = new QGroupBox;
QHBoxLayout *itemLay = new QHBoxLayout;
centralWidget->setLayout(itemLay);
labelName = new QLabel(tr("Name"));
itemLay->addWidget(labelName);
textName = new QLineEdit;
if (item) {
textName->setText(QString::fromStdString(item->getName()));
}
itemLay->addWidget(textName);
labelDescription = new QLabel(tr("Description"));
if (item) {
textDescription = new QPlainTextEdit(QString::fromStdString(item->getDescription()));
} else {
textDescription = new QPlainTextEdit;
}
itemLay->addWidget(textDescription);
buttonAcc = new QPushButton(tr("Save"));
buttonAcc->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
QObject::connect(buttonAcc, &QPushButton::clicked, this, &DialogAddUpdateItem::acceptItem);
buttonRevert = new QPushButton(tr("Revert"));
buttonRevert->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
QObject::connect(buttonRevert, &QPushButton::clicked, this, &DialogAddUpdateItem::revertItem);
buttonCancel = new QPushButton(tr("Cancel"));
buttonCancel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
QObject::connect(buttonCancel, &QPushButton::clicked, this, &DialogAddUpdateItem::cancelItem);
buttonsWidget = new QGroupBox;
itemLay->addWidget(buttonsWidget);
QVBoxLayout *buttonsLay = new QVBoxLayout;
buttonsLay->addWidget(buttonAcc);
buttonsLay->addWidget(buttonRevert);
buttonsLay->addWidget(buttonCancel);
}
}
In DialogAddUpdateItem.cpp the centralWidget has no parent, therefore it is not bound to anything and therefore not displayed. You should modify this:
centralWidget = new QGroupBox;
into this:
centralWidget = new QGroupBox(this);
Now the DialogAddUpdateItem will be the parent of the centralWidget and it should display it.
Also it seems like You are leaving some other widgets without a parent - it might cause trouble. For example the QLineEdit textName has this issue.
First of all, I created about 20 push buttons using for loop. And named them using if else loop. Now, I want to connect each push buttons with the new dialog box. If I had used the design mode of QT, it would show me the name of the button when I press connect(ui->pushButton_0, SIGNAl(released()), SLOT(digit_pressed()) something like this. But, I don't know the name of the pushbutton I made as the for and if else loop made it. The connect(ui-> .......) also doesn't show any predictions. How can I link these push buttons and a new dialog box?
Here is my code:
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
private slots:
void on_pushButton_clicked();
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QPushButton>
#include <QVBoxLayout>
#include "amputation.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(ui->)
QPixmap pix("/home/skanda/Desktop/D4564.png");
ui->label_2->setPixmap(pix);
setWindowTitle("First Aid");
QVBoxLayout *lay = new QVBoxLayout();
int i;
for(i=0;i<25;i++)
{
if(i==0){
QPushButton *button = new QPushButton("Amputation");
lay->addWidget(button);
}
else if(i==1){
QPushButton *button = new QPushButton("Asthama");
lay->addWidget(button);
}
else if(i==2){
QPushButton *button = new QPushButton("Bleeding");
lay->addWidget(button);
}
else if(i==3){
QPushButton *button = new QPushButton("Burns");
lay->addWidget(button);
}
else if(i==4){
QPushButton *button = new QPushButton("Chest Pain");
lay->addWidget(button);
}
else if(i==5){
QPushButton *button = new QPushButton("Diarrhoea");
lay->addWidget(button);
}
else if(i==6){
QPushButton *button = new QPushButton("Drowning");
lay->addWidget(button);
}
else if(i==7){
QPushButton *button = new QPushButton("Epilepsy");
lay->addWidget(button);
}
else if(i==8){
QPushButton *button = new QPushButton("Fainting");
lay->addWidget(button);
}
else if(i==9){
QPushButton *button = new QPushButton("Fever");
lay->addWidget(button);
}
else if(i==10){
QPushButton *button = new QPushButton("Food Poisoning");
lay->addWidget(button);
}
else if(i==11){
QPushButton *button = new QPushButton("Fracture");
lay->addWidget(button);
}
else if(i==12){
QPushButton *button = new QPushButton("Head Injury");
lay->addWidget(button);
}
else if(i==13){
QPushButton *button = new QPushButton("Muscle Strain");
lay->addWidget(button);
}
else if(i==14){
QPushButton *button = new QPushButton("No breathing");
lay->addWidget(button);
}
else if(i==15){
QPushButton *button = new QPushButton("Nose bleed");
lay->addWidget(button);
}
else if(i==16){
QPushButton *button = new QPushButton("Poisoning");
lay->addWidget(button);
}
else if(i==17){
QPushButton *button = new QPushButton("Snake Bites");
lay->addWidget(button);
}
else if(i==18){
QPushButton *button = new QPushButton("Stroke");
lay->addWidget(button);
}
else if(i==19) {
QPushButton *button = new QPushButton("Sun Burn");
lay->addWidget(button);
}
else if(i==20) {
QPushButton *button = new QPushButton("Testicle Pain");
lay->addWidget(button);
}
else if(i==21) {
QPushButton *button = new QPushButton("Ulcer");
lay->addWidget(button);
}
else if(i==22) {
QPushButton *button = new QPushButton("Child delievery");
lay->addWidget(button);
}
else if(i==23) {
QPushButton *button = new QPushButton("Heart Attack");
lay->addWidget(button);
}
else {
QPushButton *button = new QPushButton("Gastric");
lay->addWidget(button);
}
}
ui->scrollContents->setLayout(lay);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked(){
Amputation amp;
amp.setModal(true);
amp.show();
}
**In these codes, I have tried my luck by creating on_pushButton_clicked() function. But, it was just a try. **
As in programming everything is cooking, :), let's see what are the ingredients of connect():
connect(sender, &Sender::signal, receiver, &Receiver::slot);
so sender would be the buttons, the signal is the clicked, the receiver itself, that is, this, and the slot on_pushButton_clicked
I see unnecessary if-else, everything can be reduced to a for:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QPushButton>
#include <QVBoxLayout>
#include "amputation.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QPixmap pix("/home/skanda/Desktop/D4564.png");
ui->label_2->setPixmap(pix);
setWindowTitle("First Aid");
QVBoxLayout *lay = new QVBoxLayout();
QStringList names{"Amputation", "Asthama", "Bleeding", "Burns", "Chest Pain",
"Drowning", "Diarrhoea", "Epilepsy", "Fainting", "Fever",
"Food Poisoning", "Fracture", "Head Injury", "Muscle Strain",
"No breathing", "Nose bleed", "Poisoning", "Snake Bites",
"Stroke","Sun Burn", "Testicle Pain", "Ulcer", "Child delievery",
"Heart Attack", "Gastric"};
for(const QString & name: names)
{
QPushButton *button = new QPushButton(name);
lay->addWidget(button);
connect(button, &QPushButton::clicked, this, &MainWindow::on_pushButton_clicked)
}
ui->scrollContents->setLayout(lay);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked(){
Amputation amp;
amp.setModal(true);
amp.show();
}
Note:
avoid using the old style of connection, has many disadvantages, read the content of the following link for more information:
https://wiki.qt.io/New_Signal_Slot_Syntax
Make all these QPushButton members of a class such that they are created and destroyed properly rather than creating them in an loop.
Once you have each one as a separate member, then have a method InitializeConnections() and make all the connections under it using the Qt connect syntax.
If you believe these buttons are part of the MainWindow class, then your class can look something like this :
class MainWindow{
...
...
private :
// Will make connections of each button to it's respective slot.
void InitializeConnections();
private :
QPushButton *mAmputationButton;
QPushButton *mAsthmaButton;
//.. so on
};
And in MainWindow.cpp :
#include <QPushButton>
#include <QVBoxLayout>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow),
mAmputationButton(new QPushButton("Amputation") ),
mAsthmaButton(new QPushButton("Asthama") )
{
InitializeConnections();
}
void MainWindow::InitializeConnections()
{
connect(mAmputationButton, &QPushButton::clicked, this, &MainWindow::amputation_slot );
connect(mAsthmaButton, &QPushButton::clicked, this, &MainWindow::asthma_slot );
// same way for others.
}
The slots that i have mentioned are just for example, connect it to the slot that you need it to be connected to.
UPDATE :
Here is a mini-implementation made using just the two buttons :
MainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
class QPushButton;
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
QPushButton *mAmputationButton;
QPushButton *mAsthmaButton;
private slots:
void on_pushButton_clicked();
};
MainWindow.cpp
#include "MainWindow.h"
#include <QPushButton>
#include <QVBoxLayout>
#include <QDialog>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
mAmputationButton( new QPushButton("Amputation" ) ),
mAsthmaButton( new QPushButton("Astham" ) )
{
setWindowTitle("First Aid");
QWidget *sampleWidget = new QWidget();
QVBoxLayout *lay = new QVBoxLayout();
lay->addWidget(mAmputationButton);
connect(mAmputationButton, &QPushButton::clicked, this, &MainWindow::on_pushButton_clicked );
connect(mAsthmaButton, &QPushButton::clicked, this, &MainWindow::on_pushButton_clicked );
lay->addWidget(mAsthmaButton);
sampleWidget->setLayout(lay);
setCentralWidget(sampleWidget);
}
MainWindow::~MainWindow(){}
void MainWindow::on_pushButton_clicked(){
QDialog *sampleDialog = new QDialog();
sampleDialog->setModal(true);
sampleDialog->show();
}
Note1 : In the slot on_pushbutton_clicked, I am just creating a new dialog and showing it. Just add your slot logic there and you will be good to go.
Note2 : It will be advisable to have all your connections in a single method such as Initialize Connections as already mentioned above.
Take this mini-implementation just as an example that you can work on top of rather than a copy-paste use of it.
I have an application that has 3 main widgets. I also have a pop-out QDockWidget. I'm trying to get the QDockWidget to dock into the right half of the bottom widget, but as you can see in the image below, the only places I can dock the window are on the edges of the application. How can I make it so that the QDockWidget window takes up the right half of the bottom widget?
Also, is there a way to have a QDockWidget be already docked upon opening the application instead of having it open separately in its own window?
EDIT: Using #Bertrand's answer below, here's what I wound up doing:
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
void on_actionRestore_layout_triggered();
QMainWindow* m_rightSideWindow;
QDockWidget* m_dockWidget1;
QDockWidget* m_dockWidget2;
QDockWidget* m_dockWidget3;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QtWidgets>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow),
m_rightSideWindow(NULL),
m_dockWidget1(NULL),
m_dockWidget2(NULL),
m_dockWidget3(NULL)
{
ui->setupUi(this);
QSplitter *splitter = new QSplitter(this);
splitter->setOrientation(Qt::Horizontal);
QTreeView* leftSideWidget = new QTreeView(this);
m_rightSideWindow = new QMainWindow(this);
m_rightSideWindow->setWindowFlags(Qt::Widget);
m_rightSideWindow->layout()->setContentsMargins(3, 3, 3, 3);
splitter->addWidget(leftSideWidget);
splitter->addWidget(m_rightSideWindow);
m_dockWidget1 = new QDockWidget("Dock 1", this);
m_rightSideWindow->addDockWidget(Qt::TopDockWidgetArea, m_dockWidget1);
m_dockWidget1->setTitleBarWidget(new QWidget()); // remove title bar
m_dockWidget1->setAllowedAreas(Qt::NoDockWidgetArea); // do not allow to dock
QTextEdit* textEdit1 = new QTextEdit(this); // put any QWidget derived class inside
m_dockWidget1->setWidget(textEdit1);
m_dockWidget2 = new QDockWidget("Dock 2", this);
m_rightSideWindow->addDockWidget(Qt::BottomDockWidgetArea, m_dockWidget2);
m_dockWidget2->setTitleBarWidget(new QWidget());
m_dockWidget2->setAllowedAreas(Qt::NoDockWidgetArea);
QTextEdit* textEdit2 = new QTextEdit(this);
m_dockWidget2->setWidget(textEdit2);
m_dockWidget3 = new QDockWidget("Dock 3", this);
m_rightSideWindow->addDockWidget(Qt::BottomDockWidgetArea, m_dockWidget3);
QTextEdit* textEdit3 = new QTextEdit(this);
m_dockWidget3->setWidget(textEdit3);
setCentralWidget(splitter);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_actionRestore_layout_triggered()
{
QList<QDockWidget*> list = findChildren<QDockWidget*>();
foreach(QDockWidget* dock, list)
{
if(dock->isFloating())
dock->setFloating(false);
m_rightSideWindow->removeDockWidget(dock);
if (dock == m_dockWidget1)
m_rightSideWindow->addDockWidget(Qt::TopDockWidgetArea, m_dockWidget1);
else
m_rightSideWindow->addDockWidget(Qt::BottomDockWidgetArea, dock);
dock->setVisible(true);
}
m_rightSideWindow->splitDockWidget(m_dockWidget2, m_dockWidget3, Qt::Horizontal);
}
You can dock a QDockWidget on a QMainWindow or another QDockWidget.
To get the desired layout embed a sub QMainWindow on the right side of your main window, and use it as a QWidget with setWindowFlags(Qt::Widget):
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QtWidgets>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QSplitter *splitter = new QSplitter(this);
splitter->setOrientation(Qt::Horizontal);
QTreeView* leftSideWidget = new QTreeView(this);
m_rightSideWindow = new QMainWindow(this);
m_rightSideWindow->setWindowFlags(Qt::Widget);
m_rightSideWindow->layout()->setContentsMargins(3, 3, 3, 3);
splitter->addWidget(leftSideWidget);
splitter->addWidget(m_rightSideWindow);
m_dockWidget1 = new QDockWidget("Dock 1", this);
m_rightSideWindow->addDockWidget(Qt::TopDockWidgetArea, m_dockWidget1);
m_dockWidget1->setTitleBarWidget(new QWidget()); // remove title bar
m_dockWidget1->setAllowedAreas(Qt::NoDockWidgetArea); // do not allow to dock
QTextEdit* textEdit1 = new QTextEdit(this); // put any QWidget derived class inside
m_dockWidget1->setWidget(textEdit1);
m_dockWidget2 = new QDockWidget("Dock 2", this);
m_rightSideWindow->addDockWidget(Qt::BottomDockWidgetArea, m_dockWidget2);
m_dockWidget2->setTitleBarWidget(new QWidget());
m_dockWidget2->setAllowedAreas(Qt::NoDockWidgetArea);
QTextEdit* textEdit2 = new QTextEdit(this);
m_dockWidget2->setWidget(textEdit2);
m_dockWidget3 = new QDockWidget("Dock 3", this);
m_rightSideWindow->addDockWidget(Qt::BottomDockWidgetArea, m_dockWidget3);
QTextEdit* textEdit3 = new QTextEdit(this);
m_dockWidget3->setWidget(textEdit3);
setCentralWidget(splitter);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_actionRestore_layout_triggered()
{
QList<QDockWidget*> list = findChildren<QDockWidget*>();
foreach(QDockWidget* dock, list)
{
if(dock->isFloating())
dock->setFloating(false);
m_rightSideWindow->removeDockWidget(dock);
if (dock == m_dockWidget1)
m_rightSideWindow->addDockWidget(Qt::TopDockWidgetArea, m_dockWidget1);
else
m_rightSideWindow->addDockWidget(Qt::BottomDockWidgetArea, dock);
dock->setVisible(true);
}
m_rightSideWindow->splitDockWidget(m_dockWidget2, m_dockWidget3, Qt::Horizontal);
}