3
votes

I have a simple QWidget in a QDockWidget and my own title bar for this dock widget. In this title bar, I put a QPushButton that, when triggered, will allow me to:

  • set the title bar vertical
  • hide the widget inside the QDockWidget

I managed to get both of them working separately, but I can't succeed in doing it simultaneously.

Here is the code for the title bar:

QDockTitleBar::QDockTitleBar(const QString &title, QDockWidget * parent)
    : QWidget(parent)
{
    pDock = qobject_cast<QSuiteDockWidget*>(parentWidget());

    m_pMainLayout = new QHBoxLayout(this);

    m_pLabel = new QLabel(title, this);
    m_pMainLayout->addWidget(m_pLabel);

    m_pMainLayout->addStretch();

    m_pToggleButton = new QPushButton(this);
    //m_pToggleButton->setIcon(...); // whatever
    m_pToggleButton->setFlat(true);
    connect(m_pToggleButton, SIGNAL(clicked()), this, SLOT(toggleButtonTriggered()));
    m_pMainLayout->addWidget(m_pToggleButton);    
}

void QDockTitleBar::resizeEvent(QResizeEvent* event)
{
    if (pDock->features() & QDockWidget::DockWidgetVerticalTitleBar) 
        qDebug() << "I am Vertical";
    else 
        qDebug() << "I am Horizontal";
}

void QDockTitleBar::toggleButtonTriggered()
{
    const QDockWidget::DockWidgetFeatures features = pDock->features();

    if(features & QDockWidget::DockWidgetVerticalTitleBar)
    {
        pDock->widget()->show(); // comment this one...
        pDock->setFeatures(features ^ QDockWidget::DockWidgetVerticalTitleBar);
    }
    else
    {
        pDock->widget()->hide(); //... and this one : the title bar is set vertical
        pDock->setFeatures(features | QDockWidget::DockWidgetVerticalTitleBar);
    }           
}

In my main function :

QDockWidget* dock = new QDockWidget();
dock->setWindowTitle("DOCK");
QDockTitleBar* labelDock = new QDockTitleBar("DOCK", dock);
QWidget* widget = new QWidget(dock);
dock->setTitleBarWidget(labelDock);
dock->setWidget(widget);
addDockWidget(Qt::RightDockWidgetArea, dock);

NB : If I change pDock->widget()->hide() in pDock->widget()->show() and vice versa, I almost have the desired behavior, but the widget is hidden when the title bar is horizontal (I want it to be hidden when the title bar is vertical)...

I also put the resizeEvent(). When I trigger the button, title bar horizontal, I have :

I am Vertical

I am Horizontal

I am Horizontal

and if I trigger the button once again :

I am Vertical

I am Horizontal

I am Horizontal

I am Horizontal

Can anyone explain me this behavior and/or tell me what am I doing wrong and how I can fix it?


Edit : I work on Qt5.6, if that matters.

I am not focusing on the resizeEvent() being called or not, it's just the behavior that is not the one wanted. At the moment :

1/ If I use this code :

if(features & QDockWidget::DockWidgetVerticalTitleBar)
    pDock->setFeatures(features ^ QDockWidget::DockWidgetVerticalTitleBar);
else
    pDock->setFeatures(features | QDockWidget::DockWidgetVerticalTitleBar);

It works like it is supposed to work : the title bar is set vertical when the button is triggered, and back to horizontal when I trigger the button again. Plus, the widget is always shown.

2/ If I use this code :

if(features & QDockWidget::DockWidgetVerticalTitleBar)
{
    pDock->widget()->show();
    pDock->setFeatures(features ^ QDockWidget::DockWidgetVerticalTitleBar);
}
else
{
    pDock->widget()->hide();
    pDock->setFeatures(features | QDockWidget::DockWidgetVerticalTitleBar);
}   

Then, if I trigger the button, the widget is hidden (as wanted), BUT the title bar is not set vertical. If I trigger the button again, the widget is shown (as wanted), and the title bar is still horizontal (seems normal, since it didn't change at the first triggering).

3/ If I use this code (this is where the behavior seems to be near of what I want) :

if(features & QDockWidget::DockWidgetVerticalTitleBar)
{
    pDock->widget()->hide();
    pDock->setFeatures(features ^ QDockWidget::DockWidgetVerticalTitleBar);
}
else
{
    pDock->widget()->show();
    pDock->setFeatures(features | QDockWidget::DockWidgetVerticalTitleBar);
}  

Then :

  • first triggering : title bar set vertical (it is OK) BUT widget still shown
  • second triggering : title bar back to horizontal BUT widget hidden this time
  • third triggering, and after : title bar vertical with widget shown, then title bar horizontal with widget hidden. I would like the opposite, i.e. title bar vertical/widget hidden and title bar horizontal/widget shown.
2

2 Answers

2
votes

First of all I tried to compile your example with qt4.86 and qt5.5.1. And they behave a little bit different. With qt4.86 I think it works fine. But with qt5.5.1 it really shows "I am Horizontal" as you described. I don't know why they differ, but they do.

By the way it works on both qt4.86 and qt5.5.1 when I deattach QDockWidget from mainwindow.

So I think it works in the way you don't expect because you think that, when you hide your widget, QDockTitleBar::resizeEvent will be certainly called. But it is not always true. For example if the width of your hiding widget is not very big and so the width of your dockwidget is determined by the titlebar width, then resizeEvent in qt5.5.1 will not be called. If you want your QDockTitleBar::resizeEvent to be always called after showing/hiding of your widget you can explicitly call QCoreApplication::sendEvent ( QObject * receiver, QEvent * event ) with QResizeEvent instance.

0
votes

You may try to remove and then reassign your widget from the QDockWidget instead of hiding it.

if(features & QDockWidget::DockWidgetVerticalTitleBar)
{
    pDock->setFeatures(features ^ QDockWidget::DockWidgetVerticalTitleBar);
    pDock->setWidget(pDockWidget);
}
else
{
    pDock->setFeatures(features | QDockWidget::DockWidgetVerticalTitleBar);
    pDockWidget = pDock->widget();
    pDock->setWidget(0);
}