代码:
#include <QWidget>
class SplitterWithButton : public QWidget
{
Q_OBJECT
public:
SplitterWithButton(Qt::Orientation orientation,QWidget *parent = nullptr);
void addWidget(QWidget *widget);
protected:
void mouseMoveEvent(QMouseEvent *event)override;
private:
enum class buttonPos
{
left,
right,
top,
bottom
};
QList<QWidget *> widgetList;
class QToolButton * btn;
class QSplitter * splitter;
void setButtonStyle(buttonPos pos);
void onBtnClicked();
buttonPos btnPos;
int processWidgetIndex{-1};
};
#include <QMouseEvent>
#include <QHBoxLayout>
#include <QSplitter>
#include <QToolButton>
SplitterWithButton::SplitterWithButton(Qt::Orientation orientation, QWidget *parent)
: QWidget(parent)
{
splitter = new QSplitter(orientation,this);
splitter->setHandleWidth(5);
splitter->setStyleSheet("QSplitter::handle{background-color:#00beac;}");
splitter->setMouseTracking(true);
setMouseTracking(true);
btn = new QToolButton(this);
btn->setCursor(Qt::PointingHandCursor);
btn->setFocusPolicy(Qt::NoFocus);
btn->hide();
btn->setStyleSheet("border:none;");
connect(btn,&QToolButton::clicked,this,&SplitterWithButton::onBtnClicked);
auto hb = new QHBoxLayout;
hb->setMargin(0);
hb->addWidget(splitter);
setLayout(hb);
}
void SplitterWithButton::onBtnClicked()
{
if(processWidgetIndex != -1)
{
auto list = splitter->sizes();
btn->hide();
switch (btnPos)
{
case buttonPos::left:
{
auto sum = list[processWidgetIndex] + list[processWidgetIndex - 1];
auto size = widgetList[processWidgetIndex - 1]->minimumSizeHint();
list[processWidgetIndex] = sum - size.width();
list[processWidgetIndex - 1] = size.width();
}break;
case buttonPos::right:
{
auto sum = list[processWidgetIndex] + list[processWidgetIndex + 1];
auto size = widgetList[processWidgetIndex + 1]->minimumSizeHint();
list[processWidgetIndex] = sum - size.width();
list[processWidgetIndex + 1] = size.width();
}break;
case buttonPos::top:
{
auto sum = list[processWidgetIndex] + list[processWidgetIndex - 1];
auto size = widgetList[processWidgetIndex - 1]->minimumSizeHint();
list[processWidgetIndex] = sum - size.height();
list[processWidgetIndex - 1] = size.height();
}break;
case buttonPos::bottom:
{
auto sum = list[processWidgetIndex] + list[processWidgetIndex + 1];
auto size = widgetList[processWidgetIndex + 1]->minimumSizeHint();
list[processWidgetIndex] = sum - size.height();
list[processWidgetIndex + 1] = size.height();
}break;
}
splitter->setSizes(list);
}
}
void SplitterWithButton::setButtonStyle(buttonPos pos)
{
switch (pos)
{
case buttonPos::left:
{
btn->setFixedSize(13,42);
btn->setIcon(QIcon(":/img/right.png"));
}break;
case buttonPos::right:
{
btn->setFixedSize(13,42);
btn->setIcon(QIcon(":/img/left.png"));
}break;
case buttonPos::top:
{
btn->setFixedSize(42,13);
btn->setIcon(QIcon(":/img/bottom.png"));
}break;
case buttonPos::bottom:
{
btn->setFixedSize(42,13);
btn->setIcon(QIcon(":/img/top.png"));
}break;
}
btn->setIconSize(btn->size());
btnPos = pos;
}
void SplitterWithButton::addWidget(QWidget *widget)
{
widgetList << widget;
widget->setMouseTracking(true);
splitter->addWidget(widget);
}
void SplitterWithButton::mouseMoveEvent(QMouseEvent *event)
{
auto p = event->pos();
auto size = widgetList.size();
for(int i = 0;i < size;++i)
{
auto & w = widgetList[i];
QRect rect = w->frameGeometry();
if (rect.contains(p))
{
if(splitter->orientation() == Qt::Horizontal)
{
QRect leftCenterRect = QRect(rect.x(),(rect.height() - 42)/2,13,42);
QRect rightCenterRect = QRect(rect.x() + rect.width() - 13,(rect.height() - 42)/2,13,42);
if(leftCenterRect.contains(p))//上一个是否符合条件,若不符合则不显示按钮
{
if(i > 0)
{
if(widgetList[i - 1]->width() < 5)
{
setButtonStyle(buttonPos::left);
btn->move(leftCenterRect.topLeft());
btn->show();
processWidgetIndex = i;
}
else
{
btn->hide();
processWidgetIndex = -1;
}
}
else
{
processWidgetIndex = -1;
}
}
else if(rightCenterRect.contains(p))//下一个是否符合条件,若不符合则不显示按钮
{
if(i != (size - 1))
{
if(widgetList[i + 1]->width() < 5)
{
setButtonStyle(buttonPos::right);
btn->move(rightCenterRect.topLeft());
btn->show();
processWidgetIndex = i;
}
else
{
btn->hide();
processWidgetIndex = -1;
}
}
else
{
processWidgetIndex = -1;
}
}
else
{
btn->hide();
}
}
else
{
QRect topCenterRect = QRect((rect.width() - 42)/2,rect.y(),42,13);
QRect bottomCenterRect = QRect((rect.width() - 42)/2,rect.y() + rect.height() - 13,42,13);
if(topCenterRect.contains(p))//上一个是否符合条件,若不符合则不显示按钮
{
if(i > 0)
{
if(widgetList[i - 1]->height() < 5)
{
setButtonStyle(buttonPos::top);
btn->move(topCenterRect.topLeft());
btn->show();
processWidgetIndex = i;
}
else
{
btn->hide();
processWidgetIndex = -1;
}
}
else
{
processWidgetIndex = -1;
}
}
else if(bottomCenterRect.contains(p))//下一个是否符合条件,若不符合则不显示按钮
{
if(i != (size - 1))
{
if(widgetList[i + 1]->height() < 5)
{
setButtonStyle(buttonPos::bottom);
btn->move(bottomCenterRect.topLeft());
btn->show();
processWidgetIndex = i;
}
else
{
btn->hide();
processWidgetIndex = -1;
}
}
else
{
processWidgetIndex = -1;
}
}
else
{
btn->hide();
}
}
break;
}
}
QWidget::mouseMoveEvent(event);
}
使用:
SplitterWithButton w(Qt::Horizontal);
w.addWidget(new QLabel("哈哈哈"));
w.addWidget(new QLabel("呵呵呵"));
w.addWidget(new QLabel("啦啦啦"));
w.resize(800,600);
w.show();
可设置水平/垂直方向。
当分割的一部分隐藏时会在边缘显示按钮,点击按钮则显示:
垂直方向:
用到的图片: