我无法获得QSoundEffect在单独的线程中播放。您能否告诉我为什么声音仅由第一个代码片段播放而不由第二个代码片段播放?

//main.cpp

#include <QCoreApplication>
#include "SoundThread.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    // #1
    QSoundEffect alarmSound;
    alarmSound.setSource(QUrl::fromLocalFile(":/sound"));
    alarmSound.play();

    /* #2
    SoundThread thread;
    thread.start();
    thread.wait();
    */

    return a.exec();
}


//SoundThread.h

#ifndef SOUNDTHREAD_H
#define SOUNDTHREAD_H

#include <QThread>
#include <QtMultimedia/QSoundEffect>

class SoundThread : public QThread
{
    Q_OBJECT
    private:
        void run()
        {
            QSoundEffect alarmSound;
            alarmSound.setSource(QUrl::fromLocalFile(":/sound"));
            alarmSound.play();
            while(true){}
        }
};

#endif // SOUNDTHREAD_H

最佳答案

Qt documentation on QThread中:-



由于您已经继承自QThread,因此现在有了一个不调用exec()的运行函数。因此,事件循环未运行,并且很可能需要播放声音效果。

调用exec()应该代替while(true){},因为exec()将等待直到调用exit()为止。

根据"How to Really Truly Use QThreads...",通过将对象移动到线程来正确执行此操作

class Worker : public QObject
{
    Q_OBJECT

public:
    Worker();
    ~Worker();

public slots:
    void PlaySoundEffect();

signals:
    void finished();
    void error(QString err);

private:
    // store the sound effect, so we can reuse it multiple times
    QSoundEffect* m_pAlarmSound;

private slots:

};


Worker::Worker()
{
    m_pAlarmSound = new QSoundEffect;
    m_pAlarmSound.setSource(QUrl::fromLocalFile(":/sound"));
}

Worker::~Worker()
{
    delete m_pAlarmSound;
    m_pAlarmSound = nullptr; // C++ 11
}

void Worker::PlaySoundEffect()
{
    m_pAlarmSound->play();
}

// setup the worker and move it to another thread...
MainWindow::MainWindow
{
    QThread* thread = new QThread;
    Worker* worker = new Worker();
    worker->moveToThread(thread);
    connect(worker, SIGNAL(error(QString)), this, SLOT(errorString(QString)));
    connect(thread, SIGNAL(started()), worker, SLOT(PlaySoundEffect()));
    connect(worker, SIGNAL(finished()), thread, SLOT(quit()));
    connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
    connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
    thread->start();

   // We can also connect a signal of an object in the main thread to the PlaySoundEffect slot

   // Assuming MainWindow has declared a signal void Alert();
   connect(this, &MainWindow::Alert, worker, &Worker::PlaySoundEffect);

   // Then play the sound when we want: -

   emit Alert();
}

尽管这看起来很费劲,但以这种方式进行操作有许多优点。例如,如果您有很多声音效果,则继承QThread的方法意味着您将为每个声音效果创建一个线程,这并不理想。

通过将枚举传递到PlaySoundEffect插槽中,我们可以轻松扩展上述Worker对象,以保存一系列音效并播放所需的音效。由于此线程不断运行,因此播放声音将产生较少的延迟;在运行时创建线程需要时间和资源。

关于multithreading - 在QThread中播放QSoundEffect,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/23777441/

10-12 14:36
查看更多