标签 Qt 下的文章

在 qt 中想要把 qvector 转化为原始数据构成的数组,有几种方法:

  1. 直接使用循环读取
double *bytes = new double[vec.size()];
for (int i = 0; i < vec.size(); ++i) {
   bytes[i] = vec[i];
}
QByteArray array = QByteArray::fromRawData(reinterpret_cast<void*>(bytes));
delete []bytes;
  1. 使用 qvector 自带的 constData 和 data

    QByteArray data = QByteArray::fromRawData(
        reinterpret_cast<const char*>(vec.constData()),
        sizeof(double) * vec.size()
    );
  2. 使用 stream 来输出
    QVector<double> vec;
    QByteArray data;
    QDataStream stream(&data, QIODevice::WriteOnly);
    for (auto x : vec)
    stream << x;

或者

QVector<double> vec;
// populate vector
QByteArray data;
QDataStream stream(&data, QIODevice::WriteOnly);
stream << vec;

qt 中直接使用 c 语言文件,c 文件可以直接包含,h 文件包含的时候,需要在 c++ 中添加额外信息,如下:


#ifdef __cplusplus
extern "C" {

#include "c头文件.h"

#endif
#ifdef __cplusplus
}
#endif

1. 概念:

坐标轴-QAbstractAxis:

图表中,一般都有 X、Y 坐标轴,复杂一些的还带有 Z 轴。对应到 Qt 的图表也有 X、Y 轴对象。但是今天,我们先不展开介绍。如果我们不创建轴坐标对应的对象,可以使用 Qt 的默认轴对象。后面我们会介绍用法。

系列-QAbstractSeries:

不论是曲线、饼图、棒图还是其他图表,其中展示的内容本质都是数据。一条曲线是一组数据,一个饼图也对应一组数据。在 Qt Charts 中,这些一组组的数据被称作系列。对应不同类型的图表 Qt 提供了不同的系列。系列除了负责存储、访问数据,应该还提供了数据的绘制方法,比如折线图和曲线图分别对应 QLineSerie 和 QSPLineSerie。我们可以用不同的系列达到不同的展示目的。

图例-Legend:

类似于 Excel,Qt Charts 中也提供了图例,并且还可以显示或者隐藏图例。

图表-QChart:

Qt 提供了 QChart 类来封装前面所说的内容,比如坐标轴、系列、图例等。QChart 承担了一个组织、管理的角色。QChart 派生自 QGraphicsObject,因此它实际上是一个图元 item。我们可以从 QChart 获取到坐标轴对象、数据系列对象、图例等等,并且可以设置图表的主题、背景色等样式信息。

视图-QChartView:

负责 QChart 的展示。QChart 本身只负责图表内容的组织、管理。图表的展示由视图负责,这个视图就是 QChartView。QChartView 派生自 QGraphicsView,只是它专门提供了几个面向 QChart 的接口,比如 setChart(QChart*)等。

2. 使用

要使用QtCharts 需要几个步骤:

1. pro 文件中 修改

QT       += charts

2. 把 chart 相关的头文件放在 ui 相关的头文件上面,否则会导致 编译错误,找不到 chartView 相关。

#include <QtCharts/QChartView>
#include <QtCharts/QLineSeries>
QT_CHARTS_USE_NAMESPACE

3. 在 ui 中放入 widget,然后右键 widget,选择 promote to 选项,选项卡里面:

base class name: QWidget promoted class name: QChartView Header file: QChartView

4. 注意 setChart 之后需要把 旧的给删除掉。否则内存占用越来越多。

    QChart *oldChart = ui->widget->chart();
    QChart *chart = new QChart();
    ui->widget->setChart(chart);

    if (oldChart != nullptr) {
        delete  oldChart;
    }

参考: https://www.cnblogs.com/ybqjymy/p/13253152.html https://www.cnblogs.com/linuxAndMcu/p/11381839.html

3. charts 如果需要图像进行滚动显示,那么可以参考自带的例程 dynamicspline;如果需要再图像上显示具体的 坐标,可以参考自带例程 callout.

参考: https://www.cnblogs.com/shenLong1356/p/11230390.html

4. charts 里面使用 chart.scroll(x, 0); 这个 x 注意不是 chart.plotArea().width() / m_axis.tickCount(); 而应该是 m_chart->plotArea().width() / (X_RANGE_MAX - X_RANGE_MIN); 是和 setRange 这个设置相对应,而不是和 setTickCount 这个设置的值相对应。

