【问题标题】:QSplitter becoming undistinguishable between QWidget and QTabWidgetQSplitter 在 QWidget 和 QTabWidget 之间变得无法区分
【发布时间】:2011-02-02 11:40:51
【问题描述】:

我将 QWidget 和 QTabWidget 并排放置在一个水平分离器中。并且分离器失去了它的形状,你可以通过将鼠标悬停在它上来知道有一个分离器。如何让它可见?

谢谢。

【问题讨论】:

    标签: c++ qt qt4 qtabwidget qsplitter


    【解决方案1】:

    至少对于 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 样式表的信息

    【讨论】:

    • 谢谢。这会改变颜色,但我想改变分离器浮雕。这可能吗?
    • windows下splitter的默认行为是绘制背景色。当拆分的组件默认也具有 bg-color (QWidget) 时,这很糟糕。 windows的方式是给它们一个不同的颜色和/或一个下沉的边框(QFrame支持边框)。如果您想使用浮雕,则必须更改样式(忘记样式表)。使用 setStyle() 更改样式。支持救济,例如通过 QPlastiqueStyle。您可以将 setStyle() 应用于 QApplication 对象或仅应用于拆分器(不是首选)。我会建议首先提到的原生解决方案。
    • 您可以覆盖 QSplitter::createHandle() 以使用自定义绘图返回句柄
    【解决方案2】:

    由于 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 选择另一种样式,或者使用完全不同的东西作为您添加到拆分器句柄的小部件。

    【讨论】:

    • 这太棒了。我只想补充一点,我更喜欢 QHBoxLayout,因为这样我就可以将maximumWidth(用于水平分割器)分配给水平线。
    • 赞成,因为它确实有效,但对于 Qt 错误来说,它真的感觉像是一个笨拙的解决方法......
    【解决方案3】:

    我基于上面的代码,但它处理两个分离器方向。 我只是更喜欢不透明的调整大小和不可折叠的孩子。 握把由三个平行线组成。您可以使用手柄宽度,但在 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();
        }
    }
    

    【讨论】:

    • 即使使用 Qt5.6 也可能是这里最好的解决方案。谢谢!
    • 必须设置 gripWidth = 2 才能看到把手(Win7 Classic 外观)。否则,对于应该在 Qt 几年前解决的问题,这是一个不错的解决方案。
    【解决方案4】:

    您可以继承 QSplitter 并覆盖它的 protected virtual QSplitterHandle * QSplitter::createHandle() 以返回任何让您开心的东西。

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

    【讨论】:

      【解决方案5】:

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

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

      【讨论】:

      • 这是什么语言?这看起来不像 c++
      • oops.. 抱歉,这是使用 pyqt 或 pyside 的 python
      【解决方案6】:

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

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

      结果:

      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();
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-01-12
        相关资源
        最近更新 更多