• Qt基于paintEvent自定义CharView


    Qt基于paintEvent自定义CharView

    鼠标拖动,缩放,区域缩放, 针对x轴,直接上代码
    请添加图片描述

    charview.h

    #ifndef CHARVIEW_H
    #define CHARVIEW_H
    
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    class ScaleNode
    {
    public:
        QPointF pointScaleOne;
        QPointF pointScaleTwo;
        QPointF pointScaleText;
        double scaleValue;
        bool bShowScaleText;
        ScaleNode* nextNode;
        ScaleNode(){
            bShowScaleText = false;
            nextNode = nullptr;
        }
    };
    
    class CharView: public QWidget
    {
    public:
        CharView(QWidget *parent = nullptr);
        ~CharView();
    
        virtual void paintAxisX(QPainter &painter);
        virtual void paintAxisY(QPainter &painter);
        virtual void paintCursor(QPainter &painter);
        virtual void paintData(QPainter &painter);
        virtual void paintMouseRightMove(QPainter &painter);
    
    
        void UpdeScaleNode();
        void InitScaleNode();
        void MouseLeftMoveUpdateStartEndValue();//鼠标左键拖动更新
        void MouseRightMoveUpdateStartEndValue();//鼠标右键选择更新
        void MouseWheelUpdateStartEndValue(int flag);//鼠标缩放更新
    
    private:
        void DeleteNode(ScaleNode* node);
    protected:
        virtual void paintEvent(QPaintEvent* event) override;
        virtual void resizeEvent(QResizeEvent* event) override;
        virtual void mouseMoveEvent(QMouseEvent* event) override;
        virtual void mousePressEvent(QMouseEvent* event) override;//鼠标左键按住拖动移动, 右键区域放大
        virtual void mouseReleaseEvent(QMouseEvent* event) override;
        virtual void wheelEvent(QWheelEvent* event) override;//滚动鼠标滑轮放大缩小
        virtual void mouseDoubleClickEvent(QMouseEvent* event) override;//双击恢复默认
    
    public:
        int leftBorder;
        int topBorder;
        int rightBorder;
        int bottomBorder;
    
        double scaleValue;
        int scaleLength;//刻度线高度
        int scaleTextScaleLength;//带text的刻度线高度
        int scaleTextHeight;//刻度text高度
        int scaleTextWidth;//刻度text宽度
        int scaleTextBorder;//刻度text边距
        int scaleCnt;//刻度数量
        double scaleWidth;//刻度宽度
        int scaleCntShowText;//每多少个刻度显示刻度text
        double startScaleValueInit;//默认刻度开始值
        double endScaleValueInit;//默认刻度结束值
        double startScaleValue;//当前刻度开始值
        double endScaleValue;//当前刻度结束值
        double everyWidthValue;//每个宽度的值
    
        ScaleNode* scaleNodeBegin;//第一个刻度
        QPointF currentPointF;//当前鼠标位置
        bool bShowCursor;//是否实现游标
        bool bPressLeft;//是否鼠标左键按下
        bool bPressRight;//是否鼠标右键按下
        QPointF pressPointF;//鼠标左键按下时坐标
        bool bPressRightMove;//鼠标是否按下移动
    
    
    };
    
    #endif // CHARVIEW_H
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90

    CharView.cpp

    #include "charview.h"
    
    
    #include 
    CharView::CharView(QWidget *parent):
        QWidget(parent)
    {
        setMouseTracking(true);
        setStyleSheet("background-color:rgb(255,255,255);");
        InitScaleNode();
    }
    
    CharView::~CharView()
    {
        DeleteNode(scaleNodeBegin);
    }
    
    void CharView::DeleteNode(ScaleNode *node)
    {
        if(node->nextNode)
            DeleteNode(node->nextNode);
        delete node;
        node = nullptr;
    }
    
    void CharView::UpdeScaleNode()
    {
        scaleValue = ((double)(endScaleValue - startScaleValue))/scaleCnt;
        scaleWidth = ((double)(width() - leftBorder - rightBorder))/scaleCnt;
        everyWidthValue = ((double)(endScaleValue - startScaleValue))/(width() - leftBorder - rightBorder);
    
        ScaleNode* node = scaleNodeBegin;
        int var=0;
        while(node){
    
            node->pointScaleOne = QPointF(leftBorder + var*scaleWidth, height() - bottomBorder);
            node->pointScaleTwo = QPointF(leftBorder + var*scaleWidth, height() - bottomBorder - scaleLength);
            node->pointScaleText = QPointF(leftBorder + var*scaleWidth - scaleTextWidth/2,  height() - bottomBorder + scaleTextBorder);
            node->scaleValue = startScaleValue + var*scaleValue;
            if(var%scaleCntShowText == 0)
            {
                node->pointScaleTwo = QPointF((double)(leftBorder + var*scaleWidth), height() - bottomBorder - scaleTextScaleLength);
                node->bShowScaleText = true;
            }
    
            var++;
            node = node->nextNode;
        }
    
    }
    
    void CharView::InitScaleNode()
    {
        bPressRightMove = false;
        bPressLeft = false;
        bPressRight = false;
        bShowCursor = true;
    
        leftBorder = 50;
        topBorder = 10;
        rightBorder = 50;
        bottomBorder = 20;
    
        scaleCntShowText = 5;
        startScaleValueInit = 0;
        endScaleValueInit = 3000000000;
        startScaleValue = startScaleValueInit;
        endScaleValue = endScaleValueInit;
        scaleCnt = 30;
        scaleLength = 2;
        scaleTextScaleLength = 4;
        scaleTextBorder = 5;
        scaleTextWidth = 100;
        scaleTextHeight = fontMetrics().height();
    
        ScaleNode* nodeTmp=nullptr;
        for (int var = 0; var <= scaleCnt; ++var) {
            ScaleNode* node = new ScaleNode;
            if(nodeTmp)
                nodeTmp->nextNode = node;
            nodeTmp = node;
            if(var == 0)
                scaleNodeBegin = node;
        }
    }
    
    void CharView::MouseWheelUpdateStartEndValue(int flag)
    {
        double zoomValue = (endScaleValue - startScaleValue)/10;
        if(flag > 0)
        {
            endScaleValue -= zoomValue;
        }
        else{
            endScaleValue += zoomValue;
        }
        double everyWidthValueOld = everyWidthValue;
        double centerX = currentPointF.x() - leftBorder;
        everyWidthValue = ((double)(endScaleValue - startScaleValue))/(width() - leftBorder - rightBorder);
        startScaleValue = startScaleValue + centerX*everyWidthValueOld - centerX*everyWidthValue ;
        endScaleValue = endScaleValue + centerX*everyWidthValueOld - centerX*everyWidthValue ;
        if(startScaleValue <=0)
            startScaleValue = 0;
    }
    
    void CharView::MouseLeftMoveUpdateStartEndValue()
    {
        double offsetX  =  currentPointF.x() - pressPointF.x();
        pressPointF = currentPointF;
        double offsetValue = offsetX*everyWidthValue;
    
        if(startScaleValue - offsetValue <=0 && offsetX > 0){
            startScaleValue = 0;
            offsetValue = startScaleValue;
        }else{
            startScaleValue = startScaleValue - offsetValue;
        }
        endScaleValue = endScaleValue - offsetValue;
    
    }
    
    void CharView::MouseRightMoveUpdateStartEndValue()
    {
        if(currentPointF.x() < leftBorder || currentPointF.x() > width() - rightBorder ||
           pressPointF.x() < leftBorder || pressPointF.x() > width() - rightBorder|| !bPressRight)
            return;
        endScaleValue = startScaleValue + (currentPointF.x() - leftBorder)*everyWidthValue;
        startScaleValue = startScaleValue + (pressPointF.x() - leftBorder)*everyWidthValue;
    }
    
    void CharView::paintEvent(QPaintEvent *event)
    {
        //界面大小改变,只改变刻度实际宽度, 刻度开始结束值不变
        //鼠标缩放,刻度实际宽度改变, 刻度开始结束值改变
        //鼠标拖动,刻度实际宽度不变, 刻度开始结束值改变
    
        //绘制前计算更新刻度
        UpdeScaleNode();
    
        QPainter painter(this);
       // painter.setRenderHint(QPainter::Antialiasing);//加上会加粗
    
        //绘制刻度
        paintAxisX(painter);
        paintAxisY(painter);
    
        //绘制数据
        paintData(painter);
    
        paintMouseRightMove(painter);
        //绘制游标
        if(bShowCursor)
            paintCursor(painter);
    }
    
    void CharView::paintMouseRightMove(QPainter &painter)
    {
        if(currentPointF.x() < leftBorder || currentPointF.x() > width() - rightBorder ||
           pressPointF.x() < leftBorder || pressPointF.x() > width() - rightBorder|| !bPressRight)
            return;
        QPen pen;
        pen.setStyle(Qt::DashLine);
        pen.setColor(QColor(236,132,251));
        pen.setWidth(1);
        painter.setPen(pen);
    
        double w = currentPointF.x() - pressPointF.x();
        double y = currentPointF.y() - pressPointF.y();
    
        painter.drawRect(pressPointF.x(),pressPointF.y(), w, y);
    }
    
    void CharView::paintAxisX(QPainter &painter)
    {
        QPen pen;
        pen.setStyle(Qt::SolidLine);
        pen.setColor(Qt::black);
        pen.setWidth(1);
        painter.setPen(pen);
    
        int y = height() - bottomBorder;
        painter.drawLine(QPointF(leftBorder, y),
                         QPointF(width() - rightBorder, y));
        ScaleNode* node = scaleNodeBegin;
        while(node){
    
            painter.drawLine(node->pointScaleOne,node->pointScaleTwo);
    
            if(node->bShowScaleText)
                painter.drawText(node->pointScaleText.x(), node->pointScaleText.y(), scaleTextWidth, scaleTextHeight,
                             Qt::AlignCenter, QString::number(node->scaleValue, 'f', 0));
    
            node = node->nextNode;
        }
    }
    
    void CharView::paintAxisY(QPainter &painter)
    {
    
    }
    
    void CharView::paintCursor(QPainter &painter)
    {
        if(currentPointF.x() < leftBorder || currentPointF.x() > width() - rightBorder)
            return;
        QPen pen;
        pen.setStyle(Qt::DashLine);
        pen.setColor(QColor(236,132,251));
        pen.setWidth(1);
        painter.setPen(pen);
    
    
        painter.drawLine(QPointF(currentPointF.x(), 0), QPointF(currentPointF.x(), height() - bottomBorder));
    
    
        double number = (currentPointF.x() - leftBorder)*everyWidthValue + startScaleValue;
        painter.drawText(currentPointF.x(), height() - bottomBorder - scaleTextHeight, scaleTextWidth, scaleTextHeight,
                         Qt::AlignLeft, QString::number(number, 'f', 0));
    }
    
    void CharView::paintData(QPainter &painter)
    {
        //test
        double value1 = 1240000000;
        double value2 = 1590000000;
        double x1 = leftBorder + (value1 - startScaleValue)/everyWidthValue;
        double x2 = leftBorder + (value2 - startScaleValue)/everyWidthValue;
    
        QPointF point1(x1, 100);
        QPointF point2(x2, 200);
    
        QPen pen;
        pen.setStyle(Qt::SolidLine);
        pen.setColor(Qt::black);
        pen.setWidth(1);
        painter.setPen(pen);
    
        painter.drawLine(point1,point2);
    }
    
    void CharView::resizeEvent(QResizeEvent *event)
    {
        UpdeScaleNode();
        return QWidget::resizeEvent(event);
    }
    
    void CharView::mouseMoveEvent(QMouseEvent *event)
    {
        currentPointF = event->localPos();
        if(bPressLeft){
           if(currentPointF != pressPointF)
                MouseLeftMoveUpdateStartEndValue();
        }
        else if(bPressRight){
            bPressRightMove = true;
        }
        update();
        return QWidget::mouseMoveEvent(event);
    }
    
    void CharView::mousePressEvent(QMouseEvent *event)
    {
        if(!bPressLeft && event->button() == Qt::LeftButton){
            bPressLeft = true;
            pressPointF = event->localPos();
        }
        else if(!bPressRight && event->button() == Qt::RightButton){
            bPressRight = true;
            pressPointF = event->localPos();
        }
        return QWidget::mousePressEvent(event);
    }
    
    void CharView::mouseReleaseEvent(QMouseEvent *event)
    {
        if(bPressRight)
        {
            if(bPressRightMove && currentPointF != pressPointF)
                MouseRightMoveUpdateStartEndValue();
            bPressRight = false;
            bPressRightMove = false;
            update();
        }
        bPressLeft = false;
        return QWidget::mouseReleaseEvent(event);
    }
    
    void CharView::wheelEvent(QWheelEvent *event)
    {
        MouseWheelUpdateStartEndValue(event->delta());
        update();
        return QWidget::wheelEvent(event);
    }
    
    void CharView::mouseDoubleClickEvent(QMouseEvent *event)
    {
        startScaleValue = startScaleValueInit;
        endScaleValue = endScaleValueInit;
        return QWidget::mouseDoubleClickEvent(event);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
    • 300
    • 301
  • 相关阅读:
    直播课堂系统02-搭建项目环境
    Mysql中获取所有表名以及表名带时间字符串使用BetweenAnd筛选区间范围
    java基于微信小程序的竞赛报名管理系统
    【FLASH存储器系列十】Nand Flash芯片使用指导之一
    《操作系统导论》之并发问题
    金仓数据库KingbaseES客户端编程开发框架-MyBatis(2. 概述 3. MyBatis配置说明)
    unity之粒子特效制作图片拼合文字效果
    『Linux - gcc / g++』c程序翻译过程
    C语言实现字符串比较
    戴哥说Java(三)——Java的反射和注解
  • 原文地址:https://blog.csdn.net/kchmmd/article/details/132941605