Qt 笔记6--Qt 窗体区域拉伸移动

很多时候,一个窗体中各子区域的大小需要动态调整,如Qt Creator主界面的项目区、类视图去、编码区、应用程序输出区等,它们之间大小调整一般通过拖动边界区域来实现的。以下为笔者通过重写mouseMoveEvent、mousePressEvent、mouseReleaseEvent等方法实现的一个简单区域拉伸移动案例,相应学习笔记贴在此处以便于后续参考。

 

1、功能介绍

以下两张图分别为Qt Creator中左右和上下区域拉伸移动的效果,本文主要为了达到类似的效果。笔者通过重写widget中的mouseMoveEvent、mousePressEvent、mouseReleaseEvent方法,根据其鼠标位置变化来确定是否更改区域的大小,从而达到区域拉伸移动的效果。

图1 左右拉伸移动

Qt 笔记6--Qt 窗体区域拉伸移动_区域拉伸移动

图2 上下拉伸移动

Qt 笔记6--Qt 窗体区域拉伸移动_Qt拉伸窗区域拉伸移动_02

 

2、源代码

该方法比较简单,笔者使用第一行区域的下边界和第二行一列区域的右边界为触发边界,触发区间为[-5,5],代码主要包括三个源文件:widget.h、widget.cpp和main.cpp,具体源码如下:

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QDebug>
#include <QKeyEvent>

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
Q_OBJECT

public:
explicit Widget(QWidget *parent = 0);
~Widget();

protected:

virtual void mouseMoveEvent(QMouseEvent *event) override;
virtual void mousePressEvent(QMouseEvent *event) override;
virtual void mouseReleaseEvent(QMouseEvent *event) override;
virtual void resizeEvent(QResizeEvent *event) override;

private:
Ui::Widget *ui;
int mousePosX;//记录有效位置的X
int mousePosY;//记录有效位置的Y
bool mouseFlagX = false;//记录是否可以进行左右移动
bool mouseFlagY = false;//记录是否可以开始上下移动
};

#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
}

Widget::~Widget()
{
delete ui;
}

void Widget::mouseMoveEvent(QMouseEvent *event)
{
if(mouseFlagX){
//qDebug().noquote()<<"Moving X:"<<event->x();
int xChanged = event->x()-mousePosX;
ui->widget_2->resize(ui->widget_2->geometry().width()+xChanged,ui->widget_2->geometry().height());
ui->widget_3->setGeometry(ui->widget_3->geometry().x()+xChanged,ui->widget_2->geometry().y(),ui->widget_3->geometry().width()-xChanged,ui->widget_3->geometry().height());
mousePosX = event->x();
}
if(mouseFlagY){
//qDebug().noquote()<<"Moving Y:"<<event->y();
int yChanged = event->y()-mousePosY;
ui->widget_1->resize(ui->widget_1->geometry().width(),ui->widget_1->geometry().height()+yChanged);
ui->widget_2->setGeometry(ui->widget_2->geometry().x(),ui->widget_2->geometry().y()+yChanged,ui->widget_2->geometry().width(),ui->widget_2->geometry().height()-yChanged);
ui->widget_3->setGeometry(ui->widget_3->geometry().x(),ui->widget_3->geometry().y()+yChanged,ui->widget_3->geometry().width(),ui->widget_3->geometry().height()-yChanged);
mousePosY = event->y();
}
}

void Widget::mousePressEvent(QMouseEvent *event)
{
//qDebug().noquote()<<"mousePressEvent";
if(event->y()<=(ui->widget_1->geometry().height()+5) && event->y()>=(ui->widget_1->geometry().height()-5))
{
mousePosY = event->y();
mouseFlagY = true;
}
if(event->x()<=(ui->widget_2->geometry().width()+5) && event->x()>=(ui->widget_2->geometry().width()-5))
{
mousePosX = event->x();
mouseFlagX = true;
}
}

void Widget::mouseReleaseEvent(QMouseEvent *event)
{
//qDebug().noquote()<<"mouseReleaseEvent";
mouseFlagX = false;
mouseFlagY = false;
}

void Widget::resizeEvent(QResizeEvent *event)
{
QSize qsize = this->size();
ui->widget_1->resize(qsize.width(),ui->widget_1->height());
ui->widget_2->resize(ui->widget_2->width(),qsize.height()-ui->widget_1->height()-2);
ui->widget_3->resize(qsize.width() - ui->widget_2->width()+2,qsize.height()-ui->widget_1->height()-2);
}

main.cpp

#include "widget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();

return a.exec();
}

3、测试结果

如下gif图片所示,触发区间为第一行区域下边界和第二行第一列的右边界;此处只提供了一种触发方法,也可以根据需要自定义其它类型的触发效果。

Qt 笔记6--Qt 窗体区域拉伸移动_mouseReleaseEvent_03

4、说明

以上代码默认测试环境为Qt 5.7,测试系统为Windows7 x64