提交 c8c7eae4 编写于 作者: D dragon

Add source file.

Add project & source file.
上级 bb3fe9ab
#-------------------------------------------------
#
# Project created by QtCreator 2017-11-16T09:53:11
#
#-------------------------------------------------
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets charts serialport
TARGET = QtChart
TEMPLATE = app
# The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp \
mainwidget.cpp \
chartview.cpp \
callout.cpp
HEADERS += \
mainwidget.h \
chartview.h \
callout.h
FORMS += \
mainwidget.ui
#include "callout.h"
#include <QPainter>
#include <QFontMetrics>
#include <QGraphicsSceneMouseEvent>
#include <QMouseEvent>
#include <QChart>
Callout::Callout(QChart *chart):
QGraphicsItem(chart),
chart(chart)
{
}
QRectF Callout::boundingRect() const
{
QPointF anchor = mapFromParent(chart->mapToPosition(this->anchor));
QRectF rect;
rect.setLeft(qMin(this->rect.left(), anchor.x()));
rect.setRight(qMax(this->rect.right(), anchor.x()));
rect.setTop(qMin(this->rect.top(), anchor.y()));
rect.setBottom(qMax(this->rect.bottom(), anchor.y()));
return rect;
}
void Callout::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
Q_UNUSED(option)
Q_UNUSED(widget)
QPainterPath path;
path.addRoundedRect(rect, 5, 5);
QPointF anchor = mapFromParent(chart->mapToPosition(this->anchor));
if (!rect.contains(anchor)) {
QPointF point1, point2;
// establish the position of the anchor point in relation to rect
bool above = anchor.y() <= rect.top();
bool aboveCenter = anchor.y() > rect.top() && anchor.y() <= rect.center().y();
bool belowCenter = anchor.y() > rect.center().y() && anchor.y() <= rect.bottom();
bool below = anchor.y() > rect.bottom();
bool onLeft = anchor.x() <= rect.left();
bool leftOfCenter = anchor.x() > rect.left() && anchor.x() <= rect.center().x();
bool rightOfCenter = anchor.x() > rect.center().x() && anchor.x() <= rect.right();
bool onRight = anchor.x() > rect.right();
// get the nearest rect corner.
qreal x = (onRight + rightOfCenter) * rect.width();
qreal y = (below + belowCenter) * rect.height();
bool cornerCase = (above && onLeft) || (above && onRight) || (below && onLeft) || (below && onRight);
bool vertical = qAbs(anchor.x() - x) > qAbs(anchor.y() - y);
qreal x1 = x + leftOfCenter * 10 - rightOfCenter * 20 + cornerCase * !vertical * (onLeft * 10 - onRight * 20);
qreal y1 = y + aboveCenter * 10 - belowCenter * 20 + cornerCase * vertical * (above * 10 - below * 20);;
point1.setX(x1);
point1.setY(y1);
qreal x2 = x + leftOfCenter * 20 - rightOfCenter * 10 + cornerCase * !vertical * (onLeft * 20 - onRight * 10);;
qreal y2 = y + aboveCenter * 20 - belowCenter * 10 + cornerCase * vertical * (above * 20 - below * 10);;
point2.setX(x2);
point2.setY(y2);
path.moveTo(point1);
path.lineTo(anchor);
path.lineTo(point2);
path = path.simplified();
}
painter->setBrush(QColor(255, 255, 255));
painter->drawPath(path);
painter->drawText(textRect, text);
}
void Callout::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
event->setAccepted(true);
}
void Callout::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
if (event->buttons() & Qt::LeftButton){
setPos(mapToParent(event->pos() - event->buttonDownPos(Qt::LeftButton)));
event->setAccepted(true);
} else {
event->setAccepted(false);
}
}
void Callout::setText(const QString &text)
{
this->text = text;
QFontMetrics metrics(font);
textRect = metrics.boundingRect(QRect(0, 0, 150, 150), Qt::AlignLeft, text);
textRect.translate(5, 5);
prepareGeometryChange();
rect = textRect.adjusted(-5, -5, 5, 5);
}
void Callout::setAnchor(QPointF point)
{
anchor = point;
}
void Callout::updateGeometry()
{
prepareGeometryChange();
setPos(chart->mapToPosition(anchor) + QPoint(10, -50));
}
#ifndef __CALLOUT_H__
#define __CALLOUT_H__
#include <QChartGlobal>
#include <QGraphicsItem>
#include <QFont>
QT_BEGIN_NAMESPACE
class QGraphicsSceneMouseEvent;
QT_END_NAMESPACE
QT_CHARTS_BEGIN_NAMESPACE
class QChart;
QT_CHARTS_END_NAMESPACE
QT_CHARTS_USE_NAMESPACE
class Callout : public QGraphicsItem
{
public:
Callout(QChart *parent);
void setText(const QString &text);
void setAnchor(QPointF point);
void updateGeometry();
QRectF boundingRect() const;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
protected:
void mousePressEvent(QGraphicsSceneMouseEvent *event);
void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
private:
QString text;
QRectF textRect;
QRectF rect;
QPointF anchor;
QFont font;
QChart *chart;
};
#endif /* __CALLOUT_H__ */
#include "chartview.h"
ChartView::ChartView(QChart *chart, QWidget *parent) :
QChartView(chart, parent),
isClicking(false),
xOld(0), yOld(0)
{
setRubberBand(QChartView::RectangleRubberBand);
}
void ChartView::mousePressEvent(QMouseEvent *event)
{
if (event->button() & Qt::LeftButton) {
isClicking = true;
} else if (event->button() & Qt::RightButton) {
chart()->zoomReset();
}
QChartView::mousePressEvent(event);
}
void ChartView::mouseMoveEvent(QMouseEvent *event)
{
int x, y;
if (isClicking) {
if (xOld == 0 && yOld == 0) {
} else {
x = event->x() - xOld;
y = event->y() - yOld;
chart()->scroll(-x, y);
}
xOld = event->x();
yOld = event->y();
return;
}
QChartView::mouseMoveEvent(event);
}
void ChartView::mouseReleaseEvent(QMouseEvent *event)
{
if (isClicking) {
xOld = yOld = 0;
isClicking = false;
}
/* Disable original right click event */
if (!(event->button() & Qt::RightButton)) {
QChartView::mouseReleaseEvent(event);
}
}
void ChartView::keyPressEvent(QKeyEvent *event)
{
switch (event->key()) {
case Qt::Key_Left:
chart()->scroll(-10, 0);
break;
case Qt::Key_Right:
chart()->scroll(10, 0);
break;
case Qt::Key_Up:
chart()->scroll(0, 10);
break;
case Qt::Key_Down:
chart()->scroll(0, -10);
break;
default:
keyPressEvent(event);
break;
}
}
#ifndef __CHARTVIEW_H__
#define __CHARTVIEW_H__
#include <QChartView>
#include <QRubberBand>
QT_CHARTS_USE_NAMESPACE
class ChartView : public QChartView
{
public:
ChartView(QChart *chart, QWidget *parent = 0);
protected:
void keyPressEvent(QKeyEvent *event);
void mousePressEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
private:
bool isClicking;
int xOld;
int yOld;
};
#endif /* __CHARTVIEW_H__ */
#include "mainwidget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWidget w;
w.show();
return a.exec();
}
#include "mainwidget.h"
#include "ui_mainwidget.h"
#include <QDebug>
#include <QSerialPort>
#include <QSerialPortInfo>
#include <QtMath>
MainWidget::MainWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::MainWidget),
chart(new QChart),
tip(0),
timer(new QTimer),
count(0),
isStopping(false)
{
ui->setupUi(this);
initUI();
timer->setInterval(50);
timer->start();
initSlot();
}
MainWidget::~MainWidget()
{
delete ui;
}
void MainWidget::wheelEvent(QWheelEvent *event)
{
if (event->delta() > 0) {
chart->zoom(1.1);
} else {
chart->zoom(10.0/11);
}
QWidget::wheelEvent(event);
}
void MainWidget::initUI()
{
ui->comboBox->addItem("TCP");
ui->comboBox->addItem("UDP");
auto ports = QSerialPortInfo::availablePorts();
for (auto port : ports) {
ui->comboBox->addItem(port.portName());
}
initChart();
}
void MainWidget::initChart()
{
series = new QLineSeries;
chart->addSeries(series);
// series->setUseOpenGL(true);
chart->createDefaultAxes();
chart->axisY()->setRange(-10, 10);
chart->axisX()->setRange(0, 96);
chart->axisX()->setTitleFont(QFont("Microsoft YaHei", 10, QFont::Normal, true));
chart->axisY()->setTitleFont(QFont("Microsoft YaHei", 10, QFont::Normal, true));
chart->axisX()->setTitleText("Time/sec");
chart->axisY()->setTitleText("Speed/m");
chart->axisX()->setGridLineVisible(false);
chart->axisY()->setGridLineVisible(false);
/* hide legend */
chart->legend()->hide();
chartView = new ChartView(chart);
chartView->setRenderHint(QPainter::Antialiasing);
ui->mainHorLayout->addWidget(chartView);
}
void MainWidget::initSlot()
{
connect(timer, SIGNAL(timeout()), this, SLOT(timerSlot()));
connect(ui->stopBtn, SIGNAL(clicked(bool)), this, SLOT(buttonSlot()));
connect(series, SIGNAL(hovered(QPointF, bool)), this, SLOT(tipSlot(QPointF,bool)));
}
void MainWidget::updateData()
{
int i;
QVector<QPointF> oldData = series->pointsVector();
QVector<QPointF> data;
if (oldData.size() < 97) {
data = series->pointsVector();
} else {
/* 添加之前老的数据到新的vector中,不复制最前的数据,即每次替换前面的数据
* 由于这里每次只添加1个数据,所以为1,使用时根据实际情况修改
*/
for (i = 1; i < oldData.size(); ++i) {
data.append(QPointF(i - 1 , oldData.at(i).y()));
}
}
qint64 size = data.size();
/* 这里表示插入新的数据,因为每次只插入1个,这里为i < 1,
* 但为了后面方便插入多个数据,先这样写
*/
for(i = 0; i < 1; ++i){
data.append(QPointF(i + size, 10 * sin(M_PI * count * 4 / 180)));
}
series->replace(data);
count++;
}
void MainWidget::timerSlot()
{
if (QObject::sender() == timer) {
updateData();
}
}
void MainWidget::buttonSlot()
{
if (QObject::sender() == ui->stopBtn) {
if (!isStopping) {
timer->stop();
} else {
timer->start();
}
isStopping = !isStopping;
}
}
void MainWidget::tipSlot(QPointF position, bool isHovering)
{
if (tip == 0)
tip = new Callout(chart);
if (isHovering) {
tip->setText(QString("X: %1 \nY: %2 ").arg(position.x()).arg(position.y()));
tip->setAnchor(position);
tip->setZValue(11);
tip->updateGeometry();
tip->show();
} else {
tip->hide();
}
}
#ifndef MAINWIDGET_H
#define MAINWIDGET_H
#include <QWidget>
#include <QChart>
#include <QLineSeries>
#include <QVector>
#include <QTimer>
#include "chartview.h"
#include "callout.h"
QT_CHARTS_USE_NAMESPACE
namespace Ui {
class MainWidget;
}
class MainWidget : public QWidget
{
Q_OBJECT
public:
explicit MainWidget(QWidget *parent = 0);
~MainWidget();
private:
void wheelEvent(QWheelEvent *event);
void initUI();
void initChart();
void initSlot();
void updateData();
Ui::MainWidget *ui;
ChartView *chartView;
QChart *chart;
Callout *tip;
QLineSeries *series;
QTimer *timer;
quint16 count;
bool isStopping;
private slots:
void timerSlot();
void buttonSlot();
void tipSlot(QPointF position, bool isHovering);
};
#endif // MAINWIDGET_H
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWidget</class>
<widget class="QWidget" name="MainWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>640</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWidget</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0">
<layout class="QVBoxLayout" name="mainVerLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<layout class="QHBoxLayout" name="mainHorLayout"/>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>输入源:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboBox"/>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="stopBtn">
<property name="text">
<string>停止</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="settingBtn">
<property name="text">
<string>设置</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册