Qt文档阅读笔记-QIODevice解析及Audio Example实例解析

目录

 

QIODevice官方解释及个人分析

Audio Example官方实例解析


 

QIODevice官方解释及个人分析

QIODevice类是Qt中I/O设备的接口。
提供了读和写的接口,QIODevice是抽象的不能被实用化。
调用设备之前,要使用open()来设置打开方式(ReadOnly和ReadWrite)。可以使用write()或putChar()向设备写数据
,同样可以使用rad(),raedLine()或readAll()去读设备。当不用的时候调用close()关闭操作。
QIODevice区分了两种设备类型 随机访问设备 和 顺序设备。
随机访问设备:使用seek()可以任意访问位置,可以使用pos()定位文件的位置,QFile和QBuffer都是随机访问设备。
顺序访问设备:不能任意访问位置,数据必须一次性读取,pos()和size()在顺序访问设备里面都不能正常工作。
QTcpSocket和QProcess都是顺序访问设备。
可以使用isSequential()看看他属于什么设备类型。

当能读时会发出readyRead()信号。调用bytesAvailable()查看当前能读取的字节数。向设备写数据时会发射
bytesWritten()信号。调用bytesToWrite()来查看待写入的字节数。
QIODevice的子类QTcpSocket和QProcess都是异步处理的,但也可以使用waitForReadyRead()和waitForBytesWritten
()去让他阻塞。

  QProcess gzip;
  gzip.start("gzip", QStringList() << "-c");
  if (!gzip.waitForStarted())
      return false;

  gzip.write("uncompressed data");

  QByteArray compressed;
  while (gzip.waitForReadyRead())
      compressed += gzip.readAll();

这里可以看到QProcess这个顺序访问设备开启一个外部进程,并且使用了阻塞的方式,如果这个调用是放在GUI线程里面的,那么肯定会有问题,界面肯定会卡住。

注意:这个问题一点要注意,在本人参与的项目中,很多人写的程序,都喜欢用GUI线程去读东西,一旦处理不好,就会造成阻塞。建议Qt开发经验或技巧不足的朋友,多多使用线程去读写这些东西,不要使用GUI线程去做(其实在Qt中有很多方式和技巧可以在GUI线程里面操作,同时也不会阻塞GUI线程)

 

 

Audio Example官方实例解析

这里是官方的实例,我先把代码贴上,因为版权占用太多,我把版权去掉了,但这个例子是Qt官方提供的,特产声明(本人励志做一个有节操的程序员,不仅要看破,而且要说破)

Qt文档阅读笔记-QIODevice解析及Audio Example实例解析_第1张图片

源码如下:

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include 
#include 

QT_CHARTS_BEGIN_NAMESPACE
class QLineSeries;
class QChart;
QT_CHARTS_END_NAMESPACE

QT_CHARTS_USE_NAMESPACE

class XYSeriesIODevice;

QT_BEGIN_NAMESPACE
class QAudioInput;
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = 0);
    ~Widget();

private:
    XYSeriesIODevice *m_device;
    QChart *m_chart;
    QLineSeries *m_series;
    QAudioInput *m_audioInput;
};

#endif // WIDGET_H

xyseriesiodevice.h

#ifndef XYSERIESIODEVICE_H
#define XYSERIESIODEVICE_H

#include 
#include 

QT_CHARTS_BEGIN_NAMESPACE
class QXYSeries;
QT_CHARTS_END_NAMESPACE

QT_CHARTS_USE_NAMESPACE

class XYSeriesIODevice : public QIODevice
{
    Q_OBJECT
public:
    explicit XYSeriesIODevice(QXYSeries * series, QObject *parent = 0);

protected:
    qint64 readData(char * data, qint64 maxSize);
    qint64 writeData(const char * data, qint64 maxSize);

private:
    QXYSeries *m_series;
};

#endif // XYSERIESIODEVICE_H

main.cpp

#include 
#include "widget.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();
    
    return a.exec();
}

widget.cpp

#include "widget.h"
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include "xyseriesiodevice.h"

QT_CHARTS_USE_NAMESPACE

Widget::Widget(QWidget *parent)
    : QWidget(parent),
      m_device(0),
      m_chart(0),
      m_series(0),
      m_audioInput(0)
{
    m_chart = new QChart;
    QChartView *chartView = new QChartView(m_chart);
    chartView->setMinimumSize(800, 600);
    m_series = new QLineSeries;
    m_chart->addSeries(m_series);
    QValueAxis *axisX = new QValueAxis;
    axisX->setRange(0, 2000);
    axisX->setLabelFormat("%g");
    axisX->setTitleText("Samples");
    QValueAxis *axisY = new QValueAxis;
    axisY->setRange(-1, 1);
    axisY->setTitleText("Audio level");
    m_chart->setAxisX(axisX, m_series);
    m_chart->setAxisY(axisY, m_series);
    m_chart->legend()->hide();
    m_chart->setTitle("Data from the microphone");

    QVBoxLayout *mainLayout = new QVBoxLayout;
    mainLayout->addWidget(chartView);
    setLayout(mainLayout);

    QAudioFormat formatAudio;
    formatAudio.setSampleRate(8000);
    formatAudio.setChannelCount(1);
    formatAudio.setSampleSize(8);
    formatAudio.setCodec("audio/pcm");
    formatAudio.setByteOrder(QAudioFormat::LittleEndian);
    formatAudio.setSampleType(QAudioFormat::UnSignedInt);

    QAudioDeviceInfo inputDevices = QAudioDeviceInfo::defaultInputDevice();
    m_audioInput = new QAudioInput(inputDevices,formatAudio, this);

    m_device = new XYSeriesIODevice(m_series, this);
    m_device->open(QIODevice::WriteOnly);

    m_audioInput->start(m_device);
}

Widget::~Widget()
{
    m_audioInput->stop();
    m_device->close();
}

xyseriesiodevice.cpp

#include "xyseriesiodevice.h"
#include 

XYSeriesIODevice::XYSeriesIODevice(QXYSeries * series, QObject *parent) :
    QIODevice(parent),
    m_series(series)
{
}

qint64 XYSeriesIODevice::readData(char * data, qint64 maxSize)
{
    Q_UNUSED(data)
    Q_UNUSED(maxSize)
    return -1;
}

qint64 XYSeriesIODevice::writeData(const char * data, qint64 maxSize)
{
    qint64 range = 2000;
    QVector oldPoints = m_series->pointsVector();
    QVector points;
    int resolution = 4;

    if (oldPoints.count() < range) {
        points = m_series->pointsVector();
    } else {
        for (int i = maxSize/resolution; i < oldPoints.count(); i++)
            points.append(QPointF(i - maxSize/resolution, oldPoints.at(i).y()));
    }

    qint64 size = points.count();
    for (int k = 0; k < maxSize/resolution; k++)
        points.append(QPointF(k + size, ((quint8)data[resolution * k] - 128)/128.0));

    m_series->replace(points);
    return maxSize;
}

这里只提下这个XYSeriesIODevice这个类,

此类为QIODevice的子类。

这里提出2个问题:

为毛要重写readData()和writeData()这两个函数?

为毛readDatat()里面是空的而writeData()这函数却对QXYSeries进行了操作?

下面来依次回答这2个问题!

通过官方文档得到readData()和writeData()为纯虚函数,所以一定要写上去。

第二个问题,因为QAuidoInput::start(QIODevice *device)中把音频数据发送到device中了,他是以写入的形式发到device中的,内部肯定是有个回调,回调了writeData(),所以在那里面写曲线即可。
 

 

你可能感兴趣的:(文档阅读笔记,C/C++,Qt)