QSplitter becoming undistinguishable between QWidget and QTabWidget

10,274

Solution 1

Since the QSplitterHandle (which is what most people think of as the 'splitter') is derived from QWidget, you can add other widgets to it. Here is what I have done to solve this exact problem in the past:

// Now add the line to the splitter handle
// Note: index 0 handle is always hidden, index 1 is between the two widgets
QSplitterHandle *handle = pSplitter->handle(1);
QVBoxLayout *layout = new QVBoxLayout(handle);
layout->setSpacing(0);
layout->setMargin(0);

QFrame *line = new QFrame(handle);
line->setFrameShape(QFrame::HLine);
line->setFrameShadow(QFrame::Sunken);
layout->addWidget(line);

This adds a sunken line to the splitter handle. You can, of course, choose another style for the frame line or use something entirely different as the widget you add to the splitter handle.

Solution 2

I based this on the above code but it handles both splitter orientations. I just preferred non-opaque resizing and non-collapsible children. The grip consists of three parallel lines. You can play with the handle width, but grip at 7 looks good on Windows; haven't checked in Linux or Mac.

void helper::decorateSplitter(QSplitter* splitter, int index)
{
    Q_ASSERT(splitter != NULL);

    const int gripLength = 15; 
    const int gripWidth = 1;
    const int grips = 3;

    splitter->setOpaqueResize(false);
    splitter->setChildrenCollapsible(false);

    splitter->setHandleWidth(7);
    QSplitterHandle* handle = splitter->handle(index);
    Qt::Orientation orientation = splitter->orientation();
    QHBoxLayout* layout = new QHBoxLayout(handle);
    layout->setSpacing(0);
    layout->setMargin(0);

    if (orientation == Qt::Horizontal)
    {
        for (int i=0;i<grips;++i)
        {
            QFrame* line = new QFrame(handle);
            line->setMinimumSize(gripWidth, gripLength);
            line->setMaximumSize(gripWidth, gripLength);
            line->setFrameShape(QFrame::StyledPanel);
            layout->addWidget(line);
        }
    }
    else
    {
        //this will center the vertical grip
        //add a horizontal spacer
        layout->addStretch();
        //create the vertical grip
        QVBoxLayout* vbox = new QVBoxLayout;
        for (int i=0;i<grips;++i)
        {
            QFrame* line = new QFrame(handle);
            line->setMinimumSize(gripLength, gripWidth);
            line->setMaximumSize(gripLength, gripWidth);
            line->setFrameShape(QFrame::StyledPanel);
            vbox->addWidget(line);
        }
        layout->addLayout(vbox);
        //add another horizontal spacer
        layout->addStretch();
    }
}

Solution 3

This is true for every splitter at least with WinXP and the default Luna thema (changing to classic solves the problem). If you want to stay with Luna you may change the way the splitters are rendered, e.g. by changing the background color of the handle.

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

    QApplication a(argc, argv);
    a.setStyleSheet("QSplitter::handle { background-color: gray }");
    MainWindow w;
    w.show();
    return a.exec();
}

You may find more on Qt style sheets at https://doc.qt.io/qt-5/stylesheet-reference.html

Share:
10,274

Related videos on Youtube

Narek
Author by

Narek

Game developer.

Updated on April 17, 2022

Comments

  • Narek
    Narek about 2 years

    I am puting a QWidget and a QTabWidget next to each other in one horisontal splitter. And the splitter loses it's shape, you can know that there is a splitter only by hovering mouse on it. How to make it visible?

    Thanks.

  • Plouff
    Plouff about 8 years
    Probably the best solution here even using Qt5.6. Thanks!
  • feedc0de
    feedc0de about 8 years
    what language is this? This does not look like c++
  • panofish
    panofish about 8 years
    oops.. sorry this is python using pyqt or pyside
  • DerManu
    DerManu almost 8 years
    Had to set gripWidth = 2 for the grips to be visible (Win7 Classic look). Otherwise nice solution for a problem that should've been fixed in Qt years ago.