QT繪製區域(ROI)框(矩形框和橢圓框)

先上效果圖

由於項目要涉及芯片檢測的功能,需要選擇特定區域,所以製作了個區域選擇框,

核心代碼1:DrawQWidget.h

#ifndef DRAWQWIDGET_H
#define DRAWQWIDGET_H

#include <QWidget>
#include <QKeyEvent>
#include <qpoint.h>
#include <qpen.h>

/*
 *
 */
typedef enum draw_shap_e{
    DRAW_RECT,    //畫矩形
    DRAW_ELLIPSE, //畫橢圓
    DRAW_NO       //不畫
}DRAW_SHAP_E;
/* 用來表示鼠標在矩形區域的位置信息
 *
 */
typedef enum rect_mouse_position_e{
    RECT_UPPER=0,     //上邊緣
    RECT_LOWER=1,     //下邊緣
    RECT_LEFT,        //左邊緣
    RECT_RIGHT,       //右邊緣
    RECT_LEFTUPPER,   //左上角
    RECT_LEFTLOWER,   //左下角
    RECT_RIGHTLOWER,  //右下角
    RECT_RIGHTUPPER,  //右上角
    RECT_INSIDE,      //區域內部
    RECT_OUTSIDE      //區域外部
}RECT_MOUSE_POSITION_E;

/* 用來表示鼠標在橢圓區域的位置信息
 *
 */
typedef enum ellipse_mouse_position_e{
    ELLIPSE_UPPER=0,     //上頂角
    ELLIPSE_LOWER=1,     //下頂角
    ELLIPSE_LEFT,        //左頂角
    ELLIPSE_RIGHT,       //右頂角
    ELLIPSE_INSIDE,      //區域內部
    ELLIPSE_OUTSIDE      //區域外部
}ELLIPSE_MOUSE_POSITION_E;

class DrawQWidget : public QWidget
{
    Q_OBJECT
public:
    explicit DrawQWidget(QWidget *parent = 0);
    ~DrawQWidget();
    void set_draw_shap(DRAW_SHAP_E d);
    void set_picture_image(QString file_name);

protected:
    void timerEvent(QTimerEvent*);
    void paintEvent(QPaintEvent*) override;
    void mousePressEvent(QMouseEvent *event);
    void mouseMoveEvent(QMouseEvent *event);
    void mouseReleaseEvent(QMouseEvent *event);

private:
    bool is_mouse_pressed;//是否按下鼠標
    DRAW_SHAP_E draw_shap;



    QPoint                           new_mouse_pos;
    QPoint                           old_mouse_pos;
    int                              m_difference_x;
    int                              m_difference_y;
    QPainter                        *painter;         //用來繪製圖像
    QPen                             frame_pen;       //用來繪製區域邊框
    QPen                             red_point_pen;   //用來繪製紅色點
    const int                        BoundaryRange = 6;//用來表示邊界的寬度範圍,用於拖拽
    /* 矩形區域相關變量和函數
     * 注意:QPoint的0點是左上角,橫向向右爲X的正方向,豎向向下爲Y的正方向
     */
    int        rect_left;        //表示矩形右上角的X座標
    int        rect_top;         //表示矩形右上角的Y座標
    int        rect_width;       //表示矩形的寬(即水平長度)
    int        rect_height;      //表示矩形的高(即垂直長度)
    int        rect_top_left_x,   rect_top_left_y;       //左上
    int        rect_top_right_x,  rect_top_right_y;      //右上
    int        rect_low_left_x,   rect_low_left_y;       //左下
    int        rect_low_right_x,  rect_low_right_y;      //右下
    QPolygon                      rect_polygon;          //裝載8個紅點的座標
    RECT_MOUSE_POSITION_E         rect_mouse_pos;
    void                          rect_init_region();
    void                          rect_update_region();
    void                          rect_change_region();
    RECT_MOUSE_POSITION_E         rect_get_mouse_pos(int pos_x, int pos_y);


    /* 橢圓區域相關變量和函數
     * 注意:drawEllipse(20,20,210,160);
     * 第1,2個參數表示圓/橢圓距屏幕左上角的像素數,第3,4個參數表示圓/橢圓的寬度和高度。
     * 更加確切地表述,這個圓或橢圓是在矩形中,這個矩形的左上角的頂點在座標軸中的位置爲(20,20),
     * 這個圓或橢圓的中心爲這個矩形的中心
     */
    int        ellipse_left;        //表示橢圓右上角的X座標
    int        ellipse_top;         //表示橢圓右上角的Y座標
    int        ellipse_width;       //表示橢圓的寬(即水平長度)
    int        ellipse_height;      //表示橢圓的高(即垂直長度)
    int        ellipse_middle_x;
    int        ellipse_middle_y;
    QPolygon                         ellipse_polygon;          //裝載4個紅點的座標
    ELLIPSE_MOUSE_POSITION_E         ellipse_mouse_pos;
    void                             ellipse_init_region();
    void                             ellipse_update_region();
    void                             ellipse_change_region();
    ELLIPSE_MOUSE_POSITION_E         ellipse_get_mouse_pos(int pos_x, int pos_y);

    /* other
     *
     */
    int                 timer_id;
    QImage              picture_image;
    int                 picture_image_w;
    int                 picture_image_h;
public slots:
};
#endif // DRAWQWIDGET_H

核心代碼2:DrawQWidget.cpp

#include "DrawQWidget.h"
#include <qdebug.h>
#include <qpainter.h>
DrawQWidget::DrawQWidget(QWidget *parent) : QWidget(parent)
{
    setAttribute(Qt::WA_StyledBackground);
    setStyleSheet("background-color: rgb(0, 0, 0);");
    grabKeyboard();
    setMouseTracking(true);

    m_difference_x                = 0;
    m_difference_y                = 0;
    draw_shap                     = DRAW_NO;
    painter                       = new QPainter(this);
    frame_pen                     = QPen(QColor(0,174,255),2);
    red_point_pen                 = QPen(QColor(255,0,0),4);
    is_mouse_pressed              = false;
    timer_id = startTimer(20);


    rect_init_region();
    ellipse_init_region();
    /// 開啓鼠標實時追蹤
    setMouseTracking(true);

}

DrawQWidget::~DrawQWidget()
{
    killTimer(timer_id);
}


/* Event function
 *
 */
void DrawQWidget::timerEvent(QTimerEvent *)
{
    this->update();
}
void DrawQWidget::paintEvent(QPaintEvent *)
{
    painter->begin(this);
    painter->drawImage(QRectF(0,0,width(),height()), picture_image);
    switch (draw_shap) {
    case (DRAW_RECT)     :{
        painter->setPen(frame_pen);//繪製邊框線
        painter->drawRect(QRect(rect_left, rect_top, rect_width, rect_height));
        painter->setPen(red_point_pen);//繪製八個點
        painter->drawPoints(rect_polygon);
        }break;
    case (DRAW_ELLIPSE)  :{
        painter->setPen(frame_pen);//繪製邊框線
        painter->drawEllipse(QRect(ellipse_left, ellipse_top, ellipse_width, ellipse_height));
        painter->setPen(red_point_pen);//繪製四個點
        painter->drawPoints(ellipse_polygon);
        }break;
    case (DRAW_NO)       :break;
    }

    painter->end();
}

void DrawQWidget::mousePressEvent(QMouseEvent *event)
{
//    if (!is_start_draw) return;
    is_mouse_pressed = true;
}

void DrawQWidget::mouseMoveEvent(QMouseEvent *event)
{
//    if (!is_start_draw) return;
    new_mouse_pos = event->pos();
    if (is_mouse_pressed) {
        m_difference_x = new_mouse_pos.x() - old_mouse_pos.x();
        m_difference_y = new_mouse_pos.y() - old_mouse_pos.y();
        switch (draw_shap) {
        case (DRAW_RECT)     :rect_change_region();break;
        case (DRAW_ELLIPSE)  :ellipse_change_region();break;
        case (DRAW_NO)       :break;
        }
    }else{
        switch (draw_shap) {
        case (DRAW_RECT)     :rect_mouse_pos = rect_get_mouse_pos(new_mouse_pos.x(), new_mouse_pos.y());break;
        case (DRAW_ELLIPSE)  :ellipse_mouse_pos = ellipse_get_mouse_pos(new_mouse_pos.x(), new_mouse_pos.y());break;
        case (DRAW_NO)       :break;
        }

    }

    old_mouse_pos = new_mouse_pos;
}

void DrawQWidget::mouseReleaseEvent(QMouseEvent *event)
{
//    if (!is_start_draw) return;
    is_mouse_pressed = false;
}


/* Rect function
 *
 */
