QT6 源(45):分隔条 QSplitter 允许程序的用户修改布局,程序员使用 IDE时,就是分隔条的用户,以及其 QSplitter 源代码
(1)
(2)本类的继承关系如下,所以说分隔条属于容器:
(3)本类的属性:
(4) 这是一份 QSplitter 的举例代码,注意其构造函数时候的传参:
#ifndef UI_WIDGET_H
#define UI_WIDGET_H#include <QtCore/QVariant>
#include <QtWidgets/QApplication>
#include <QtWidgets/QFrame>
#include <QtWidgets/QHBoxLayout>
#include <QtWidgets/QSplitter>
#include <QtWidgets/QWidget>QT_BEGIN_NAMESPACEclass Ui_Widget
{
public:QHBoxLayout * horizontalLayout;QSplitter * splitter;QFrame * frame;QFrame * frame_2;void setupUi(QWidget *Widget){if (Widget->objectName().isEmpty())Widget->setObjectName(QString::fromUtf8("Widget"));Widget->resize(523, 339);horizontalLayout = new QHBoxLayout(Widget); //为主窗体采用水平布局horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout"));splitter = new QSplitter(Widget); //对,生成的是水平分隔条。本分割条属于本窗体容器。splitter->setObjectName(QString::fromUtf8("splitter"));splitter->setOrientation(Qt::Horizontal);frame = new QFrame(splitter);frame->setObjectName(QString::fromUtf8("frame"));frame->setFrameShape(QFrame::StyledPanel);frame->setFrameShadow(QFrame::Plain);frame->setLineWidth(2);splitter->addWidget(frame); //把左 frame 添加入 splitter//继承关系上, splitter 才扩充了添加窗体的方法frame_2 = new QFrame(splitter);frame_2->setObjectName(QString::fromUtf8("frame_2"));frame_2->setFrameShape(QFrame::StyledPanel);frame_2->setFrameShadow(QFrame::Plain);frame_2->setLineWidth(2);splitter->addWidget(frame_2); //把右 frame 添加入 splitterhorizontalLayout->addWidget(splitter); //把分隔条 splitter 添加到主窗体的布局中//可见,分隔条相当于容器,隐身的容器;也相当于布局,可以接收子容器,还可以被放入布局中retranslateUi(Widget);QMetaObject::connectSlotsByName(Widget);} // setupUivoid retranslateUi(QWidget *Widget){Widget->setWindowTitle(QCoreApplication::translate("Widget", "Widget", nullptr));} // retranslateUi};namespace Ui {class Widget: public Ui_Widget {};
} // namespace UiQT_END_NAMESPACE#endif // UI_WIDGET_H
(5)给出源代码,来自于头文件 qsplitter . h :
#ifndef QSPLITTER_H
#define QSPLITTER_H#include <QtWidgets/qtwidgetsglobal.h>
#include <QtWidgets/qframe.h>
#include <QtWidgets/qsizepolicy.h>/*
QT_CONFIG宏实现了对 Qt特性的安全编译时检查。特性可以处于三种状态:
0 或未定义:在测试时会引发编译错误
-1:该功能不可用
1:该功能可用The QT_CONFIG macro implements a safe compile time check for features of Qt.Features can be in three states:0 or undefined: This will lead to a compile error when testing for it-1: The feature is not available1: The feature is available
*/
#define QT_CONFIG(feature) (1/QT_FEATURE_##feature == 1)#define QT_REQUIRE_CONFIG(feature) Q_STATIC_ASSERT_X(QT_FEATURE_##feature == 1,\"Required feature " #feature " for file " __FILE__ " not available.")QT_REQUIRE_CONFIG(splitter); //条件编译,确保有了此源代码模块QT_BEGIN_NAMESPACE //说明本类定义在 QT 的全局空间class QSplitterPrivate;
class QTextStream;class QSplitterHandle;// class QLayout : public QObject, public QLayoutIte
// class QWidget : public QObject, public QPaintDevice
//class QFrame : public QWidget
//一个分割器允许用户通过拖动它们之间的边界来控制子控件的大小。
//任何数量的控件都可以由一个单一的分割器控制。
//如果在调用 insertWidget()或addWidget()时,一个部件已经在 QSplitter中,
//它将移动到新位置。这可以用于稍后重新排序 splitter中的部件。
//可以使用indexOf()、widget()和count()来访问splitter 中的部件。
//默认的QSplitter将其子元素水平排列(并排);
//您可以使用setOrientation(Qt::Vertical)将其子元素垂直排列。
//默认情况下,所有小部件都可以像用户希望的那样大或小,
//介于小部件的minimumSizeHint()(或minimumSize())和maximumSize()之间。
//默认情况下,QSplitter会动态调整其子项的大小。
//如果您希望QSplitter仅在调整大小操作结束时调整子项的大小,请调用setOpaqueResize(false)。
//小部件之间初始大小的分布是通过将初始大小与拉伸因子相乘来确定的。
//您还可以使用setSizes()来设置所有小部件的大小。函数sizes()返回由用户设置的大小。
//或者,您可以使用saveState()和restoreState()分别保存和恢复小部件的大小。
//当你隐藏(hide)一个子元素时,它的空间将被分配到其他子元素中。当你再次显示(show)它时,它将被恢复。
class Q_WIDGETS_EXPORT QSplitter : public QFrame
{Q_OBJECT //又插入了此宏//此属性保存了分割器的方向.//默认情况下,方向是水平(即小部件是并排排列的)。可能的方向是Qt::Horizontal和Qt::Vertical。Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation)//如果分隔条在交互式移动时动态(不透明)地重新调整大小,则返回true。否则返回 false。//默认的缩放行为取决于样式(由SH_Splitter_OpaqueResize样式提示确定)。//但是,您可以通过调用setOpaqueResize()来覆盖它。Q_PROPERTY(bool opaqueResize READ opaqueResize WRITE setOpaqueResize)//不透明//此属性包含分隔符手柄的宽度。即被分隔条隔开的内部各控件之间的间距。//默认情况下,此属性包含一个值,该值取决于用户的平台和样式偏好。//如果您将 handleWidth 设置为1或0,则实际抓取区域将增长到与其各自的小部件重叠几个像素Q_PROPERTY(int handleWidth READ handleWidth WRITE setHandleWidth)//这个属性表示子控件是否可以被用户缩小到0的大小。默认情况下,子元素是可折叠的。//使用setCollapsible()方法可以启用或禁用单个子元素的折叠。Q_PROPERTY(bool childrenCollapsible //倒塌;垮塌;可折叠 collapseREAD childrenCollapsible WRITE setChildrenCollapsible)private:Q_DISABLE_COPY(QSplitter)Q_DECLARE_PRIVATE(QSplitter)
private:friend class QSplitterHandle;public://构造一个水平分割器,将 parent参数传递给 QFrame构造函数。explicit QSplitter(QWidget * parent = nullptr); //本组件属于 parent容器explicit QSplitter(Qt::Orientation, QWidget * parent = nullptr);//Constructs a splitter with the given orientation and parent.~QSplitter();//Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation)Qt::Orientation orientation() const;void setOrientation(Qt::Orientation); //方向就是水平或垂直两种//Q_PROPERTY(bool opaqueResize READ opaqueResize WRITE setOpaqueResize)bool opaqueResize() const;void setOpaqueResize(bool opaque = true);//Q_PROPERTY(int handleWidth READ handleWidth WRITE setHandleWidth)int handleWidth() const;void setHandleWidth(int);//Q_PROPERTY(bool childrenCollapsible
// READ childrenCollapsible WRITE setChildrenCollapsible)bool childrenCollapsible() const;void setChildrenCollapsible(bool);//Returns true if the widget at index is collapsible, otherwise returns false.bool isCollapsible(int index) const;void setCollapsible(int index, bool);//Sets whether the child widget at index is collapsible to collapse.//默认情况下,子项是可折叠的,这意味着用户可以将它们的大小缩小到大小0,//即使它们具有非零的minimumSize()或minimumSizeHint()。//可以通过调用此函数在每个 widget的基础上更改此行为,//也可以通过设置 childrencollapsible 属性为拆分器中的所有 widget 全局更改此行为。//返回此拆分器中所有小部件的大小参数的列表。//如果拆分器的方向是水平,则列表包含从左到右的像素宽度;//如果方向是垂直的,则列表包含从顶部到底部的像素高度。//将值传递给另一个分块器的 setSizes()函数将产生一个布局与此相同的分块器。QList<int> sizes() const; //本函数的返回值是一个链表容器void setSizes(const QList<int> &list);//将子控件的相应大小设置为列表中给出的值。//如果分隔线是水平的,则值以像素为单位设置每个小部件的宽度,从左到右。//如果分隔线是垂直的则设置每个小部件的高度,从上到下。//列表中的额外值将被忽略。如果列表包含太少的值,结果是不确定的,但程序仍然会表现得很好。//分割器组件的整体大小不受影响。相反,任何额外的/缺失的空间将根据尺寸的相对权重在组件之间分配。//如果您指定大小为0,则小部件将不可见。//小部件的大小策略将被保留。也就是说小于相应小部件的最小大小提示值的值将被提示值替换。//保存分割器的布局状态。//通常,这用于与QSettings一起使用,以记住未来会话的大小。版本号作为数据的一部分存储。QByteArray saveState() const;bool restoreState(const QByteArray &state);//Restores the splitter's layout to the state specified.//Returns true if the state is restored; otherwise returns false.QSize sizeHint() const override;QSize minimumSizeHint() const override;//Returns the valid range of the splitter at index in *min and *max//if min and max are not 0.void getRange(int index, int *min, int *max) const;//Returns the number of widgets contained in the splitter's layout.int count() const;int indexOf(QWidget *w) const;QWidget * widget(int index) const; //!!扩充了添加窗体的方法,就类似于 Qlayout了void addWidget(QWidget *widget);void insertWidget(int index, QWidget *widget);QWidget * replaceWidget(int index, QWidget *widget);void refresh(); //不要调用本函数//Updates the splitter's state. You should not need to call this function.//Updates the size policy of the widget at position index to//have a stretch factor of stretch.//stretch 并不是有效的拉伸因子;有效的拉伸因子是通过取小部件的初始大小并//将其乘以 stretch 计算得出的 。void setStretchFactor(int index, int stretch);//返回分割器布局中给定索引处左侧(或上方)的项的句柄,//如果不存在这样的项则返回nullptr。索引为0的句柄总是隐藏的。//对于像阿拉伯语和希伯来语这样的右至左语言,水平分隔符的布局是颠倒的。在索引处的控件右侧是手柄。QSplitterHandle * handle(int index) const;
protected:virtual QSplitterHandle * createHandle();//返回一个新的分隔符处理程序作为此分隔符的子控件。//此函数可以在子类中重新实现,以提供对自定义处理程序的支持。bool event(QEvent *) override;void childEvent(QChildEvent *) override;void resizeEvent(QResizeEvent *) override;void changeEvent(QEvent *) override;//在位置 pos 显示橡皮筋 RubberBand。如果 pos是负数,则移除皮筋。void setRubberBand(int position);int closestLegalPosition(int pos, int index);//Returns the closest legal position to pos of the widget at index.//对于阿拉伯语和希伯来语等从右向左的语言,水平分隔符的布局//是颠倒的。然后从小部件的右边缘测量位置。//将分割器手柄的左边缘或顶部边缘在索引 index 处移动到尽可能靠近位置pos的位置,//位置pos是从小部件的左边缘或顶部边缘的距离。void moveSplitter(int pos, int index);Q_SIGNALS: //信号函数void splitterMoved(int pos, int index);//当 index 索引处的分路器手柄移动到位置 pos 时,会发出此信号。
}; //完结 class QSplitter : public QFrameclass QSplitterHandlePrivate;//当人们想到分割器时,通常会想到QSplitterHandle。它是用于调整部件大小的控制柄。
//使用 QSplitter的典型开发人员永远不必担心 QSplitterHandle。
//它提供给那些想要提供额外功能(如弹出菜单)的分割器处理程序的开发人员。
//创建分割器处理程序的典型方法是子类化QSplitter,然后重写QSplitter::createHandle()以
//实例化自定义分割器处理程序。
class Q_WIDGETS_EXPORT QSplitterHandle : public QWidget
{Q_OBJECT
public:explicit QSplitterHandle(Qt::Orientation o, QSplitter *parent);~QSplitterHandle();void setOrientation(Qt::Orientation o);Qt::Orientation orientation() const;bool opaqueResize() const;QSplitter *splitter() const;QSize sizeHint() const override;protected:void paintEvent(QPaintEvent *) override;void mouseMoveEvent(QMouseEvent *) override;void mousePressEvent(QMouseEvent *) override;void mouseReleaseEvent(QMouseEvent *) override;void resizeEvent(QResizeEvent *) override;bool event(QEvent *) override;void moveSplitter(int p);int closestLegalPosition(int p);private:Q_DISABLE_COPY(QSplitterHandle)Q_DECLARE_PRIVATE(QSplitterHandle)
};QT_END_NAMESPACE#endif // QSPLITTER_H
(6)
谢谢