1.界面编辑
首先我们选择对应的控件来对所需界面进行布局,布局如下:

界面上部分用的是文本编辑框可以用来输入要转化为语音的文本,选择左边的控件为Text Edit下面我们选择的是两个Group Box用来将我们的选项进行分组,然后我们选择Label控件并编辑成相应的文字用于对后面的下拉列表选项进行说明,后面的下拉列表选择Combo Box控件该控件可以放入字符串图片的信息供我们进行下拉选择,中间的分割线选择Vertical Line用来显示分割,右边同样先选择Label控件用来说明后面的滑动条信息和数字信息,下面我们选择Push Button控件用来当功能按钮使用。
2.程序编写
在qt中提供了多个界面主题的设置可以根据自己的需要进行主题设置,若要选择其他主题要加入如下程序:
cpp
a.setStyle(QStyleFactory::create("fusion")); //使用fusion这个主题
我选择的是fusion主题,然后我们就要对界面和后面事件的处理进行一些初始化。
cpp
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
QStringList list = QTextToSpeech::availableEngines(); //获取支持的语音引擎
for(QString &engine : list) //循环遍历该链表中的语音引擎
{
qDebug() << "engine:" << engine;
ui->comboBox_engine->addItem(engine); //将遍历得到的语音引擎添加到comboBox中
}
tts = new QTextToSpeech(this); //指定父对象
ui->label_rate->setNum(50);
ui->label_volume->setNum(50);
ui->label_ptich->setNum(50); //设置语音标签初始值
}
可见该初始化我们在构造函数中进行,首先我们获取到系统所支持的语音引擎链表,然后通过遍历该链表将其中的语音引擎显示出来,并将其添加到对应的comboBox控件中。然后我们定义一个指针用来指向我们创建的QTextToSpeech类对象其中的参数填入this用来指向父对象就是该类,该指针后面可以用于我们来访问此类的方法。最后我们给语音设置的标签设置初始数字,对应将划动条的相关参数也赋值,该参数的调整在我们上一章所讲到的对应类的属性编辑那个栏目进行编辑如下:

初始化完成后我们就要来对处理对应事件的槽函数进行编写了,首先对于语音引擎的槽函数编写如下:
cpp
void Widget::on_comboBox_engine_activated(int index)
{
qDebug() << "on_comboBox_engine_activated:" << index ;
ui->comboBox_language->clear(); //每次点击下拉列表框时先清除box中原来的选项防止重复
QVector<QLocale> languages = tts->availableLocales(); //不能直接使用类名加::的方式调用该方法,以为在qt中这个方法不静态方法是普通方法
if(tts != nullptr) //将返回的QLocale类对象装入QVector容器中
{
for(auto &local : languages)
{
qDebug() << "local:" << local;
qDebug() << "local country" << local.country(); //使用QLocale类对象引用调用该方法显示该类中的国家信息
qDebug() << "local country" << QLocale::countryToString(local.country()); //将国家信息转化为字符串
qDebug() << "local language"<< QLocale::languageToString(local.language()); //将语言信息转化为字符串
qDebug() << "local script" << QLocale::scriptToString(local.script()); //将描述信息转化成字符串
ui->comboBox_language->addItem(QString(tr("%0-%1-%2")
.arg(QLocale::countryToString(local.country()))
.arg(QLocale::scriptToString(local.script()))
.arg( QLocale::languageToString(local.language()))
),QVariant(local));//tr()是国际翻译函数可以将传入的字符串变成可翻译文本,也可以用于字符串的拼接
//其中%012是占位符,对应后面的.arg
//QVariant将local对象包装为通用数据类型,并采用联合体将语言信息于下拉列表关联起来
}
}
}
首先我们在进入该槽函数时将comboBox_language清除,防止每次进入时都将该控件进行值选项的添加导致重复,然后通过文本转语音类的指针访问获取语言信息的方法,让后将其返回值放入到QVector容器中,判空后我们遍历该容器中的值,通过引用将该语言信息中的国家,语言,描述信息提出出来并使用*ToString的方法来将其转换成字符串。然后我们通过QString直接初始化创建一个字符串对象将其通过addItem函数填入到comboBox下拉列表控件中,tr()函数是将文本转化成可翻译字符串的函数且可以进行格式化编辑,所以我们用其进行字符串的拼接,其中0,1,2分别表示后面的arg中的字符串,然后我们使用QVariant将local对象包装为通用数据类型,并采用联合体将语言信息于下拉列表关联起来,我们就完成了对第一个下拉列表的槽函数的编写,然后界面如下:

