Qt graphicsView里面实现Widget 可自由移动和拉伸

实现的效果:如下图:主要是紫色的方块能在graphicsView里面自由移动  + 紫色方块能自由拉伸(整个代码复制过去就可以用了)

 

具体代码如下:

1.创建一个项目(默认的就行了)

2.创建 (紫色方块)

AutoSizeWidget.cpp

#pragma execution_character_set("utf-8")
#include "AutoSizeWidget.h"
#include "ui_autosizewidget.h"
#include <QDebug>
 
AutoSizeWidget::AutoSizeWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::AutoSizeWidget)
{
    ui->setupUi(this);
    this->setWindowFlags(Qt::FramelessWindowHint);//去掉标题栏
    //this->setAttribute(Qt::WA_StyledBackground,true);
    isLeftPressDown = false;
    dir = NONE;
    // 追踪鼠标
    this->setMouseTracking(true);
}
 
AutoSizeWidget::~AutoSizeWidget()
{
    delete ui;
}
 
void AutoSizeWidget::judgeRegionSetCursor(const QPoint& currentPoint)
{
    // 获取窗体在屏幕上的位置区域,tl为topleft点,rb为rightbottom点
    QRect rect = this->rect();
 
    QPoint tl = mapToParent(rect.topLeft());
    QPoint rb = mapToParent(rect.bottomRight());
 
    int x = currentPoint.x();
    int y = currentPoint.y();
 
    if (tl.x() + Padding >= x && tl.x() <= x && tl.y() + Padding >= y && tl.y() <= y) {
        // 左上角
        dir = LEFTTOP;
        this->setCursor(QCursor(Qt::SizeFDiagCursor));  // 设置鼠标形状
    }
    else if (x >= rb.x() - Padding && x <= rb.x() && y >= rb.y() - Padding && y <= rb.y()) {
        // 右下角
        dir = RIGHTBOTTOM;
        this->setCursor(QCursor(Qt::SizeFDiagCursor));
    }
    else if (x <= tl.x() + Padding && x >= tl.x() && y >= rb.y() - Padding && y <= rb.y()) {
        //左下角
        dir = LEFTBOTTOM;
        this->setCursor(QCursor(Qt::SizeBDiagCursor));
    }
    else if (x <= rb.x() && x >= rb.x() - Padding && y >= tl.y() && y <= tl.y() + Padding) {
        // 右上角
        dir = RIGHTTOP;
        this->setCursor(QCursor(Qt::SizeBDiagCursor));
    }
    else if (x <= tl.x() + Padding && x >= tl.x()) {
        // 左边
        dir = LEFT;
        this->setCursor(QCursor(Qt::SizeHorCursor));
    }
    else if (x <= rb.x() && x >= rb.x() - Padding) {
        // 右边
        dir = RIGHT;
        this->setCursor(QCursor(Qt::SizeHorCursor));
    }
    else if (y >= tl.y() && y <= tl.y() + Padding) {
        // 上边
        dir = UP;
        this->setCursor(QCursor(Qt::SizeVerCursor));
    }
    else if (y <= rb.y() && y >= rb.y() - Padding) {
        // 下边
        dir = DOWN;
        this->setCursor(QCursor(Qt::SizeVerCursor));
    }
    else {
        // 默认
        dir = NONE;
        this->setCursor(QCursor(Qt::ArrowCursor));
    }
}
 
void AutoSizeWidget::mouseReleaseEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton) {
        isLeftPressDown = false;
        if (dir != NONE) {
            this->releaseMouse();
            this->setCursor(QCursor(Qt::ArrowCursor));
        }
    }
}
void AutoSizeWidget::mousePressEvent(QMouseEvent *event)
{
    switch (event->button()) {
    case Qt::LeftButton:
        isLeftPressDown = true;
        if (dir != NONE) {
            this->mouseGrabber();
        }
        else {
            dragPosition = event->globalPos() - this->frameGeometry().topLeft();
        }
        break;
    default:
        QWidget::mousePressEvent(event);
    }
}
void AutoSizeWidget::mouseMoveEvent(QMouseEvent *event)
{
    QPoint gloPoint = mapToParent(event->pos());
    QRect rect = this->rect();
    QPoint tl = mapToParent(rect.topLeft());
    QPoint rb = mapToParent(rect.bottomRight());
    qDebug()<<"鼠标移动位置"<<gloPoint
            <<"矩形左上角坐标 "<<tl
            <<"矩形右下角坐标 "<<rb;
    if (!isLeftPressDown) {
        this->judgeRegionSetCursor(gloPoint);
    }
    else {
 
        qDebug()<<"左键是否点击 是";
        if (dir != NONE) {
            qDebug()<<"状态    "<<dir;
            QRect rMove(tl, rb);
 
            switch (dir) {
            case LEFT:
                if (rb.x() - gloPoint.x() <= this->minimumWidth())
                    rMove.setX(tl.x());
                else
                    rMove.setX(gloPoint.x());
                break;
            case RIGHT:
                rMove.setWidth(gloPoint.x() - tl.x());
                break;
            case UP:
                if (rb.y() - gloPoint.y() <= this->minimumHeight())
                    rMove.setY(tl.y());
                else
                    rMove.setY(gloPoint.y());
                break;
            case DOWN:
                rMove.setHeight(gloPoint.y() - tl.y());
                break;
            case LEFTTOP:
                if (rb.x() - gloPoint.x() <= this->minimumWidth())
                    rMove.setX(tl.x());
                else
                    rMove.setX(gloPoint.x());
                if (rb.y() - gloPoint.y() <= this->minimumHeight())
                    rMove.setY(tl.y());
                else
                    rMove.setY(gloPoint.y());
                break;
            case RIGHTTOP:
                rMove.setWidth(gloPoint.x() - tl.x());
                rMove.setY(gloPoint.y());
                break;
            case LEFTBOTTOM:
                rMove.setX(gloPoint.x());
                rMove.setHeight(gloPoint.y() - tl.y());
                break;
            case RIGHTBOTTOM:
                rMove.setWidth(gloPoint.x() - tl.x());
                rMove.setHeight(gloPoint.y() - tl.y());
                break;
            default:
                break;
            }
            this->setGeometry(rMove);
        }
        else {
            move(event->globalPos() - dragPosition);
            event->accept();
        }
    }
    QWidget::mouseMoveEvent(event);
}