void DrawQWidget::rect_init_region()
{
    rect_left   = 100;
    rect_top    = 200;
    rect_width  = 101;
    rect_height = 101;
    rect_mouse_pos = RECT_OUTSIDE;
    rect_update_region();
}
void DrawQWidget::rect_update_region()
{
    rect_top_left_x  = rect_left;            rect_top_left_y  = rect_top;
    rect_top_right_x = rect_left+rect_width; rect_top_right_y = rect_top;
    rect_low_left_x  = rect_left;            rect_low_left_y  = rect_top+rect_height;
    rect_low_right_x = rect_left+rect_width; rect_low_right_y = rect_top+rect_height;

    int Middle_X = rect_left + (rect_width>>1);
    int Middle_Y = rect_top + (rect_height>>1);
    rect_polygon.clear();
    rect_polygon<<QPoint(Middle_X, rect_top)      //上中
                <<QPoint(rect_top_right_x, Middle_Y)   //右中
                <<QPoint(Middle_X, rect_low_left_y)    //下中
                <<QPoint(rect_left, Middle_Y)     //左中
                <<QPoint(rect_left, rect_top)     //左上角
                <<QPoint(rect_top_right_x, rect_top)   //右上角
                <<QPoint(rect_top_right_x, rect_low_left_y) //右下角
                <<QPoint(rect_left, rect_low_left_y);  //左下角

}

void DrawQWidget::rect_change_region()
{
    switch (rect_mouse_pos) {
    case (RECT_UPPER): rect_top += m_difference_y; rect_height -= m_difference_y;break;//上邊界
    case (RECT_LOWER): rect_height += m_difference_y;break; //下邊界
    case (RECT_LEFT) : rect_left += m_difference_x; rect_width -= m_difference_x;break;//左邊界
    case (RECT_RIGHT): rect_width += m_difference_x;break; //右邊界
    case (RECT_LEFTUPPER) : {//左上角
        rect_top += m_difference_y; rect_height -= m_difference_y;
        rect_left += m_difference_x; rect_width -= m_difference_x;
        }break;
    case (RECT_LEFTLOWER) : {//左下角
        rect_height += m_difference_y;
        rect_left += m_difference_x; rect_width -= m_difference_x;
        }break;
    case (RECT_RIGHTLOWER) : {//右下角
        rect_height += m_difference_y;
        rect_width += m_difference_x;
        }break;
    case (RECT_RIGHTUPPER) : {//右上角
        rect_top += m_difference_y; rect_height -= m_difference_y;
        rect_width += m_difference_x;
        }break;
    case (RECT_INSIDE) : {//內部
        rect_top += m_difference_y;rect_left += m_difference_x;
        }break;
    case (RECT_OUTSIDE) : return;//外部
    }
    rect_update_region();
}

RECT_MOUSE_POSITION_E DrawQWidget::rect_get_mouse_pos(int pos_x, int pos_y)
{
    if (pos_x < rect_top_left_x || pos_x > rect_top_right_x || pos_y < rect_top_left_y || pos_y > rect_low_left_y) {
        this->setCursor(QCursor(Qt::ArrowCursor));
        return RECT_OUTSIDE;
    }else if (pos_y <= rect_top_left_y+BoundaryRange){ //1:左上角  2:右上角  3:上邊緣
          if      (pos_x <= rect_top_left_x+BoundaryRange) {this->setCursor(QCursor(Qt::SizeFDiagCursor));return RECT_LEFTUPPER;}
          else if (pos_x >= rect_top_right_x-BoundaryRange){this->setCursor(QCursor(Qt::SizeBDiagCursor));return RECT_RIGHTUPPER;}
          else                                        {this->setCursor(QCursor(Qt::SizeVerCursor));  return RECT_UPPER;}
    }else if (pos_y >= rect_low_left_y-BoundaryRange){ //1:左下角  2:右下角  3:下邊緣
          if      (pos_x <= rect_low_left_x+BoundaryRange) {this->setCursor(QCursor(Qt::SizeBDiagCursor));return RECT_LEFTLOWER;}
          else if (pos_x >= rect_low_right_x-BoundaryRange){this->setCursor(QCursor(Qt::SizeFDiagCursor));return RECT_RIGHTLOWER;}
          else                                        {this->setCursor(QCursor(Qt::SizeVerCursor));  return RECT_LOWER;}
    }else if (pos_x <= rect_top_left_x+BoundaryRange) {   //左邊緣
        this->setCursor(QCursor(Qt::SizeHorCursor));  return RECT_LEFT;
    }else if (pos_x >= rect_top_right_x-BoundaryRange) {  //右邊緣
        this->setCursor(QCursor(Qt::SizeHorCursor));  return RECT_RIGHT;
    }else {
        this->setCursor(QCursor(Qt::SizeAllCursor));
        return RECT_INSIDE;
    }
}
/* Ellipse function
 *
 */
void DrawQWidget::ellipse_init_region()
{
    ellipse_left   = 100;
    ellipse_top    = 200;
    ellipse_width  = 101;
    ellipse_height = 101;
    ellipse_mouse_pos = ELLIPSE_OUTSIDE;
    ellipse_update_region();
}

