Qt實現正弦曲線圖(類似示波器功能)

寫在前面:因爲Qt的GUI界面座標和數學座標系不同,所在顯示時要進行座標轉換,GUI界面是以左上角爲原點座標的

頭文件:

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private:
    Ui::MainWindow *ui;
private slots:
    int OnSettingsChanged();
};

#endif // MAINWINDOW_H
sinwidget.h(繼承於QWidget)
#ifndef SINWIDGET_H
#define SINWIDGET_H

#include <QWidget>
#include <QPainter>
#include <math.h>
#include <QPoint>
#include <QPaintEvent>

class SinWidget : public QWidget
{
    Q_OBJECT
public:
    explicit SinWidget(QWidget *parent = 0);
public:
    void Adjust(int period, int grain, int radius);
    QPoint origin();            // 座標原點位置
    QPoint toCoord(QPoint p);   // 將GUI窗口的點(x,y)轉換成座標系統裏的點
    QPoint fromCoord(QPoint p); // 將座標系內的(x,y)轉成GUI的座標

signals:

public slots:

private:
    virtual void paintEvent(QPaintEvent *event );
    int m_period, m_grain, m_radius;
};

#endif // SINWIDGET_H

源文件:

main.cpp

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}
mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    ui->m_ctlPeriod->setValue(50);
    ui->m_ctlGrain->setValue(1);
    ui->m_ctlRadius->setValue(50);

    connect(ui->m_ctlRadius, SIGNAL(valueChanged(int)),
            this, SLOT(OnSettingsChanged()));

    connect(ui->m_ctlGrain, SIGNAL(valueChanged(int)),
            this, SLOT(OnSettingsChanged()));

    connect(ui->m_ctlPeriod, SIGNAL(valueChanged(int)),
            this, SLOT(OnSettingsChanged()));

    OnSettingsChanged();
}

MainWindow::~MainWindow()
{
    delete ui;
}

int MainWindow::OnSettingsChanged()
{
    ui->frame->Adjust(ui->m_ctlPeriod->value(),
                     ui->m_ctlGrain->value(),
                     ui->m_ctlRadius->value());

    return 0;
}
sinwidget.cpp

#include "sinwidget.h"

SinWidget::SinWidget(QWidget *parent) :
    QWidget(parent)
{
    m_period = 20;  //週期
    m_grain = 1;    //粒度
    m_radius = 10; // 振幅
}

void SinWidget::Adjust(int period, int grain, int radius)
{
    m_period = period;
    m_grain = grain;
    m_radius = radius;
    update(); // 更新重繪
}

QPoint SinWidget::origin()
{
    QRect r = this->rect();
    return r.center();
}
// 將GUI窗口的點(x,y)轉換成數學座標系統裏的點
QPoint SinWidget::toCoord(QPoint p)
{
    // 圓心
    QPoint o = this->origin();
    QPoint result =  p - o;
    result.setY(0 - result.y()); // y座標反轉
    return result;
}
// 將數學座標系內的(x,y)轉成GUI的座標
QPoint SinWidget::fromCoord(QPoint p)
{
    // 圓心
    QPoint o = this->origin();
    p.setY(0 - p.y()); // y座標反轉
    return p + o;

}

void SinWidget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);

    int width = this->width();
    int height = this->height();
    QRect rect(0,0, width, height);

    // 設置背景爲黑色
    painter.setBrush(QBrush(QColor(0x00,0x00, 0x00)));
    painter.drawRect(rect);

    painter.setPen(QPen(QColor(0, 255, 0))); // 設置線條爲綠色

    QPoint o = origin();
    painter.drawLine(QPoint(0, o.y()), QPoint(width, o.y())); // x軸
    painter.drawLine(QPoint(o.x(), 0), QPoint(o.x(), height));// y軸


    // 正弦曲線: 從座標原點,向左、向右伸展
    QPoint p1(0,0);
    for(int x=0; x<width/2; x+=m_grain)
    {
        // y=sin(x)
        double angle = (double) x / m_period * 2 * 3.1415926;
        double y = m_radius * sin(angle);
        QPoint p2(x, y);

        // 右側
        painter.drawLine(fromCoord(p1), fromCoord(p2));

        // 左側
        QPoint base(0,0);
        painter.drawLine(fromCoord(base-p1), fromCoord(base-p2));

        p1 = p2;
    }
}
設計界面:(用到了Spin Box 、Label、Widget、部件)

注:Widget部件爲提升的自定義部件,即如下圖;


效果圖:


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