exilefox 发表于 2012-4-1 13:07:21

超简明Qt教程之二--计算器

本帖最后由 exilefox 于 2012-4-1 13:12 编辑

超简明Qt教程--计算器Exilefox2012年4月1日
之前发了一个Qt Desiger设计ui的入门教程,本篇本来是三部曲的第二部分,但是本人最近要到深圳找饭吃,各种忙,所以只能不负责任的草草把这篇先发出来,至于什么时候能完成全部3篇我也不知道。所以各位看官如果对Qt有兴趣,不要等,积极探索,说不定等我发第三篇的时候各位已经是高手啦~
上篇着重做了界面,而一个完整的项目需要界面和功能的结合,所谓内外兼修嘛~这篇主要讲如何将界面与函数实现结合起来,顺带再穿插一些stylesheet的内容。同样,只是个引子,以最简单的计算器为例。
我们要做的计算器是这样一个东西:有0~9 十个数字按键、一个加号键、一个减号键,一个清除键,一个回车键、一个显示框。我承认我懒,这个计算器就只能实现加减法运算,是不是弱爆了?没关系,你要搞个乘除法、进制转换什么的原理是一样滴~
新建工程时候选择Widget而不是mainwindow,毕竟我们计算器没高级到需要一个菜单什么的。

在这里我们还自己改了一下这个类的名称,方便记忆嘛~Qt还挺聪明的,你改了类名称下面的几个文件名称也自动跟着改了。
一、编辑UI
工程建立了和上次一样,先直接做.ui文件。

如图,只用到两类控件 pushButton 和lineEdit
先拖一个pushButton出来,改名为button_1 ,修改显示的文字为1 。剩下的数字键也要这样?非也,你只需选中,ctrl+C,ctrl+v几次就一个个出来了。对象名字什么的是自动连续的,但是显示内容就得自己动手改了。剩下的按钮自己能够搞定了吧?
拖个LineEdit出来做显示。从名字可以知道这家伙是输入类型的,而计算器显示不是输出的吗?用textBrowser不是更准确一些吗?实际上用textBrowser也是可以的,但到后面我发现他有个问题,这货死活不能靠右显示。而官方的例子里面用的是lineEdit,只不过加了句代码
setReadOnly(true);
把它设置成了readonly。从这点展开将,我想让大家知道的是这些控件的应用可以是很灵活的,输入的可以用来显示,按钮贴上图做图标什么的,想象力+大胆尝试, QtDesigner自带的控件就可以满足你大部分的要求。

计算器的框架大体有了,是不是觉得不太好看呢?在这里我们用stylesheet做一些简单的修饰。
字体加大加粗:对所有的Qbutton都有效,所以在总体控件的空白处点右键-改变样式表

弹出的串口先输入要修改的对象QPushButton{}--请注意到和上一节我们讲的相比,这里少了#号,表示这个ui里面所有的pushbutton类的控件都生效。把光标移到{}中,点选择字体,选择好后对字体样式的描述就自动写到{}里了。点击确定看看大家是否都变得又黑又粗了呢^-^?

个别、字体改变颜色:不过眼尖的你也许看到了enter因为变得太大而超出格子了,而且我们希望加号减号键这些有其他的颜色。所以我们再这对个别修改一下。在enter键上点右键-改变样式表 ,除改变字体之外我们还可以选添加颜色来改变颜色。剩下几个按键也有你喜好修改好。


改变边框圆角:对那个方方正正的显示框我们也来修改一下,步骤同前面一样

请注意这里有个border-radius: 10px;
他是边框棱角的设置选项,但是这东西在编辑样式表对话框的下拉菜单中是找不着的,各位就要手动输入了。这类没列出来的属性还有很多,靠大家平时积累记住,另外就是上http://doc.qt.nokia.com/4.3/stylesheet-reference.html查一查,那里列出了有什么控件可以修改stylesheet,可以修改那些属性。



二、实现函数
至此ui相关的大部分工作就完成了,接下来我们来充实一下函数的实现。由于本篇侧重讲功能与界面的结合,就不可能像上一篇那样宣称只用几行代码搞定了,但是实际上也不多。
以下是纯c++编程部分,给出的代码是我偷懒的代码,各位完全可以用自己的方式来实现。
连接槽函数:在数字按键上点击右键-转到槽函数,选择信号为click(),这样我们就跳到了.cpp文件里,这时程序已经把声明什么的写好,就等着我们来填坑了~
你会发现这些槽函数的名字很有规律void calculor::on_button_1_clicked(),复制粘贴,改一下button_1我们就把其他的槽函数一起建好了,坑挖好了,但是还是没有内容,先留着,去.h在类定义中加一些我们需要的变量。