1. 首先把 release 版本的 exe 复制到其他文件夹,比如 Desktop\test

2. 使用开始菜单中 qt 里面的控制台窗口,使用 cd 命令打开到 Desktop\test 位置,然后使用打包命令:

windeployqt test.exe

然后 qt 会自动把依赖复制到 Desktop\test 文件夹里面。

3. 安装 enigma virtual box.

4. 使用 enigma virtual box.

  1. enter input file name 后面的 browse 里面选择,Desktop\test 中的 test.exe 文件。
  2. 左下角 files 里面的 add 中选择 add folder recursive 里面选择 Desktop\test 文件夹。
  3. 点击右下角 process 进行封包。

1. qt 中两个字符的字符串直接转换为 hex,类似于 ”1A" 要转换成 16进制的 0x1A,使用 int QString::toInt(bool *ok, int base)。具体如下:

QString  str = "0x1A";
int value = str.toInt(nullptr, 16);
uint8_t tmp = static_cast<uint8_t>(str.toUInt(nullptr, 16));

2. 如果是字符串本身转换为16进制,类似于 "1" 要转换成 0x31,使用 QByteArray,其中有方法 toLatin1、toLocal8Bit, Latin1代表ASCII,Local8Bit代表unicode

QByteArray ar = str.toLatin1().toHex();

3. 如果是16进制转为 QByteArray,可以用 setNum 函数

QByteArray().setNum( hex )

今天参考 qt4 的书籍,在 qt5 的平台上面,用了 QSignalMapper,结果收到警告“ QSignalMapper is deprecated"。

经过一番查找,找到了相应的说明, 参考自:https://doc.qt.io/qt-5/qsignalmapper.html This class is obsolete. It is provided to keep old source code working. We strongly advise against using it in new code. 官方建议 qt5 里面使用 lambda 方式表达。

下面是旧的方式:

class ButtonWidget : public QWidget
{
    Q_OBJECT

public:
    ButtonWidget(const QStringList &texts, QWidget *parent = 0);

signals:
    void clicked(const QString &text);

private:
    QSignalMapper *signalMapper;
};
ButtonWidget::ButtonWidget(const QStringList &texts, QWidget *parent)
    : QWidget(parent)
{
    signalMapper = new QSignalMapper(this);

    QGridLayout *gridLayout = new QGridLayout;
    for (int i = 0; i < texts.size(); ++i) {
        QPushButton *button = new QPushButton(texts[i]);
        connect(button, SIGNAL(clicked()), signalMapper, SLOT(map()));
        signalMapper->setMapping(button, texts[i]);
        gridLayout->addWidget(button, i / 3, i % 3);
    }

    connect(signalMapper, SIGNAL(mapped(QString)),
            this, SIGNAL(clicked(QString)));

    setLayout(gridLayout);
}

This class was mostly useful before lambda functions could be used as slots. The example above can be rewritten simpler without QSignalMapper by connecting to a lambda function. 下面是新的方式:

ButtonWidget::ButtonWidget(const QStringList &texts, QWidget *parent)
    : QWidget(parent)
{
    QGridLayout *gridLayout = new QGridLayout;
    for (int i = 0; i < texts.size(); ++i) {
        QString text = texts[i];
        QPushButton *button = new QPushButton(text);
        connect(button, &QPushButton::clicked, [=] { clicked(text); });
        gridLayout->addWidget(button, i / 3, i % 3);
    }
    setLayout(gridLayout);
}

今天用 qt 中的按键的时候,希望按键有两种状态,通过 clicked(bool) 发送信号给槽,结果一直发的是 false,不能为 true,后来终于找到问题了,有两种解决方法。

  1. 在 button 的属性里面选择 checkable
  2. 在代码里面增加 yourButton->setCheckable(true)

使用 qextserialport 编写串口助手的时候,提示找不到 __imp_SetupDiGetDeviceRegistryPropertyW,经过摸索有以下两种解决方法:

第一种: 把相应的源文件手动加入到项目中,不要加入 qextserialport.pri 文件,在 项目 pro 文件中,按照当前的系统平台,加入库文件,比如说: win 平台,需要加入

win32:LIBS             += -lsetupapi -ladvapi32 -luser32

第二种: 不要手动加入源文件到项目中。在 项目 pro 文件中加入 qextserialport.pri 文件。

include(3rdparty/qextserialport/src/qextserialport.pri)

相比较而言,明显是第二种更加方便。