在Qt经常会用到分割器QSplitter,可以对多个控件进行水平或者垂直分割,但有一些特殊的需求无法满足,比如:四方分割。。。QuadSplitter是qt-apps里面的一个应用,挺不错的,拿来和大家分享一下,下载地址: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#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错误: 程序数据库管理器不匹配 请检查安装

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

随机推荐

  1. 微软开源PowerShell并支持Linux和OS X

    [微软在开源的道路上加速度了] 从一开始的各种对抗,各种通吃,到现在开始做服务,包罗万象.果然,换了主力,大有不同. 微软今天还宣布开源其.NET框架,令.NET Core能在Linux和OS X上运 ...

  2. 函数call相关[ASM]

    前言:   __cdecl:C/C++函数默认调用约定,参数依次从右向左传递,并压入堆栈,最后由调用函数清空堆栈,这种方式适用于传递参数个数可变的被调用函数,只有被调用函数才知道它传递了多少个参数给被 ...

  3. Joomla 3.x. How to edit registration page

    Adding registration form fields In order to add new fields to the registration form, database and fi ...

  4. CoreData Multiple Context性能分析-读书笔记

    From: http://floriankugler.com/blog/2013/4/29/concurrent-core-data-stack-performance-shootout  http: ...

  5. 编程:C#调用Python模块

    当下,C#与Python都是比较热门的计算机编程语言,他们各有优缺点,如果能让他们互相配合工作,那是多么美好的事情,今天我来讲解一下如何利用C#来调用Python. 如果让C#支持调用Python模块 ...

  6. hdu5035:概率论推公式

    题目大意: 你要去邮局发一个包裹,有n个窗口,每个都有人,每一个窗口完成一次服务的时间 ti 的分布符合几何分布:ki*e^(-ki*t) 每个窗口当前服务已经进行了ci时间 你会去第一个完成当前服务 ...

  7. pyqt托盘例子

    # -*- coding: cp936 -*- #!/usr/bin/env python # -*- coding:utf-8 -*- from PyQt4 import QtCore, QtGui ...

  8. 自定义checkbox样式

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  9. 利用Excel批量高速发送电子邮件

    利用Excel批量高速发送电子邮件,分两步: 1. 准备待发送的数据: a.) 打开Excel,新建Book1.xlsx b.) 填入以下的内容, 第一列:接收人,第二列:邮件标题,第三列:正文,第四 ...

  10. Android ActionBar详解(三):ActionBar实现切换Tabs标签

    实现切换Tabs标签; Activity代码: public class ActionBarTabs extends Activity { @Override protected void onCre ...