QSplitter在QWidget和QTabWidget之间无法区分

时间:2010-03-30 13:34:37

标签: c++ qt qt4 qtabwidget qsplitter

我在一个水平分离器中将QWidget和QTabWidget放在一起。分离器失去了它的形状,只有将鼠标悬停在它上面就可以知道有一个分离器。如何让它可见?

感谢。

7 个答案:

答案 0 :(得分:27)

由于QSplitterHandle(大多数人认为是'拆分器')是从QWidget派生的,因此您可以添加其他小部件。以下是我过去为解决这个问题所做的工作:

// 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);

这会在分离器手柄上添加一条凹陷线。当然,您可以为框架line选择另一种样式,或者使用与添加到拆分器句柄中的窗口小部件完全不同的样式。

答案 1 :(得分:9)

我基于上面的代码,但它处理两个分割器方向。 我只是喜欢非不透明的大小调整和不可折叠的孩子。 手柄由三条平行线组成。您可以使用手柄宽度进行游戏,但在Windows上抓握7看起来不错;没有在Linux或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();
    }
}

答案 2 :(得分:7)

对于每个拆分器都是如此,至少使用WinXP和默认的Luna thema(改为经典解决问题)。 如果你想留在Luna,你可以改变分割器的渲染方式,例如:通过更改手柄的背景颜色。

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

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

您可以在https://doc.qt.io/qt-5/stylesheet-reference.html

的Qt样式表中找到更多信息

答案 3 :(得分:0)

您可以继承QSplitter并覆盖它protected virtual QSplitterHandle * QSplitter::createHandle()以返回任何让您满意的内容。

例如,从该重载方法中,您可以使用自定义绘图返回QSplitterHandle的子类。

答案 4 :(得分:0)

使用要将句柄添加到的QSplitter调用splitter_handles {}:

#include "splitter_handles.h"
...
QSplitter spl {};
... // widgets added to 'spl'
plitter_handles {spl}; // adding handles
...

结果:

enter image description here

splitter_handles.h

#ifndef SPLITTER_HANDLES_H
#define SPLITTER_HANDLES_H

#include <QLayout>
#include <QPainter>
#include <QSplitter>

class handle : public QWidget
{
    Q_OBJECT

protected:
    void paintEvent(QPaintEvent *e) {
        Q_UNUSED(e);
        QPainter painter {this};
        painter.setPen(Qt::NoPen);
        painter.setBrush(Qt::Dense4Pattern);
        painter.drawRect(this->rect());
    }
};

class splitter_handles {
public:
    splitter_handles(QSplitter * spl) {
        const int width {7};
        spl->setHandleWidth(width);
        for(int h_idx {1}; h_idx < spl->count(); h_idx++) {
            auto l_handle {new handle {}};
            l_handle->setMaximumSize(width*2, width*2);

            auto layout {new QHBoxLayout {spl->handle(h_idx)}};
            layout->setSpacing(0);
            layout->setMargin(1);
            layout->addWidget(l_handle);
        }
    }
};

#endif // SPLITTER_HANDLES_H

main.c

#include <QApplication>
#include <QGroupBox>
#include <QLayout>
#include <QSplitter>

#include "splitter_handles.h"

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

    auto spl_v {new QSplitter {Qt::Vertical}};
    spl_v->addWidget(new QGroupBox {"box 1"});
    spl_v->addWidget(new QGroupBox {"box 2"});
    spl_v->addWidget(new QGroupBox {"box 3"});
    splitter_handles {spl_v}; // set handles

    auto wdg  {new QWidget {}};
    auto v_lt {new QVBoxLayout {wdg}};
    v_lt->addWidget(spl_v);
    v_lt->setMargin(0);

    auto spl_h {new QSplitter {}};
    spl_h->addWidget(wdg);
    spl_h->addWidget(new QGroupBox {"box 4"});
    spl_h->addWidget(new QGroupBox {"box 5"});
    splitter_handles {spl_h};

    auto h_lt {new QHBoxLayout {}};
    h_lt->addWidget(spl_h);

    QWidget w {};
    w.setLayout(h_lt);
    w.setGeometry(100,100,500,300);
    w.show();

    return a.exec();
}

答案 5 :(得分:0)

这是使拆分器可见的最有用的Python实现。 该代码的灵感来自@francek的c ++实现。 enter image description here

from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
import sys

class Handle(QWidget):
    def paintEvent(self, e=None):
        painter = QPainter(self)
        painter.setPen(Qt.NoPen)
        painter.setBrush(Qt.Dense6Pattern)
        painter.drawRect(self.rect())

class customSplitter(QSplitter):
    def addWidget(self, wdg):
        super().addWidget(wdg)
        self.width = self.handleWidth()
        l_handle = Handle()
        l_handle.setMaximumSize(self.width*2, self.width*10)
        layout = QHBoxLayout(self.handle(self.count()-1))
        layout.setSpacing(0)
        layout.setContentsMargins(0,0,0,0)
        layout.addWidget(l_handle)

class Window(QMainWindow):
    def setUI(self, MainWindow):
        self.splt_v = customSplitter(Qt.Vertical)
        self.splt_v.setHandleWidth(8)
        self.splt_v.addWidget(QGroupBox("Box 1"))
        self.splt_v.addWidget(QGroupBox("Box 2"))
        self.splt_v.addWidget(QGroupBox("Box 3"))

        self.wdg = QWidget()
        self.v_lt = QVBoxLayout(self.wdg)
        self.v_lt.addWidget(self.splt_v)

        self.spl_h = customSplitter()
        self.spl_h.addWidget(self.wdg)
        self.spl_h.addWidget(QGroupBox("Box 4"))
        self.spl_h.addWidget(QGroupBox("Box 5"))

        self.h_lt = QHBoxLayout()
        self.h_lt.addWidget(self.spl_h)
        self.w = QWidget()
        self.w.setLayout(self.h_lt)
        self.w.setGeometry(0,0,1280,720)
        self.w.show()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    MainWindow = QMainWindow()
    ui = Window()
    ui.setUI(MainWindow)
    sys.exit(app.exec_())

答案 6 :(得分:-1)

感谢Merula的回答......我尝试了这个,现在我的分离器是可见的,看起来很漂亮而不会看起来很突兀。此代码适用于使用PyQt或PySide的Python。

app = QtGui.QApplication(sys.argv)
app.setStyle("Plastique")   # set style (using this style shows splitters! :)