Qt之四方分割器QuadSplitter

时间:2021-12-26 21:08:18

在Qt经常会用到分割器QSplitter,可以对多个控件进行水平或者垂直分割,但有一些特殊的需求无法满足,比如:四方分割。。。QuadSplitter是qt-apps里面的一个应用,挺不错的,拿来和大家分享一下,下载地址:QuadSplitter

 
效果如下:
Qt之四方分割器QuadSplitter
 Qt之四方分割器QuadSplitter
 
#ifndef QUADSPLITTER_H
#define QUADSPLITTER_H #include class QuadSplitterPrivate; class QuadSplitter : public QFrame
{
Q_OBJECT
public:
QuadSplitter(QWidget *parent);
~QuadSplitter(); void addWidget(QWidget *, int row, int column); int spacing() const;
void setSpacing(int spacing); int splittersSpacing() const;
void setSplittersSpacing(int spacing); int centerPartWidth() const;
void setCenterPartWidth(int value); int minimumWidgetSize() const;
void setMinimumWidgetSize(int value);
protected:
void resizeEvent(QResizeEvent *);
private:
QuadSplitterPrivate * const d_ptr;
Q_DISABLE_COPY(QuadSplitter)
Q_DECLARE_PRIVATE(QuadSplitter);
friend class AdvSplitter;
}; #endif // QUADSPLITTER_H #include "quadsplitter.h"
#include
#include
#include
#include
#include
#include class AdvSplitter; class QuadSplitterPrivate : public QObject
{
Q_DECLARE_PUBLIC(QuadSplitter);
public:
QuadSplitterPrivate(QuadSplitter* _q_ptr);
void addWidget(QWidget *widget, int row, int column);
void splitterMoveStart(AdvSplitter* splitter, bool center);
void splitterMove(AdvSplitter* splitter, QPoint const& offset, bool center);
void arrange();
qreal realPercent(Qt::Orientation orientation) const; int spacing() const;
void setSpacing(int spacing); int splittersSpacing() const;
void setSplittersSpacing(int spacing); int centerPartWidth() const;
void setCenterPartWidth(int value); int minimumWidgetSize() const;
void setMinimumWidgetSize(int value);
private:
QuadSplitter *q_ptr; QScopedPointer _horizontalSplitter;
QScopedPointer _verticalSplitter; QPointer _grid[][];
int _spacing;
int _splittersSpacing;
QPoint _splittersMovingPos;
int _minimumWidgetSize;
int _centerPart; int realSpacing() const;
int realWidth() const;
int realHeight() const;
};
//////////////////////////////////////////////////////////////////////////
class AdvSplitter : public QWidget
{
public:
AdvSplitter(QWidget* parent, QuadSplitterPrivate* priv, Qt::Orientation orientation)
: QWidget(parent), _percent(0.5), _orientation(orientation),
_mouse(false), _center(false), _private(priv)
{
setMouseTracking(true);
if (orientation == Qt::Horizontal)
setCursor(Qt::SplitHCursor);
else if (orientation == Qt::Vertical)
setCursor(Qt::SplitVCursor);
} qreal percent() const
{
return _percent;
} void setPercent(qreal val)
{
_percent = val;
}
protected:
void paintEvent (QPaintEvent *event)
{
QStylePainter painter(this);
QStyleOption opt1, opt2;
opt1.init(this);
opt2.init(this);
opt1.state = opt2.state = QStyle::State_None;
if (_orientation == Qt::Horizontal)
{
opt1.state |= QStyle::State_Horizontal;
opt2.state |= QStyle::State_Horizontal; if (_private)
{
int hiPart = qFloor((qreal)opt1.rect.height() * _private->realPercent(Qt::Vertical) + 0.5);
int loPart = opt1.rect.height() - hiPart;
opt1.rect.setBottom(opt1.rect.top() + hiPart);
opt2.rect.setTop(opt2.rect.bottom() - loPart);
}
}
else if (_private)
{
int hiPart = qFloor((qreal)opt1.rect.width() * _private->realPercent(Qt::Horizontal) + 0.5);
int loPart = opt1.rect.width() - hiPart;
opt1.rect.setRight(opt1.rect.left() + hiPart);
opt2.rect.setLeft(opt2.rect.right() - loPart);
} painter.drawControl(QStyle::CE_Splitter, opt1);
if (_private)
painter.drawControl(QStyle::CE_Splitter, opt2);
} void mouseMoveEvent(QMouseEvent * event)
{
if (!_mouse && _private)
{
if (_orientation == Qt::Horizontal)
{
int hiPart = qFloor((qreal)height() * _private->realPercent(Qt::Vertical) + 0.5);
if (event->pos().y() > (hiPart - _private->centerPartWidth() / ) &&
event->pos().y() < (hiPart + _private->centerPartWidth() / ))
setCursor(Qt::SizeAllCursor);
else
setCursor(Qt::SplitHCursor);
}
else
{
int hiPart = qFloor((qreal)width() * _private->realPercent(Qt::Horizontal) + 0.5);
if (event->pos().x() > (hiPart - _private->centerPartWidth() / ) &&
event->pos().x() < (hiPart + _private->centerPartWidth() / ))
setCursor(Qt::SizeAllCursor);
else
setCursor(Qt::SplitVCursor);
}
}
else if (_center)
{
if (cursor().shape() != Qt::SizeAllCursor)
setCursor(Qt::SizeAllCursor);
}
else if (_orientation == Qt::Horizontal)
{
if (cursor().shape() != Qt::SplitHCursor)
setCursor(Qt::SplitHCursor);
}
else if (cursor().shape() != Qt::SplitVCursor)
setCursor(Qt::SplitVCursor); if (_mouse && (event->buttons() & Qt::LeftButton))
{
QPoint pt = mapToParent(event->pos()); if (QuadSplitter* p = qobject_cast(parent()))
p->d_ptr->splitterMove(this, pt - _mousePos, _center);
}
} void mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton)
{
_mouse = true;
if (_private)
{
if (_orientation == Qt::Horizontal)
{
int hiPart = qFloor((qreal)height() * _private->realPercent(Qt::Vertical) + 0.5);
if (event->pos().y() > (hiPart - _private->centerPartWidth() / ) &&
event->pos().y() < (hiPart + _private->centerPartWidth() / ))
{
_center = true;
setCursor(Qt::SizeAllCursor);
}
else
setCursor(Qt::SplitHCursor);
}
else
{
int hiPart = qFloor((qreal)width() * _private->realPercent(Qt::Horizontal) + 0.5);
if (event->pos().x() > (hiPart - _private->centerPartWidth() / ) &&
event->pos().x() < (hiPart + _private->centerPartWidth() / ))
{
_center = true;
setCursor(Qt::SizeAllCursor);
}
else
setCursor(Qt::SplitVCursor);
}
}
}
_mousePos = mapToParent(event->pos());
if (QuadSplitter* p = qobject_cast(parent()))
p->d_ptr->splitterMoveStart(this, _center);
} void mouseReleaseEvent(QMouseEvent *event)
{
_mouse = false;
_center = false;
}
private:
bool _mouse;
QPoint _mousePos;
Qt::Orientation _orientation;
qreal _percent;
QPointer _private;
bool _center;
};
//////////////////////////////////////////////////////////////////////////
QuadSplitterPrivate::QuadSplitterPrivate(QuadSplitter* _q_ptr)
: q_ptr(_q_ptr), _spacing(), _splittersSpacing(),
_minimumWidgetSize(), _centerPart()
{
Q_Q(QuadSplitter);
_horizontalSplitter.reset(new AdvSplitter(q, this, Qt::Horizontal));
_verticalSplitter.reset(new AdvSplitter(q, this, Qt::Vertical)); arrange();
} int QuadSplitterPrivate::realSpacing() const
{
const Q_Q(QuadSplitter);
return _spacing + q->frameWidth();
} int QuadSplitterPrivate::realWidth() const
{
const Q_Q(QuadSplitter);
return q->width() - (realSpacing() * ) - _splittersSpacing;
} int QuadSplitterPrivate::realHeight() const
{
const Q_Q(QuadSplitter);
return q->height() - (realSpacing() * ) - _splittersSpacing;
} void QuadSplitterPrivate::arrange()
{
Q_Q(QuadSplitter); QPair minMaxHorizontalSizes[] =
{QPair(, QWIDGETSIZE_MAX), QPair(, QWIDGETSIZE_MAX)}; QPair minMaxVerticalSizes[] =
{QPair(, QWIDGETSIZE_MAX), QPair(, QWIDGETSIZE_MAX)}; for (int r = ; r < ; ++r)
{
for (int c = ; c < ; ++c)
{
if (_grid[r][c] && _grid[r][c]->parent() == q)
{
minMaxHorizontalSizes[c] =
QPair(
qMax(_grid[r][c]->minimumWidth() < _minimumWidgetSize ? _minimumWidgetSize : _grid[r][c]->minimumWidth(),
minMaxHorizontalSizes[c].first),
qMin(_grid[r][c]->maximumWidth(), minMaxHorizontalSizes[c].second)); minMaxVerticalSizes[r] =
QPair(
qMax(_grid[r][c]->minimumHeight() < _minimumWidgetSize ? _minimumWidgetSize : _grid[r][c]->minimumHeight(),
minMaxVerticalSizes[r].first),
qMin(_grid[r][c]->maximumHeight(), minMaxVerticalSizes[r].second));
}
else
_grid[r][c] = nullptr;
}
} //columns
int leftColumnWidth = qFloor((qreal)realWidth() * _horizontalSplitter->percent() + 0.5);
if (leftColumnWidth < minMaxHorizontalSizes[].first)
leftColumnWidth = minMaxHorizontalSizes[].first;
if (leftColumnWidth > minMaxHorizontalSizes[].second)
leftColumnWidth = minMaxHorizontalSizes[].second; int columnWidth = leftColumnWidth; int rightColumnWidth = realWidth() - leftColumnWidth;
if (rightColumnWidth < minMaxHorizontalSizes[].first)
{
rightColumnWidth = minMaxHorizontalSizes[].first;
columnWidth = realWidth() - rightColumnWidth;
}
if (rightColumnWidth > minMaxHorizontalSizes[].second)
{
rightColumnWidth = minMaxHorizontalSizes[].second;
columnWidth = realWidth() - rightColumnWidth;
}
//rows
int topColumnHeight = qFloor((qreal)realHeight() * _verticalSplitter->percent() + 0.5);
if (topColumnHeight < minMaxVerticalSizes[].first)
topColumnHeight = minMaxVerticalSizes[].first;
if (topColumnHeight > minMaxVerticalSizes[].second)
topColumnHeight = minMaxVerticalSizes[].second; int columnHeight = topColumnHeight; int bottomColumnHeight = realHeight() - topColumnHeight;
if (bottomColumnHeight < minMaxVerticalSizes[].first)
{
bottomColumnHeight = minMaxVerticalSizes[].first;
columnHeight = realHeight() - bottomColumnHeight;
}
if (bottomColumnHeight > minMaxVerticalSizes[].second)
{
bottomColumnHeight = minMaxVerticalSizes[].second;
columnHeight = realHeight() - bottomColumnHeight;
} _horizontalSplitter->setGeometry(realSpacing() + columnWidth, realSpacing(), _splittersSpacing, q->height() - realSpacing() * );
_horizontalSplitter->raise(); _verticalSplitter->setGeometry(realSpacing(), realSpacing() + columnHeight, q->width() - realSpacing() * , _splittersSpacing);
_verticalSplitter->raise(); if (_grid[][])
_grid[][]->setGeometry(realSpacing(), realSpacing(), columnWidth, columnHeight);
if (_grid[][])
_grid[][]->setGeometry(realSpacing() + columnWidth + _splittersSpacing, realSpacing(), realWidth() - columnWidth, columnHeight); if (_grid[][])
_grid[][]->setGeometry(realSpacing(),
realSpacing() + columnHeight + _splittersSpacing, columnWidth, realHeight() - columnHeight);
if (_grid[][])
_grid[][]->setGeometry(realSpacing() + columnWidth + _splittersSpacing,
realSpacing() + columnHeight + _splittersSpacing, realWidth() - columnWidth, realHeight() - columnHeight);
} void QuadSplitterPrivate::addWidget(QWidget *widget, int row, int column)
{
Q_Q(QuadSplitter);
if (row < || column < || row > || column > ) {
qWarning("QGridLayout: Cannot add %s/%s to %s/%s at row %d column %d",
widget->metaObject()->className(), widget->objectName().toLocal8Bit().data(),
q->metaObject()->className(), q->objectName().toLocal8Bit().data(), row, column);
return;
} bool needShow = q->isVisible() &&
!(widget->isHidden() && widget->testAttribute(Qt::WA_WState_ExplicitShowHide));
if (widget->parentWidget() != q)
widget->setParent(q);
if (needShow)
widget->show(); _grid[row][column] = widget; arrange();
} void QuadSplitterPrivate::splitterMoveStart(AdvSplitter* splitter, bool center)
{
_splittersMovingPos = QPoint(_horizontalSplitter->x(), _verticalSplitter->y());
} void QuadSplitterPrivate::splitterMove(AdvSplitter* splitter, QPoint const& offset, bool center)
{
Q_Q(QuadSplitter);
if (center)
{
qreal newX = _splittersMovingPos.x() + offset.x() - realSpacing();
qreal newY = _splittersMovingPos.y() + offset.y() - realSpacing();
_horizontalSplitter->setPercent(newX / (qreal)realWidth());
_verticalSplitter->setPercent(newY / (qreal)realHeight());
}
else if (splitter == _horizontalSplitter.data())
{
qreal newX = _splittersMovingPos.x() + offset.x() - realSpacing();
splitter->setPercent(newX / (qreal)realWidth());
}
else
{
qreal newY = _splittersMovingPos.y() + offset.y() - realSpacing();
splitter->setPercent(newY / (qreal)realHeight());
}
arrange();
} int QuadSplitterPrivate::splittersSpacing() const
{
return _splittersSpacing;
} void QuadSplitterPrivate::setSplittersSpacing(int spacing)
{
_splittersSpacing = spacing;
} qreal QuadSplitterPrivate::realPercent(Qt::Orientation orientation) const
{
if (orientation == Qt::Horizontal)
{
qreal newX = _horizontalSplitter->x() - realSpacing();
return newX / realWidth();
} qreal newY = _verticalSplitter->y() - realSpacing();
return newY / realHeight();
} int QuadSplitterPrivate::spacing() const
{
return _spacing;
} void QuadSplitterPrivate::setSpacing(int spacing)
{
_spacing = spacing;
} int QuadSplitterPrivate::centerPartWidth() const
{
return _centerPart;
} void QuadSplitterPrivate::setCenterPartWidth(int value)
{
_centerPart = value;
} int QuadSplitterPrivate::minimumWidgetSize() const
{
return _minimumWidgetSize;
} void QuadSplitterPrivate::setMinimumWidgetSize(int value)
{
_minimumWidgetSize = value;
} //////////////////////////////////////////////////////////////////////////
QuadSplitter::QuadSplitter(QWidget *parent)
: QFrame(parent), d_ptr(new QuadSplitterPrivate(this))
{
} QuadSplitter::~QuadSplitter()
{
delete d_ptr;
} void QuadSplitter::addWidget(QWidget *widget, int row, int column)
{
Q_D(QuadSplitter);
d->addWidget(widget, row, column);
} void QuadSplitter::resizeEvent(QResizeEvent *event)
{
Q_D(QuadSplitter);
d->arrange();
} int QuadSplitter::spacing() const
{
const Q_D(QuadSplitter);
return d->spacing();
} void QuadSplitter::setSpacing(int spacing)
{
Q_D(QuadSplitter);
d->setSpacing(spacing);
} int QuadSplitter::splittersSpacing() const
{
const Q_D(QuadSplitter);
return d->splittersSpacing();
} void QuadSplitter::setSplittersSpacing(int spacing)
{
Q_D(QuadSplitter);
d->setSplittersSpacing(spacing);
} int QuadSplitter::centerPartWidth() const
{
const Q_D(QuadSplitter);
return d->centerPartWidth();
} void QuadSplitter::setCenterPartWidth(int value)
{
Q_D(QuadSplitter);
d->setCenterPartWidth(value);
} int QuadSplitter::minimumWidgetSize() const
{
const Q_D(QuadSplitter);
return d->minimumWidgetSize();
} void QuadSplitter::setMinimumWidgetSize(int value)
{
Q_D(QuadSplitter);
d->setMinimumWidgetSize(value);
}

