在做图形裁剪的时候,需要一个可以改变大小和位置的矩形框,用于指定裁剪区域大小
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACE
enum MOUSE_STATE{
LEFT = 0,
RIGHT,
BOTTOM,
TOP,
TOP_LEFT,
TOP_RIGHT,
BOTTOM_LEFT,
BOTTOM_RIGHT,
IN,
OUT
};
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
private:
Ui::Widget *ui;
QTransform mat;
QRect rect;
bool m_left_down;
QPoint m_pt_begin;
QPoint m_pt_rc;
MOUSE_STATE fsm_state;
MOUSE_STATE mouse_state;
MOUSE_STATE get_mouse_state(QPoint pt);
protected:
void paintEvent(QPaintEvent *event);
void mousePressEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QPainter>
#include <QKeyEvent>
#include <qDebug>
#define CORNER_WIDTH 30 //四个角的大小
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
, m_left_down(false)
, fsm_state(OUT)
, mouse_state(OUT)
{
ui->setupUi(this);
rect = QRect(100,100,800,600);
this->setMouseTracking(true);
}
Widget::~Widget()
{
delete ui;
}
MOUSE_STATE Widget::get_mouse_state(QPoint pt){
QRect rcMax(rect),rcMin(rect);
QRect rcCorner(0,0,CORNER_WIDTH,CORNER_WIDTH);
rcMax += QMargins(CORNER_WIDTH/2,CORNER_WIDTH/2,CORNER_WIDTH/2,CORNER_WIDTH/2);
rcMin -= QMargins(CORNER_WIDTH/2,CORNER_WIDTH/2,CORNER_WIDTH/2,CORNER_WIDTH/2);
if(!rcMax.contains(pt))
return OUT;
else{
if(rcMin.contains(pt))
return IN;
else{
rcCorner.moveCenter(rect.topLeft());
if(rcCorner.contains(pt))
return TOP_LEFT;
rcCorner.moveCenter(rect.topRight());
if(rcCorner.contains(pt))
return TOP_RIGHT;
rcCorner.moveCenter(rect.bottomLeft());
if(rcCorner.contains(pt))
return BOTTOM_LEFT;
rcCorner.moveCenter(rect.bottomRight());
if(rcCorner.contains(pt))
return BOTTOM_RIGHT;
if(fabs(pt.x() - rect.left()) < CORNER_WIDTH/2)
return LEFT;
else if(fabs(pt.x() - rect.right()) < CORNER_WIDTH/2)
return RIGHT;
if(fabs(pt.y() - rect.top()) < CORNER_WIDTH/2)
return TOP;
else if(fabs(pt.y() - rect.bottom()) < CORNER_WIDTH/2)
return BOTTOM;
}
}
return OUT;
}
void Widget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
QColor line_color(Qt::lightGray);
QColor line_color_sel(Qt::darkBlue);
QColor corner_color(Qt::lightGray);
QColor corner_color_sel(Qt::darkBlue);
painter.translate(rect.topLeft());
painter.setPen(QPen(mouse_state == TOP?line_color_sel:line_color,2, Qt::SolidLine));
painter.drawLine(QPoint{0,0},QPoint{rect.width()-CORNER_WIDTH/2, 0});
painter.setPen(QPen(mouse_state == TOP_LEFT?corner_color_sel:corner_color,6, Qt::SolidLine));
painter.drawLine(QPoint{0,CORNER_WIDTH/2},QPoint{0, 0});
painter.drawLine(QPoint{0,0},QPoint{CORNER_WIDTH/2, 0});
painter.resetTransform();
painter.translate(rect.topRight());
painter.rotate(90);
painter.setPen(QPen(mouse_state == RIGHT?line_color_sel:line_color,2, Qt::SolidLine));
painter.drawLine(QPoint{0,0},QPoint{rect.height()-CORNER_WIDTH/2, 0});
painter.setPen(QPen(mouse_state == TOP_RIGHT?corner_color_sel:corner_color,6, Qt::SolidLine));
painter.drawLine(QPoint{0,CORNER_WIDTH/2},QPoint{0, 0});
painter.drawLine(QPoint{0,0},QPoint{CORNER_WIDTH/2, 0});
painter.resetTransform();
painter.translate(rect.bottomRight());
painter.rotate(180);
painter.setPen(QPen(mouse_state == BOTTOM?line_color_sel:line_color,2, Qt::SolidLine));
painter.drawLine(QPoint{0,0},QPoint{rect.width()-CORNER_WIDTH/2, 0});
painter.setPen(QPen(mouse_state == BOTTOM_RIGHT?corner_color_sel:corner_color,6, Qt::SolidLine));
painter.drawLine(QPoint{0,CORNER_WIDTH/2},QPoint{0, 0});
painter.drawLine(QPoint{0,0},QPoint{CORNER_WIDTH/2, 0});
painter.resetTransform();
painter.translate(rect.bottomLeft());
painter.rotate(270);
painter.setPen(QPen(mouse_state == LEFT?line_color_sel:line_color,2, Qt::SolidLine));
painter.drawLine(QPoint{0,0},QPoint{rect.height()-CORNER_WIDTH/2, 0});
painter.setPen(QPen(mouse_state == BOTTOM_LEFT?corner_color_sel:corner_color,6, Qt::SolidLine));
painter.drawLine(QPoint{0,CORNER_WIDTH/2},QPoint{0, 0});
painter.drawLine(QPoint{0,0},QPoint{CORNER_WIDTH/2, 0});
}
void Widget::mousePressEvent(QMouseEvent *event)
{
m_left_down = true;
m_pt_begin = event->pos();
m_pt_rc = rect.center();
fsm_state = get_mouse_state(event->pos());
update();
}
void Widget::mouseReleaseEvent(QMouseEvent *event)
{
m_left_down = false;
}
void Widget::mouseMoveEvent(QMouseEvent *event)
{
auto state = get_mouse_state(event->pos());
if(mouse_state != state){
mouse_state = state;
switch(mouse_state){
case LEFT:setCursor(Qt::SizeHorCursor); break;
case RIGHT:setCursor(Qt::SizeHorCursor);break;
case BOTTOM:setCursor(Qt::SizeVerCursor);break;
case TOP:setCursor(Qt::SizeVerCursor);break;
case TOP_LEFT:setCursor(Qt::SizeFDiagCursor);break;
case TOP_RIGHT:setCursor(Qt::SizeBDiagCursor);break;
case BOTTOM_LEFT:setCursor(Qt::SizeBDiagCursor);break;
case BOTTOM_RIGHT:setCursor(Qt::SizeFDiagCursor);break;
case IN:setCursor(Qt::SizeAllCursor);break;
case OUT:setCursor(Qt::ArrowCursor);break;
break;
}
}
if(m_left_down){
auto pt = event->pos();
switch(fsm_state){
case LEFT:
if(pt.x() < rect.right() - CORNER_WIDTH/2)
rect.setLeft(pt.x());
break;
case RIGHT:
if(pt.x() > rect.left() + CORNER_WIDTH/2)
rect.setRight(pt.x());
break;
case BOTTOM:
if(pt.y() > rect.top() + CORNER_WIDTH/2)
rect.setBottom(pt.y());
break;
case TOP:
if(pt.y() < rect.bottom() - CORNER_WIDTH/2)
rect.setTop(pt.y());
break;
case TOP_LEFT:
if(pt.x() < rect.right() - CORNER_WIDTH/2 && pt.y() < rect.bottom() - CORNER_WIDTH/2)
rect.setTopLeft(pt);
break;
case TOP_RIGHT:
if(pt.x() > rect.left() + CORNER_WIDTH/2 && pt.y() < rect.bottom() - CORNER_WIDTH/2)
rect.setTopRight(pt);
break;
case BOTTOM_LEFT:
if(pt.x() < rect.right() - CORNER_WIDTH/2 && pt.y() > rect.top() + CORNER_WIDTH/2)
rect.setBottomLeft(pt);
break;
case BOTTOM_RIGHT:
if(pt.x() > rect.left() + CORNER_WIDTH/2 && pt.y() > rect.top() + CORNER_WIDTH/2)
rect.setBottomRight(pt);
break;
case IN:
rect.moveCenter(m_pt_rc + pt - m_pt_begin);
break;
case OUT:break;
break;
}
}
update();
return QWidget::mouseMoveEvent(event);
}