1.界面设置
首先我们选择相应的控件并进行如下界面布局:

首先我们在创建文件是要选择窗体为主窗体,选择了主窗体之后我们才能编辑左上角的工具栏,这里我们的工具栏要设置的功能就是语言转化功能。然后上面选择的控件是LCD Number即数码管显示通过数码管来显示我们要计数的时间,数码管对象属性的设置如下:

然后就是中间部分的两个按钮选择Push Button控件,下面部分我们要选择的控件是table view列表显示,用于显示我们秒表的计数值。
2.程序编写与功能实现
首先我们有了界面之后我们要做的就是对该界面进行初始化,让我们以打开该软件就有一个初始化的显示界面和进行一些初始化的程序配置。首先是主题的选择程序如下:
cpp
a.setStyle(QStyleFactory::create("fusion")); //设置主题样式为"fusion"
和上一个软件一样我们选择fusion作为我们界面的主题。然后我们在窗口构造函数中进行我们的初始化,程序和详解如下:
cpp
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->lcdNumber->display("00:00.00");
timer = new QTimer(this); //让该指针指向QTimer类的对象
connect(timer,&QTimer::timeout,this,&MainWindow::timeout_slot);//参数:发送信号者,发送的说明信号,接收信号者,信号处理函数
model = new QStandardItemModel(this); //让该指针指向该类对象
//设置字段
model->setColumnCount(2); //设置该数据模型为2列
model->setHeaderData(0,Qt::Horizontal,"序号"); //设置第一列名为序号
model->setHeaderData(1,Qt::Horizontal,"数值"); //设置第二列名为数值
ui->tableView->setModel(model); //将显示模型与数据模型相关联
ui->tableView->horizontalHeader()->setDefaultSectionSize(199); //设置默认列宽度
ui->tableView->verticalHeader()->setHidden(true); //将竖直头设置为隐藏
ui->tableView->setEditTriggers(QAbstractItemView::NoEditTriggers); //设置单元表格编辑为只读模式
ui->tableView->setSelectionBehavior(QAbstractItemView::SelectRows);//设置选中表格时选中整行
}
首先对数码管的显示进行了初始化通过display函数来让其显示该字符串。然后我们创建一个QTimer类的对象让指针指向该对象,该类中有与时间设置相关的函数,让该指针可以访问该类中的成员函数。然后通过函数connect将到达时间与到达时间的处理函数来连接起来,即我们定义的槽函数,该函数的参数第一个是发送信号者,第二个是发送的什么信号,第三个是接收信号者,第四个是对该信号处理的槽函数。然后我们再创建一个QStandardItemModel类的对象,让model指针指向该对象,该类是标准列表模式的类用来保存列表数据。然后我们同过model指针来色湖之该数据模型即保存列表数据的头数据,即我们要显示的秒表记录数据的说明。然后通过setModel函数将该列表数据设置到我们的列表显示控件中,即将显示模型与数据模型关联起来。因为默认该列表数据的头宽度是可以进行调整的,所以我们将其默认值通过函数设成默认值让其不可调整。并通过setHidden将竖直的头设置为隐藏。并设置该列表显示为只读不能修改,因为该软件就是对时间的记录,不需要对记录的数据进行修改。然后设置选中为选中一行有更好的显示。完成这些初始化后我们的界面如下:

接下来我们实现数码管控件对应得功能,程序即详解如下:
cpp
void MainWindow::timeout_slot() //定时时间到的槽函数
{
msec ++;
if(msec >= 100)
{
msec = 0;
sec ++;
if(sec >= 60)
{
sec = 0;
min ++;
if(min >= 60)
{
min = 0;
}
}
}
ui->lcdNumber->display(QString::asprintf("%02d:%02d.%02d",min,sec,msec)); //格式化拼接字符串并显示在lcdNumber控件上
}
我们通过分别定义分秒毫秒三个值来对时间进行记录,然后则三个值通过QString类下的静态函数asprintf格式化成字符串然后进行显示就完成了数码管数值显示变化的功能。然后我们来实现第一个按钮控件的功能:
cpp
void MainWindow::on_pushButton_start_clicked(bool checked)
{
qDebug() << "on_pushButton_start_clicked:" << checked;
ischecked = checked;
if(checked == true)
{
timer->start(10);//开始计时,时间10ms
if(language)
{
ui->pushButton_start->setText("停止计时");
ui->pushButton_reset->setText("计数");
}
else
{
ui->pushButton_start->setText("StopCount");
ui->pushButton_reset->setText("Count");
}
}
else
{
timer->stop(); //停止计时
if(language)
{
ui->pushButton_start->setText("开始计时");
ui->pushButton_reset->setText("复位计数");
}
else
{
ui->pushButton_start->setText("StartCount");
ui->pushButton_reset->setText("ResetCount");
}
}
}
在该控件的槽函数中我们首先通过一个变量来保存了进入该槽函数是按键状态的布尔值,这个值在后会有用到。然后我们判断传入参数的bool值来判断该按键否被按下。当按下时我们通过start函数开始时间并通过判断语言类型来对该控件文本进行不同语言的显示,当判断状态没有在按下状态时我们就停止计时,来通过该按键对时间开始和停止进行控制,实现效果如图:


然后我们继续实现第二个按键的功能,程序及详解如下:
cpp
void MainWindow::on_pushButton_reset_clicked()
{
if(ui->pushButton_start->isChecked())//计数
{
qDebug() << QString::asprintf("%02d:%02d.%02d",min,sec,msec);
model->setItem(lineCount,0,new QStandardItem(QString::asprintf("%03d",lineCount+1))); //创建第一列内容
model->setItem(lineCount,1,new QStandardItem(QString::asprintf("%02d:%02d.%02d",min,sec,msec)));//创建第二列内容
model->item(lineCount,0)->setTextAlignment(Qt::AlignCenter); //设置条目中对应行列的文本排列为中心排列
model->item(lineCount,1)->setTextAlignment(Qt::AlignCenter); //设置条目中对应行列的文本排列为中心排列
ui->tableView->setModel(model); //将上面的文本模型关联到显示模型中
lineCount++; //转到下一行
}
else//复位计数
{
min = 0 ; sec = 0 ; msec = 0;
ui->lcdNumber->display(QString::asprintf("%02d:%02d.%02d",min,sec,msec));
model->removeRows(0,lineCount); //将数据模型中的行移除从0到lineCount
lineCount = 0;
}
}
在该控件槽函数中我们首先通过判断第一个按键的状态,若状态为按下即表示该按键的功能要实现的时计数功能即将时间给记录下来,当第一个按键状态为松开时,该按键要实现的功能应该是复位计数功能即将记录的数据和数码管显示的数据清除。在计数功能中我们首先通过model指针调用setItem函数来设置列表要保存的数据,其中lineCount变量从0开始,表示列表中的第一行数据,但是对于我们要显示的序号值我们要从1开始所以我们对lineCount进行了加1。通过创建QStandardItem对象并直接初始化然后设置到该列表对应列中我们就可以对记录的数据进行保存了。然后我们通过setTextAlignment函数设置列中的文本为中心排列,让其显示在中心。然后进行该列表数据关联到列表显示中显示出来,最后linecount加1转到下一行。对于复位计数功能的实现我们就是将对应的分秒毫秒值进行归零,然后转化成字符串显示到数码管上是数码管的实现归零,然后通过removeRows移除一行列表数据的函数,将列表数据从0开始到lineCount行数据全部移除,然后将lineCount归零,便于下次计数时我们从标号为0的第一行开始。接下来就是对左上角选项栏控件的功能实现,我们先进行配置如下:

