N
N
NosferatuZodd2021-11-29 01:42:52
Qt
NosferatuZodd, 2021-11-29 01:42:52

You need to add a scale for the graph that is drawn manually through QPainter, what do you recommend?

I'll make a reservation right away - I'm not reinventing the wheel, I have to draw the graph myself, since this is the task. The graph itself is being drawn, I tried to add some scale and scaleXY parameters to change the scale of the graph when scrolling the mouse wheel, but these attempts are not very successful. Ideally, I don’t want to scale the picture (as I do it now through "painter.scale(scaleXY, scaleXY)"), but rather change the scale of the graph, and it would be absolutely ideal to add movement along the graph while holding the LMB.

chart
#include "chart.h"
#include "mainwindow.h"

Chart::Chart(long long x0, long long yx0, QWidget *parent) : QWidget(parent), x0(x0), yx0(yx0)
{
    y = 0;
    C = qExp(2*x0)*(2000-(qExp(2*x0)/4)+yx0);
    scale = 20; // масштаб клеток/отрезков
    scaleXY = 1; //масштаб графика

    setMouseTracking(true);

}

void Chart::paintEvent(QPaintEvent*){
    painter.begin(this);
    if(scaleXY <1) scaleXY = 1; // задаем минимальную границу масштаба
    painter.scale(scaleXY, scaleXY); 

    painter.setRenderHints(QPainter::Antialiasing, true);
    painter.setBackgroundMode(Qt::OpaqueMode);
    painter.setBackground(Qt::white);

    pen.setColor(Qt::gray);
    pen.setWidth(1);
    painter.setPen(pen);

    for(int i = 0; i < width(); i+=scale){
        painter.drawLine(i, 0, i, height()); //клетки
        painter.drawLine(0, i, width(), i);
    }

    pen.setColor(QColor(220, 20, 60));
    pen.setWidth(3);
    painter.setPen(pen);

    painter.drawLine((width()/2), 0,(width()/2), height()); // ось Y

    QPolygon arrowY;
    arrowY << QPoint(width()/2, 0) << QPoint((width()/2)-20, 20); //левая часть стрелки
    arrowY << QPoint(width()/2, 0) << QPoint((width()/2)+20, 20); //правая часть стрелки
    painter.drawPolygon(arrowY);

    painter.drawLine(0, (height()/2), width(), (height()/2)); // ось X

    QPolygon arrowX;
    arrowX << QPoint(width(), height()/2) << QPoint((width())-20, (height()/2)-20); //верхняя часть стрелки
    arrowX << QPoint(width(), height()/2) << QPoint((width())-20,(height()/2)+20); //нижняя часть стрелки
    painter.drawPolygon(arrowX);

    for(int i = 0; i < width(); i+=scale){
        painter.drawLine(i, (height()/2)-5, i, (height()/2)+5); // отрезки слева направо
    }

    for(int i = 0; i < height(); i+=scale){
        painter.drawLine((width()/2)-5, i, (width()/2)+5, i); // отрезки сверху вниз
    }

    pen.setColor(QColor(0, 128, 128));
    pen.setWidth(4);
    painter.setPen(pen);

   for(float x = -100; x <= 100; x+=0.001){
        y = ((qExp(2*x)/4) + (C/qExp(2*x)) - 2000)/1000; 
        painter.drawPoint(QPoint(((width()/2)+x), ((height()/2)-y))); // здесь отрисовка самого графика
    }
    painter.end();
}

void Chart::wheelEvent(QWheelEvent* e){
    if(e->angleDelta().y() > 0){
        scale+= 1;
        scaleXY+=0.1;
        update();
    }
    else if(e->angleDelta().y() < 0){
        scale-= 1;
        scaleXY-=0.1;
        update();
    }
}

void Chart::mouseMoveEvent(QMouseEvent *e){
    bool leftClick = e->buttons() & Qt::LeftButton;
    if(leftClick){
        mousePoint = e->pos();
        update();
    }
}


Mainwindow
#include "mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QWidget(parent)
{
    resize(825, 800);
    setWindowFlags(Qt::MSWindowsFixedSizeDialogHint);

    line_x0 = new QLineEdit(this); // x0
    line_yx0 = new QLineEdit(this); // y(x0)

    btnDraw = new QPushButton("Отрисовать график", this);

    lbl1 = new QLabel("y (");
    lbl2 = new QLabel(") = ");

    layoutMain = new QVBoxLayout(this);
    layoutInput = new QHBoxLayout;
    layoutChart = new QHBoxLayout;

    layoutInput->addWidget(lbl1);
    layoutInput->addWidget(line_x0);
    layoutInput->addWidget(lbl2);
    layoutInput->addWidget(line_yx0);
    layoutInput->addWidget(btnDraw);

    layoutMain->addLayout(layoutInput);
    layoutMain->addSpacing(100);

    connect(btnDraw, SIGNAL(clicked()), this, SLOT(drawChart()));
}

MainWindow::~MainWindow()
{
}

void MainWindow::drawChart(){
    Chart* chart = new Chart(line_x0->text().toFloat(), line_yx0->text().toFloat(), this);
    layoutChart->addWidget(chart);
    layoutMain->addLayout(layoutChart);
    chart->update();
}

Answer the question

In order to leave comments, you need to log in

1 answer(s)
P
Pavel K, 2021-11-29
@PavelK

Greetings.
Maybe it's worth just multiplying the value in X and Y by some factor N, depending on the scale?

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question