如何同步制作QSound?

How to make QSound synchronously?

如何同步制作QSound?

我有一个退出按钮。如果我点击它我想播放声音然后退出程序。 QSound是异步的,不知道怎么弄成同步的

你真的不需要同步播放声音。任何可能阻塞 GUI 线程超过 0.10 秒的事情都不应该在那里完成,查看 here 了解更多信息。

既然你愿意在用户点击退出按钮时播放声音,我认为使用 QSoundEffect is better for your case, from the docs:

This class allows you to play uncompressed audio files (typically WAV files) in a generally lower latency way, and is suitable for "feedback" type sounds in response to user actions (e.g. virtual keyboard sounds, positive or negative feedback for popup dialogs, or game sounds).

QSoundEffect 有一个信号 playingChanged(),您可以利用它仅在声音播放完毕后关闭应用程序。我不知道为什么 QSound 没有类似的信号。

这里是一个最小的例子,解释了如何做到这一点:

#include <QtWidgets>
#include <QtMultimedia>

class Widget : public QWidget {
public:
    explicit Widget(QWidget* parent= nullptr):QWidget(parent) {
        //set up layout
        layout.addWidget(&exitButton);
        //initialize sound effect with a sound file
        exitSoundEffect.setSource(QUrl::fromLocalFile("soundfile.wav"));
        //play sound effect when Exit is pressed
        connect(&exitButton, &QPushButton::clicked, &exitSoundEffect, &QSoundEffect::play);
        //close the widget when the sound effect finishes playing
        connect(&exitSoundEffect, &QSoundEffect::playingChanged, this, [this]{
            if(!exitSoundEffect.isPlaying()) close();
        });
    }
    ~Widget() = default;
private:
    QVBoxLayout layout{this};
    QPushButton exitButton{"Exit"};
    QSoundEffect exitSoundEffect;
};

//sample application
int main(int argc, char* argv[]){
    QApplication a(argc, argv);

    Widget w;
    w.show();

    return a.exec();
}

注意上面的解决方案在音效播放完毕后才会关闭window

另一种方法似乎对应用程序用户更敏感,即关闭 window,在 window 关闭时播放声音,然后在播放结束后退出应用程序。但这需要在应用程序级别 (quitOnLastWindowClosed) 关闭最后一个 window 时禁用隐式退出。

由于禁用隐式退出,您必须在程序的每个可能的退出路径上添加 qApp->quit();。这是显示第二种方法的示例:

#include <QtWidgets>
#include <QtMultimedia>

class Widget : public QWidget {
public:
    explicit Widget(QWidget* parent= nullptr):QWidget(parent) {
        //set up layout
        layout.addWidget(&exitButton);
        //initialize sound effect with a sound file
        exitSoundEffect.setSource(QUrl::fromLocalFile("soundfile.wav"));
        //play sound effect and close widget when exit button is pressed
        connect(&exitButton, &QPushButton::clicked, &exitSoundEffect, &QSoundEffect::play);
        connect(&exitButton, &QPushButton::clicked, this, &Widget::close);
        //quit application when the sound effect finishes playing
        connect(&exitSoundEffect, &QSoundEffect::playingChanged, this, [this]{
            if(!exitSoundEffect.isPlaying()) qApp->quit();
        });
    }
    ~Widget() = default;
private:
    QVBoxLayout layout{this};
    QPushButton exitButton{"Exit"};
    QSoundEffect exitSoundEffect;
};

//sample application
int main(int argc, char* argv[]){
    QApplication a(argc, argv);
    //disable implicit quit when last window is closed
    a.setQuitOnLastWindowClosed(false);

    Widget w;
    w.show();

    return a.exec();
}