通过actiong编辑器对其进行以上配置,然后我们对其槽函数进行编写,程序及详解如下:
cpp
void MainWindow::on_action_language_triggered()
{
QTranslator translator;
translator.load("translations/en_US.qm"); //将语言转化编译文件装载
if(language) //将语言转换成英文
{
language = false;
QApplication::installTranslator(&translator); //安装一个翻译对象,参数是翻译对象的地址该地址下的文件已经被编译成.qm文件了,将用tr和对象编辑中可以进行语言转化的文字进行转化
ui->retranslateUi(this); //重新初始化ui界面
model->clear(); //清除数据保存模型里面的内容
lineCount = 0; //清除行号
model->setColumnCount(2); //设置该数据模型为2列
model->setHeaderData(0,Qt::Horizontal,"NO"); //设置第一列名为序号
model->setHeaderData(1,Qt::Horizontal,"Value"); //设置第二列名为数值
ui->tableView->setModel(model); //将显示模型与数据模型相关联
}
else //将语言转换成中文
{
language = true;
QApplication::installTranslator(nullptr); //安装一个空的翻译对象,即不翻译,重新初始化后即可显示中文
ui->retranslateUi(this); //重新初始化ui界面
model->clear(); //清除数据保存模型里面的内容
lineCount = 0; //清除行号
model->setColumnCount(2); //设置该数据模型为2列
model->setHeaderData(0,Qt::Horizontal,"序号"); //设置第一列名为序号
model->setHeaderData(1,Qt::Horizontal,"数值"); //设置第二列名为数值
ui->tableView->setModel(model); //将显示模型与数据模型相关联
}
on_pushButton_start_clicked(ischecked); //在中英文切换时再次检查第一个按键控件的状态并刷新显示文字
}
我们首先创建一个 QTranslator类的对象,通过调用该类中的load函数将语音转化文件加载,该函数可以让工程自动定位到语音转化文件的位置以便于后续使用。对于该文件怎么来的下面我们来详细讲解一下。首先我们要通过新建文件,往工程内添加QT Translation file文件如下图所示:

选中该文件添加,然后我们可以在工程中点开文件,文件中内容如下:
cpp
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="en_US">
可见里面几乎时一个空文件,所以我们要通过命令行来对该文件添加相应的程序,点开QT给我们提供的qt环境下的终端,然后进入到该文件的保存路径下,然后输入lupdate 加上该工程文件即可添加语音转换程序到该文件下了。执行了该终端命令后我们可以看到里面的内容变成了如下程序:
cpp
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="en_US">
<context>
<name>MainWindow</name>
<message>
<location filename="mainwindow.ui" line="31"/>
<source>秒表计时器 1.5</source>
<translation>SeconedCount 1.5</translation>
</message>
<message>
<location filename="mainwindow.ui" line="61"/>
<source>开始计时</source>
<translation>StartCount</translation>
</message>
<message>
<location filename="mainwindow.ui" line="77"/>
<location filename="mainwindow.cpp" line="63"/>
<source>复位计数</source>
<translation>ResetCount</translation>
</message>
<message>
<location filename="mainwindow.ui" line="102"/>
<source>语言</source>
<translation>Language</translation>
</message>
<message>
<location filename="mainwindow.ui" line="110"/>
<source>切换到英文</source>
<translation>SwichToChinese</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="58"/>
<source>计数</source>
<translation>Count</translation>
</message>
</context>
</TS>
可见其就是可以将我们的中文转化成英文,我们可以直接在该程序之下编写也可以通过qt给我们提供的语言家程序进行改写,该程序如下图所示:

添加相应的ts文件再修改语言即可,完成后我们再在终端中输入lrelease 加上工程文件名既可将ts文件编译成qm文件,然后我们将该文件添加的相应目录下即可使用该文件来完成语言的切换了。我们将该文件准备完毕后,然后我们就进行一个语言判断,我们要转化成什么语言,是英文转化成中文还是中文转化成英文。对于中文转化成英文首先判断完成后将标志位置位,置位后下一次转化就是另一次的转化了。然后通过函数installTranslator将翻译的对象安装上,即可进行翻译,然后我们要通过retranslateUi函数来重新初始化ui界面才能将转化后的语言显示出来,完成语言的转化。转化后要我们清除model下的内容,并也将lineCount归零,以便于重新记录时间数据。当然直接通过model调用clear函数不仅会清除记录的数据也会清除掉列表的头,当然这也是我们想要的,因为列表的头不能直接通过前面的配置进行语言转化,所以我们清除了之后重新对列表头文字的初始化就也可以实现语言的转化了。对于英语转汉语来说,区别就是不需要将语言转化的对象加载进来即可然后其他的方法差不多。当然最后我们就要实现一个在软件计时时我们就转化语言导致语言按键语言混乱的情况,我们就要在程序的最后调用开始按键的槽函数,并传入我们前面记录该按键状态的变量作为参数,保持在运行时转化语言时按键状态和显示状态情况不变,最后在通过打包就可以做出该秒表计时器软件了。