使用方法:(类似于QGridLayout)

    QuadSplitter *pSplitter = new QuadSplitter(this);

    QStringList strList;
strList << "#990099" << "#99FFFF" << "#CC0099" << "#CCFF99";
for (int i = ; i < strList.count(); ++i)
{
QWidget *pWidget = new QWidget(this);
pWidget->setStyleSheet(QString("background:%1").arg(strList.at(i)));
pSplitter->addWidget(pWidget, i/, i%);
}

http://blog.sina.com.cn/s/blog_a6fb6cc90102vkr2.html

Qt之四方分割器QuadSplitter的更多相关文章

  1. Qt布局与分割器QSplitter

    Qt的布局方式主要有四种:   QGridLayout         栅格布局 QFormLayout       表格布局 QHBoxLayout       水平布局 QVBoxLayout   ...

  2. JAVA学习课第五 — IO流程(九)文件分割器合成器

    文件分割器 private static final int SIZE = 1024 *1024; public static void splitFile(File file) throws IOE ...

  3. 13 KNN背景分割器

    传统的前景背景分割方法有GrabCut,分水岭算法,当然也包括一些阈值分割的算法.但是这些算法在应用中往往显得鲁棒性较弱,达不到一个好的分割效果. 现代的背景分割算法融入了机器学习的一些方法来提高分类 ...

  4. Opencv中KNN背景分割器

    背景分割器BackgroundSubtractor是专门用来视频分析的,会对视频中的每一帧进行"学习",比较,计算阴影,排除检测图像的阴影区域,按照时间推移的方法提高运动分析的结果 ...

  5. C&num;txt文本分割器

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...

  6. QT 利用QSplitter 分割区域, 并添加QScrollArea 滚动区域,滚动条

    1. QSplitter 分割区域, 可以分割区域中可以随意添加自己的布局 2. #include "dialog.h" #include <QApplication> ...

  7. Qt之布局管理器

    简述 Qt的布局系统提供了一个简单的和强有力的方式,来自动排列窗口子控件布局. 所有QWidget子类可以使用布局来管理他们的子控件.QWidget::setLayout()函数可以为一个控件布局.当 ...

  8. Qt 简易图片播放器

    一.前言 使用 Qt 制作了一个简单的图片播放器,点击 "浏览按钮" 浏览图片所在目录,目录中的所有图片缩小图标和名称会显示在左侧的图片列表中,点击列表中的图片项,可以在右侧区域的 ...

  9. Qt错误&colon; 程序数据库管理器不匹配 请检查安装

    错误提示: C1902: 程序数据库管理器不匹配:请检查安装解决 解决方法: 到D:\VisualStudio2015\VC\bin目录下面拷贝mspdbsrv.exe.mspdb140.dll.ms ...