AutoSizeWidget.h

#ifndef AUTOSIZEWIDGET_H
#define AUTOSIZEWIDGET_H
 
#include <QWidget>
#include <QMouseEvent>
//#include "basewidget.h"
//这是mainWindow的基类,继承与QWidget,实现了可拉伸大小
enum Direction {
    UP, DOWN, LEFT, RIGHT, LEFTTOP, LEFTBOTTOM, RIGHTBOTTOM, RIGHTTOP, NONE
};
 
namespace Ui {
class AutoSizeWidget;
}
 
class AutoSizeWidget : public QWidget
{
    Q_OBJECT
 
public:
    explicit AutoSizeWidget(QWidget *parent = 0);
    ~AutoSizeWidget();
 
protected:
    void mouseMoveEvent(QMouseEvent *) override;
    void mousePressEvent(QMouseEvent *) override;
    void mouseReleaseEvent(QMouseEvent *) override;
 
private:
    Ui::AutoSizeWidget *ui;
    void judgeRegionSetCursor(const QPoint&);
    const int Padding = 2;
    bool isLeftPressDown;  // 判断左键是否按下
    QPoint dragPosition;   // 窗口移动拖动时需要记住的点
    // 窗口大小改变时,记录改变方向
    Direction dir;
};
 
#endif // AUTOSIZEWIDGET_H

AutoSizeWidget.ui   (大小随意)

 

3.创建蓝色方块(不需要就不要加了,主要是紫色方块功能)

BaseWidget.cpp

#include "BaseWidget.h"
#include "ui_BaseWidget.h"
 
BaseWidget::BaseWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::BaseWidget)
{
    ui->setupUi(this);
}
 
BaseWidget::~BaseWidget()
{
    delete ui;
}
BaseWidget.h
#ifndef BASEWIDGET_H
#define BASEWIDGET_H
 
#include <QWidget>
 
namespace Ui {
class BaseWidget;
}
 
class BaseWidget : public QWidget
{
    Q_OBJECT
 
public:
    explicit BaseWidget(QWidget *parent = 0);
    ~BaseWidget();
 
private:
    Ui::BaseWidget *ui;
};
 
#endif // BASEWIDGET_H

BaseWidget.ui

 

4.在MainWindow里面加入graphicsView,还有蓝色和紫色方块

MainWindow.cpp

#include "AutoSizeWidget.h"
#include "BaseWidget.h"
#include "mainwindow.h"
#include "ui_mainwindow.h"
 
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
 
    QGraphicsScene *scene = new QGraphicsScene;
    ui->graphicsView->setScene(scene);
    scene->setSceneRect(ui->graphicsView->rect());
    //ui->graphicsView->resize(600,400);
    ui->graphicsView->show();
 
    BaseWidget *w = new BaseWidget();
    w->move(100,100);
    scene->addWidget(w);
 
    BaseWidget *w1 = new BaseWidget();
    w1->move(355,100);
    scene->addWidget(w1);
 
    BaseWidget *w2 = new BaseWidget();
    w2->move(100,255);
    scene->addWidget(w2);
 
    BaseWidget *w3 = new BaseWidget();
    w3->move(355,255);
    scene->addWidget(w3);
 
    AutoSizeWidget *item = new AutoSizeWidget();
    scene->addWidget(item);
 
}
 
MainWindow::~MainWindow()
{
    delete ui;
}

MainWindow.ui

 

5.运行就可以了(整个代码复制就可以用了

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值