接下来我们对第二个下拉列表槽函数的编写,程序及详解如下:
cpp
void Widget::on_comboBox_language_activated(int index)
{
qDebug() << "on_comboBox_language_activated:" << index;
ui->comboBox_name->clear(); //每次进入到该程序前先清除该box中的成员
if(tts != nullptr)
{
tts->setLocale(ui->comboBox_language->currentData().toLocale()); //设置语言
QVector<QVoice> voices = tts->availableVoices(); //获取有效语音包
for(QVoice &voice : voices)
{
qDebug() << "gender:" << QVoice::genderName(voice.gender()); //获取语音性别
qDebug() << "age :" << QVoice::ageName(voice.age()); //获取语音年龄
qDebug() << "name :" << voice.name(); //获取语音姓名
ui->comboBox_name->addItem(QString(tr("%0(%1)")
.arg(voice.name())
.arg(QVoice::genderName(voice.gender()))
));
}
}
}
在该槽函数中传入的参数index是索引值,我们首先在进入该槽函数时也要先将comboBox_name控件中的内容清除防止多次进入该槽函数后对该下拉列表进行内容的重复添加。然后判空,注意判空是非常重要的避免空指针的使用导致程序死机,然后我们通过调用setLocale函数设置该下拉列表中的语音。然后通过tts指针来调用获取有效语音包的函数获取到系统的有效语音包并放入到QVector容器中,然后遍历该容器中的语音包内容通过访问类中的成员函数获取到相应的值并转化成字符串,因为下拉列表中只能填入字符串和图片所必须要将其转化成字符串。同样使用tr进行字符串的拼接然后将该字符串填入到combobox_name下拉列表中。
cpp
void Widget::on_comboBox_name_activated(int index)
{
if(tts != nullptr)
{
QVector<QVoice> voices = tts->availableVoices(); //获取有效语音包
tts ->setVoice(voices[index]); //设置语音包
}
}
然后就是对第三个下拉列表的槽函数的编写,我们依旧先判空,然后通过tts指针调用该类中获取有效语音包的函数,然后通过传入的索引值index设置语音包,完成对语音包的选择功能。完成后效果如下:

下拉列表槽函数编写完成后我们就要对右边的滑动条槽函数进行编写如下:
cpp
void Widget::on_horizontalSlider_rate_valueChanged(int value)
{
ui->label_rate->setNum(value); //将该标签的值设置为该滑动条的值,即可将两值关联起来
if(tts != nullptr)
{
double newvalue = (value - 50) / 50.0; //将0到100的整形转化成-1到1的浮点数
tts->setRate(newvalue); //再将得到的值作为参数传入设置系统语速
}
}
void Widget::on_horizontalSlider_volume_valueChanged(int value)
{
ui->label_volume->setNum(value); //将该标签的值设置为该滑动条的值,即可将两值关联起来
if(tts != nullptr)
{
double newvalue = value / 100.0; //将0到100的整形转化成0到1的浮点数
tts->setVolume(newvalue); //再将得到的值作为参数传入设置系统语速
}
}
void Widget::on_horizontalSlider_pitch_valueChanged(int value)
{
ui->label_ptich->setNum(value); //将该标签的值设置为该滑动条的值,即可将两值关联起来
if(tts != nullptr)
{
double newvalue = (value - 50) / 50.0; //将0到100的整形转化成-1到1的浮点数
tts->setPitch(newvalue); //再将得到的值作为参数传入设置系统语速
}
}
我们通过选择对应事件改变的槽函数来通过事件的改变来完成槽函数的编写,可见我们选择的是若滑动条的值改变了我们槽函数的传入参数就会变,在如上的槽函数中我们首先都是将该滑动条的值设置成对应得label控件,对于音速滑动条的槽函数我们判空后通过tts指针调用setRate设置音速的成员函数来设置系统的音速,我们通过查看该函数可知该函数的参数值是-1到1的double类型所以我们要先进行一个数值的转化,然后对于音量和音调的设置同样也是对相应类中已有成员函数的调用即可。完成后我们最后进行按键控件的编写,程序如下:
cpp
void Widget::on_pushButton_play_clicked()
{
if(tts != nullptr)
{
tts->say(ui->textEdit->toPlainText()); //将textEdit中的内容播报出来
}
}
void Widget::on_pushButton_pause_clicked()
{
if(tts != nullptr)
{
tts->pause(); //暂停播报内容
}
}
void Widget::on_pushButton_resume_clicked()
{
if(tts != nullptr)
{
tts->resume(); //继续播报内容
}
}
void Widget::on_pushButton_stop_clicked()
{
if(tts != nullptr)
{
tts->stop(); //停止播报内容
}
}
分别通过tts指针调用say,pause,resume,stop函数来对文本转语音后播放,暂停,继续,停止的控制。最后编写完效果如下:
