I have been trying to figure out if you could dock a QDockWidget in a QSplitter, here is my original question. However, after doing a lot of digging around, I found this helpful post which lead to another post that stated that QDockWidgets
can only be docked on QMainWindows
. In the helpful post I linked, there was a comment that led to this solution on the QtCenter.
What I have done, is taken that code and added it to my application. However, I quickly found out that it only works one way. As in if I have a QMainWindow
in my QSplitter
, I can take the QDockWindow
out of the QSplitter
and dock it on the main application. However, I cannot re-dock my QSplitter's QDockWindow
back into the QSplitter's QMainWindow
.
I then tried to create another class called, MyWindow
as I figured that maybe I just need to be able to create a seperate QMainWindow
class that I can then connect through the GUI and has the same functions as the MainWindowClass
. However that too has failed. Here is my code:
MyWindow.hpp
#ifndef MYWINDOW_HPP
#define MYWINDOW_HPP
#include <QMainWindow>
#include <QObject>
#include <QWidget>
#include <QDockWidget>
class MyWindow : public QMainWindow
{
Q_OBJECT
public:
MyWindow(QWidget *child = nullptr);
QMainWindow* createNewWindow();
public slots:
void dragStarted(bool started);
void enterEvent(QEvent *event);
void dragEnded() { dw = nullptr; }
private:
QDockWidget* dw = nullptr;
};
#endif // MYWINDOW_HPP
MyWindow.cpp
#include "mywindow.hpp"
MyWindow::MyWindow(QWidget *child) : QMainWindow (child){}
QMainWindow* MyWindow::createNewWindow()
{
QMainWindow *newWindow = new QMainWindow(this);
newWindow->setWindowFlags(Qt::Widget);
return newWindow;
}
void MyWindow::dragStarted(bool started)
{
if(started)
{
if(QDockWidget* dock = qobject_cast<QDockWidget*>(sender()))
dw = dock;
else
dw = nullptr;
}
}
void MyWindow::enterEvent(QEvent *event)
{
if(dw && dw->parent() != this)
{
addDockWidget(Qt::RightDockWidgetArea, dw);
dw = nullptr;
}
}
MainWindow.hpp
#ifndef MAINWINDOW_HPP
#define MAINWINDOW_HPP
#include <QMainWindow>
#include <QWidget>
#include <QDockWidget>
#include "mywindow.hpp"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
public slots:
void dragStarted(bool started);
void enterEvent(QEvent *event);
void dragEnded() { dw = nullptr; }
private:
Ui::MainWindow *ui;
QDockWidget* dw = nullptr;
};
#endif // MAINWINDOW_HPP
MainWindow.cpp
#include "mainwindow.hpp"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QWidget *child = nullptr;
MyWindow myWindow(child);
QMainWindow *leftWindow = myWindow.createNewWindow();
QMainWindow *rightWindow = myWindow.createNewWindow();
leftWindow->addDockWidget(Qt::LeftDockWidgetArea,ui->leftDock);
rightWindow->addDockWidget(Qt::RightDockWidgetArea,ui->rightDock);
ui->splitter->addWidget(leftWindow);
ui->splitter->addWidget(rightWindow);
//connect(ui->leftDock,SIGNAL(topLevelChanged(bool)),&myWindow,SLOT(dragStarted(bool)));
//connect(ui->rightDock,SIGNAL(topLevelChanged(bool)),&myWindow,SLOT(dragStarted(bool)));
connect(ui->leftDock,SIGNAL(topLevelChanged(bool)),this,SLOT(dragStarted(bool)));
connect(ui->rightDock,SIGNAL(topLevelChanged(bool)),this,SLOT(dragStarted(bool)));
//connect(ui->leftDock,SIGNAL(dockLocationChanged (Qt::DockWidgetArea)),&myWindow,SLOT(dragEnded()));
//connect(ui->rightDock,SIGNAL(dockLocationChanged (Qt::DockWidgetArea)),&myWindow,SLOT(dragEnded()));
connect(ui->leftDock,SIGNAL(dockLocationChanged (Qt::DockWidgetArea)),this,SLOT(dragEnded()));
connect(ui->rightDock,SIGNAL(dockLocationChanged (Qt::DockWidgetArea)),this,SLOT(dragEnded()));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::dragStarted(bool started)
{
if(started)
{
if(QDockWidget* dock = qobject_cast<QDockWidget*>(sender()))
dw = dock;
else
dw = nullptr;
}
}
void MainWindow::enterEvent(QEvent *event)
{
if(dw && dw->parent() != this)
{
addDockWidget(Qt::RightDockWidgetArea, dw);
dw = nullptr;
}
}
The commented out pieces of code is what I originally tried to do in order to connect them. My thought process was that MyWindow
class should have it's own QDockWidget
, however when thinking about it, MainWindow
class is the one that actually owns the QDockWidget
and I am not really sure if re-assigning the parent QMainWindow
is the right way to go or not.
What do I need to do in order to get them to re-dock to their original Parent's QMainWindow?
EDIT:
Here is the ui file should anyone need it:
MainWindow.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1144</width>
<height>802</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralWidget">
<widget class="QSplitter" name="splitter">
<property name="geometry">
<rect>
<x>30</x>
<y>60</y>
<width>781</width>
<height>591</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>681</width>
<height>551</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::Box</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<property name="lineWidth">
<number>2</number>
</property>
<property name="midLineWidth">
<number>2</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</widget>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1144</width>
<height>21</height>
</rect>
</property>
</widget>
<widget class="QToolBar" name="mainToolBar">
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
</widget>
<widget class="QStatusBar" name="statusBar"/>
<widget class="QDockWidget" name="leftDock">
<property name="maximumSize">
<size>
<width>524287</width>
<height>300</height>
</size>
</property>
<property name="windowTitle">
<string>Left Dock</string>
</property>
<attribute name="dockWidgetArea">
<number>1</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QTabWidget" name="tabWidget">
<widget class="QWidget" name="tab">
<attribute name="title">
<string>Tab 1</string>
</attribute>
</widget>
<widget class="QWidget" name="tab_2">
<attribute name="title">
<string>Tab 2</string>
</attribute>
</widget>
</widget>
</item>
</layout>
</widget>
</widget>
<widget class="QDockWidget" name="rightDock">
<property name="maximumSize">
<size>
<width>524287</width>
<height>300</height>
</size>
</property>
<property name="windowTitle">
<string>Right Dock</string>
</property>
<attribute name="dockWidgetArea">
<number>1</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents_2">
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QTabWidget" name="tabWidget_2">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="tab_3">
<attribute name="title">
<string>Tab 1</string>
</attribute>
</widget>
<widget class="QWidget" name="tab_4">
<attribute name="title">
<string>Tab 2</string>
</attribute>
</widget>
</widget>
</item>
</layout>
</widget>
</widget>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>