5

I´ve been trying to add the buttons to an undocked QDockWidget window as I normally do for a QDialog, but with no success as follows:

QDockWidget* dw = new QDockWidget(QString("Stream %1").arg(i + 1), this); 
dw->setWindowFlags((dw->windowFlags() | Qt::WindowMaximizeButtonHint |
    Qt::WindowMinimizeButtonHint | Qt::WindowCloseButtonHint));

When I undock them they still only have the [X] close button.

What am I missing?

Development environment info: Windows 10 x64, Visual Studio 2015, Qt 5.7.1, C++

Jens A. Koch
  • 39,862
  • 13
  • 113
  • 141
Petar Petrov
  • 702
  • 5
  • 14

2 Answers2

13

I figured out how to do it. You have to connect to the QDockWidget toplevelChanged(bool) signal.

connect(ui.dockWidget, SIGNAL(topLevelChanged(bool)), this, SLOT(dockWidget_topLevelChanged(bool)));

Then you need to check if its floating and set the window hints.

void MyClass::dockWidget_topLevelChanged(bool)
{
    QDockWidget* dw = static_cast<QDockWidget*>(QObject::sender());
    if (dw->isFloating())
    {
        dw->setWindowFlags(Qt::CustomizeWindowHint |
            Qt::Window | Qt::WindowMinimizeButtonHint |
            Qt::WindowMaximizeButtonHint |
            Qt::WindowCloseButtonHint);
        dw->show();
    }
}
Petar Petrov
  • 702
  • 5
  • 14
  • 3
    Here's how to show this QDockWidget separately in the Windows taskbar. https://stackoverflow.com/a/54459140/2721136 – KungPhoo Jan 31 '19 at 11:04
3

I'm afraid you can't do it that way, as QDockWidget look and feel is essentially hard coded in the QStyle your application is using, as stated in the documnetation (here in the "Appearance" section). Basically, QDockWidget is a borderless window, and the title bar and its structure(title, buttons, etc) is just painted using the style.

To overcome this, you may use a QProxyStyle to paint the minimize and maximize buttons, but these would not be "real" buttons but just their pixmaps. Hence, you would still need to perform some tinkering to handle the clicks to those virtual buttons (e.g. catching the click event on the title bar and determining if it happened inside one of these buttons).

Another possible solution is to subclass QDockWidget and implement all the painting and click event handling there. Beaware that if you want to support multiple platforms you may need to use QStyle::drawControl() to paint the extra buttons, instead of painting everything by yourself (e.g. drawing a pixmap).

I hope this helps you. Good luck with your project.

Sergio Monteleone
  • 2,776
  • 9
  • 21
  • Thats actually a good solution, for the buttons I could use the MousePressEvent and get the .rect() from the cursor over the "button" and see if it was clicked. Thats similar to what I did in the end, but I ended up subclassing QTabWidgets reimplementing the click and move event and unparenting and reparenting them. Visually they are more appropiate to what I needed (Because I was setting max size of central layout to (0,0) for QDockWidgets as I don´t need them as docks but like main widgets) – Petar Petrov May 26 '18 at 15:33
  • I found a solution, connecting to toplevelchanged signal. I´m going to post the solution soon. – Petar Petrov May 28 '18 at 11:40