Qt基于paintEvent自定义CharView

Qt基于paintEvent自定义CharView

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

charview.h

#ifndef CHARVIEW_H
#define CHARVIEW_H

#include <QWidget>
#include <QPainter>
#include <QPaintEvent>
#include <QResizeEvent>
#include <QMouseEvent>
#include <QWheelEvent>
#include <QPointF>

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

CharView.cpp

#include "charview.h"


#include <QDebug>
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);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值