随机推荐

  1. zstuoj 4243 牛吃草 ——(二分&plus;两圆交)

    这题上次补了以后忘记写博客了,现在补一下. 有两个注意点,第一是两圆相交的模板.可以通过任意一种情况手推出来. 第二是,实数二分要注意不用ans记录为妙,因为可能因为eps过小,导致ans无法进入记录 ...

  2. jQuery 分步引导 插件

    转自:http://blog.libnav.com/js/57.html 很多时候一个网站或者一个Web应用出品,为了让你的用户知道你的站点(或应用)有些什么?如何操作?为了让你的用户有更好的体验.往 ...

  3. (转)Android 从底层实现让应用杀不死【失效Closed】(1)

    转自:http://klob.diandi.life/?p=21#symple-tab-%e8%b0%83%e6%9f%a5%e5%af%b9%e8%b1%a1 情景还原: 我的应用调用了Notifi ...

  4. 关于tableView刷新

    UITabelView的局部刷新 1. 刷新整个tableView用[self.tableView reloadData]; 2. [self.tableView reloadRowsAtIndexP ...

  5. WILL吃桃&lowbar;KEY

    WILL 吃桃 (peach.pas/c/cpp) [ 题目描述] Will 很喜欢吃桃, 某天 Will 来到了一片森林, 森林中有 N 颗桃树, 依次编号为 1,2,„,N.每棵树上有数量不等的桃 ...

  6. 关于Websockets问题&colon;

     Websockets是一种与服务器进行全双工,双向通信的信道,它不使用http协议,他有自己的协议即自定义协议,ws协议:它的安全协议为wss协议.这种协议专门为快速传输小数据而设计的.对服务其有一 ...

  7. 【BootStrap】 布局组件 I

    BootStrap布局组件 I 除了在原生的HTML基础上进行了外观和类别上的改进,BS还包装了很多组件进库中,设计网页时我们可以方便地调用这些组件.下面来简略地介绍一下各种各样的组件 ■ 字体图标 ...

  8. 当配置 DispatcherServlet拦截&OpenCurlyDoubleQuote;&sol;”,SpringMVC访问静态资源的三种方式

    如何你的DispatcherServlet拦截 *.do这样的URL,就不存在访问不到静态资源的问题.如果你的DispatcherServlet拦截“/”,拦截了所有的请求,同时对*.js,*.jpg ...

  9. MySQL RPM二进制安装

    +++++++++++++++++++++++++++++++++++++++++++标题:MySQL RPM二进制安装时间:2019年2月24日内容:MySQL RPM二进制安装重点:MySQL R ...

  10. MyLog

    using System;using System.Collections.Generic;using System.IO;using System.Linq;using System.Text;us ...