void DrawQWidget::ellipse_update_region()
{
    ellipse_middle_x = ellipse_left + (ellipse_width>>1);
    ellipse_middle_y = ellipse_top + (ellipse_height>>1);
    ellipse_polygon.clear();
    ellipse_polygon<<QPoint(ellipse_middle_x,        ellipse_top)            //上頂角
                   <<QPoint(ellipse_left+ellipse_width, ellipse_middle_y)    //右頂角
                   <<QPoint(ellipse_middle_x, ellipse_top+ellipse_height)    //下頂角
                   <<QPoint(ellipse_left, ellipse_middle_y);                 //左頂角
}

void DrawQWidget::ellipse_change_region()
{
    switch (ellipse_mouse_pos) {
    case (ELLIPSE_UPPER)  : ellipse_top += m_difference_y; ellipse_height -= m_difference_y;break;
    case (ELLIPSE_LOWER)  : ellipse_height += m_difference_y;break;
    case (ELLIPSE_LEFT)   : ellipse_left += m_difference_x; ellipse_width -= m_difference_x;break;
    case (ELLIPSE_RIGHT)  : ellipse_width += m_difference_x;break;
    case (ELLIPSE_INSIDE) : ellipse_top += m_difference_y;ellipse_left += m_difference_x;break;
    case (ELLIPSE_OUTSIDE): return;
    }
    ellipse_update_region();
}

ELLIPSE_MOUSE_POSITION_E DrawQWidget::ellipse_get_mouse_pos(int pos_x, int pos_y)
{
    if (pos_x < ellipse_left || pos_x > (ellipse_left+ellipse_width) || pos_y < ellipse_top || pos_y > (ellipse_top+ellipse_height)) {
        this->setCursor(QCursor(Qt::ArrowCursor));
        return ELLIPSE_OUTSIDE;
    }else if (pos_y <= ellipse_top+BoundaryRange){ //上頂角
          if (pos_x >= (ellipse_middle_x-3) && pos_x <= (ellipse_middle_x+3)){
              this->setCursor(QCursor(Qt::SizeVerCursor));  return ELLIPSE_UPPER;
          }else{
            this->setCursor(QCursor(Qt::SizeAllCursor));  return ELLIPSE_INSIDE;
          }
    }else if (pos_y >= ellipse_top+ellipse_height-BoundaryRange){ //下頂角
        if (pos_x >= (ellipse_middle_x-3) && pos_x <= (ellipse_middle_x+3)) {
            this->setCursor(QCursor(Qt::SizeVerCursor));  return ELLIPSE_LOWER;
        }else{
            this->setCursor(QCursor(Qt::SizeAllCursor));  return ELLIPSE_INSIDE;
        }
    }else if (pos_x <= ellipse_left+BoundaryRange) {   //左頂角
        if (pos_y >= (ellipse_middle_y-3) && pos_y <= (ellipse_middle_y+3)) {
            this->setCursor(QCursor(Qt::SizeHorCursor));  return ELLIPSE_LEFT;
        }else{
            this->setCursor(QCursor(Qt::SizeAllCursor));  return ELLIPSE_INSIDE;
        }
    }else if (pos_x >= ellipse_left+ellipse_width-BoundaryRange) {  //右頂角
        if (pos_y >= (ellipse_middle_y-3) && pos_y <= (ellipse_middle_y+3)) {
            this->setCursor(QCursor(Qt::SizeHorCursor));  return ELLIPSE_RIGHT;
        }else{
            this->setCursor(QCursor(Qt::SizeAllCursor));  return ELLIPSE_INSIDE;
        }
    }else {
        this->setCursor(QCursor(Qt::SizeAllCursor));
        return ELLIPSE_INSIDE;
    }
}

/* other function
 *
 */
void DrawQWidget::set_draw_shap(DRAW_SHAP_E d)
{
    draw_shap = d;
}

void DrawQWidget::set_picture_image(QString file_name)
{
    QImage image_tmp;
    image_tmp.load(file_name);
    if (!image_tmp.isNull()){
        picture_image   = image_tmp;
        picture_image_w = image_tmp.width();
        picture_image_h = image_tmp.height();
    }
}

 

在QWidget上繪製區域框,可以放大縮小移動,可以是矩形,也可以是橢圓,註釋非常完整。

完整項目源碼:https://download.csdn.net/download/qq_40732350/12032761

沒有積分的朋友可以到淘寶代理下載,只要一塊錢(不限積分)

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章