.h文件
先是一堆槽函数的声明,这个是自动生成的。
后面的私有成员定义:
首先是两个计算数,frist和second,当然还有结果result
然后是表示现在输入的是frist还是second的标志位,我们用个枚举来做,当有加号、减号按下时这个状态由FRIST转到SECOND
结构体SIGN存放的是表示进行加法还是减法的标志位
其他的请各位看注释~#ifndef CALCULOR_H
#define CALCULOR_H

#include <QWidget>

namespace Ui {
class calculor;
}

class calculor : public QWidget
{
Q_OBJECT

public:
explicit calculor(QWidget *parent = 0);
~calculor();


private slots:
void on_button_1_clicked();
void on_button_2_clicked();
void on_button_3_clicked();
void on_button_4_clicked();
void on_button_5_clicked();
void on_button_6_clicked();
void on_button_7_clicked();
void on_button_8_clicked();
void on_button_9_clicked();
void on_button_0_clicked();
void on_button_clean_clicked();
void on_button_enter_clicked();
void on_button_plus_clicked();
void on_button_minus_clicked();

private:
Ui::calculor *ui;
void trans(char key);//把输入的数转换成十进制,并输出到文本框
void cal(void);//计算结果
enum state {FRIST,SECOND}my_state;
enum sign {PLUS,MINUS,NO}my_sign;
int frist;//第一个数的值
int second;
int result;//计算结果
};

#endif // CALCULOR_H

.cpp文件
这里重点是cal和trans,plus三个函数的实现#include "ui_calculor.h"
#include "calculor.h"



calculor::calculor(QWidget *parent) :
QWidget(parent),
ui(new Ui::calculor)
{
//this->setWindowOpacity(0.7);
ui->setupUi(this);
ui->lineEdit->setAlignment(Qt::AlignRight);
ui->lineEdit->setReadOnly(true);
my_state=FRIST;
my_sign=NO;
frist=0;
second=0;
result=0;
}

calculor::~calculor()
{
delete ui;
}
/*********************************
函数名:on_button_x_clicked()
作用:数字按键点击信号的槽函数
**********************************/
void calculor::on_button_1_clicked()
{
trans(1);
}
void calculor::on_button_2_clicked()
{
trans(2);
}
void calculor::on_button_3_clicked()
{
trans(3);
}
void calculor::on_button_4_clicked()
{
trans(4);
}
void calculor::on_button_5_clicked()
{
trans(5);
}
void calculor::on_button_6_clicked()
{
trans(6);
}
void calculor::on_button_7_clicked()
{
trans(7);
}
void calculor::on_button_8_clicked()
{
trans(8);
}
void calculor::on_button_9_clicked()
{
trans(9);
}
void calculor::on_button_0_clicked()
{
trans(0);
}
/*********************************
函数名:on_button_enter_clicked()
作用:enter按键点击信号的槽函数,调用cal()计算,最后清空
**********************************/

void calculor::on_button_enter_clicked()
{
cal();// 如果按下,调用cal函数计算结果
ui->lineEdit->setText(QString::number(result));// 显示结果
frist=0;// 清除frist和second以及相应的状态标识
second=0;
my_state=FRIST;
my_sign=NO;
}

/*********************************
函数名:on_button_plus_clicked()
作用:加号按键点击信号的槽函数,my_sign置PLUS
**********************************/
void calculor::on_button_plus_clicked()
{
my_sign=PLUS;// 如果按下,向sign变量中存放+号标志
if(my_state==SECOND)//连续加的情况
{
cal();
ui->lineEdit->setText(QString::number(result));// 显示结果
frist=result;
second=0;
}
my_state=SECOND;// 把状态标志指向second

}

/*********************************
函数名:on_button_minus_clicked()
作用:减号按键点击信号的槽函数,my_sign置MINUS
**********************************/
void calculor::on_button_minus_clicked()
{
my_sign=MINUS;// 如果按下,向sign变量中存放+号标志
if(my_state==SECOND)//连续加的情况
{
cal();
ui->lineEdit->setText(QString::number(frist));// 显示结果
frist=result;
second=0;
}
my_state=SECOND;// 把状态标志指向second
}
/*********************************
函数名:on_button_clean_clicked()
作用:clean按键点击信号的槽函数,清空显示和数据
**********************************/
void calculor::on_button_clean_clicked()
{
ui->lineEdit->clear();
my_state=FRIST;
my_sign=NO;
frist=0;
second=0;
result=0;
}

/*********************************
函数名:trans()
作用:将传入的数组合成十进制
**********************************/
void calculor::trans(char key)
{
if(my_state==FRIST)
{
frist=frist*10+(int)key;//将传入的数组合成10进制传给first
ui->lineEdit->setText(QString::number(frist));//显示
}
else
{
second=second*10+(int)key;//将传入的数组合成10进制传给second
ui->lineEdit->setText(QString::number(second));//显示
}

}
/*********************************
函数名:cal()
作用:根据my_sign选择进行何种计算,结果保存在result
**********************************/
void calculor::cal(void)
{
switch(my_sign)
{
case PLUS:result=frist+second;break;
case MINUS:result=frist-second;break;
}
}
解释一下trans里面这句
ui->lineEdit->setText(QString::number(frist));
调用对象ui里面的子对象的函数setText以实现找lineEdit里面显示数字
ui这个对象我们在上一篇提到过,是系统自动生成的.ui界面文件的类的对象(好拗口),总之,就是我们在.ui里面画的那些东西都在这个对象下面。
QString::number(frist)表示把数字转换成字符串。这是由于setText的参数要求要是字符串型。(把鼠标悬停在函数名上一会儿就会显示这个函数的参数类型等相关信息)

剩下的那些void calculor::on_button_1_clicked()里面实现的就是点击数字键就执行trans函数把数字转换成frist或者second里,并显示出来。

void calculor::on_button_plus_clicked()等和数字键的功能有些不同,比如按了plus要把当前状态从FRIST换到SECOND,还要实现判断是否是连加的情况。

最后来看看构造函数,在这里我们完成对lineEdit的进一步修饰。
前面我们提到了两个问题:lineEdit设为只读 ui->lineEdit->setReadOnly(true);
                  lineEdit要靠右显      ui->lineEdit->setAlignment(Qt::AlignRight);
好,解决了。
编译一下,计算器就出来啦。


-------------------------------------------------------------------------------
为了避免上一次不出图的悲催情况,在这里附上附件以及工程文件

ps 我在水区发了个贴求深圳生活攻略,欢迎各位来捧场

changhui0222 发表于 2012-4-1 13:17:12

不错。搞QT的人多了起来!

lghtjpu 发表于 2012-4-1 13:36:27

QT帝又来授课了,要好好听课了

wanghongyang 发表于 2012-4-1 13:46:00

QT真挺好的

cqjyq 发表于 2012-4-7 08:43:59

学习了

newhz 发表于 2012-4-7 08:54:18

几天的图片都能显示,
这个帖子能再发一遍么
http://www.ourdev.cn/thread-5463008-1-1.html

longfeix86 发表于 2012-4-7 09:24:45

楼主,你那个代码行号是怎么弄出来的啊?

zhikai_wu 发表于 2012-4-7 10:13:28

能不能在STM32里用啊。

zyp000 发表于 2012-4-7 10:19:56

感谢LZ。
之前一个帖子没看到,能否把链接编辑在帖子里呢?

FlashNuk 发表于 2012-4-8 10:20:48

附件无法下载,另外请教一下,qt designer 现在怎么都不提供下载了呢?楼主能否上传到网盘?让我们也尝尝鲜。

boyazy 发表于 2012-4-8 10:23:56

好好听课{:smile:}

FORESTD 发表于 2012-4-8 10:40:55

我是来顶楼主的...

Q28182900 发表于 2013-1-14 10:42:20

boyiee 发表于 2013-1-18 13:21:17

好东西。快速入门啊嘿嘿

hongshuang_3721 发表于 2013-3-7 16:16:09

好贴,我顶

Jason_rao 发表于 2013-10-7 17:16:26

网上搜了那么多QT计算器例程,还是这个最好

skyfight 发表于 2013-10-8 17:27:51

支持一下。
页: [1]
查看完整版本: 超简明Qt教程之二--计算器