android开发自制计算器测试图,从0开始自制计算器!

先看看效果吧:

26f4a4e36ba3483754f672801af6a5d2.png

514e6056aef45912060b2fcd3d3e8439.gif

544a24e5c18ab11dd0869fbb0ded9a74.gif

97465c89d6b9e03d0278fa33a0bd4e6e.gif

很炫酷吧?

想不想要?

想要吧.

当然作者知道你们肯定想.

不然也不会点进来对不对.

好.进入正题.

1.概述

这个是仿照win10自带的计算器制作的简化版本.是用Qt做的,直接把整个表达式输入然后得出计算结果.

主要分为三部分.界面部分,事件处理部分与表达式处理部分.

界面部分就是看到的计算器,包括标题栏,中间的输出框,还有各个按键.

事件处理就是处理对应的鼠标与键盘事件.

表达式处理部分就是处理整个输入的字符串,返回计算的结果,当然这个还支持错误判断功能.

2.新建工程

选择Widgets Application.

b43ae8308cbdc6aaf875c24e939fdefe.png

起名字.

673bd35118c19a61cea72f0147405b95.png

一般只需MinGW.

1331bcbc73629b78425e66d578a35612.png

这里默认即可,名字可以随便改

cb7c074920b0a967010e9d0ca91dd076.png

c2992492d758970498308be4d796c786.png

2.界面

(1) 按键

按键的话,基本上按着改就可以了.改布局,改颜色,改字体,主要就是这三个.

首先先打开.ui文件:

c2f902a990c1e1d4364c0bfaacde2792.png

a.添加一个Grid Layout,调整好大小.

739081144e89d828e959aedc101540d9.png

b.拖入Push Button作为按键,sizePolicy属性那里水平和垂直属性都选择Expanding.

079cbc3c6344cfebb46da59c26835907.png

c.调整好颜色,设置styleSheet与字体

5edd329d58ddfee266e7179f1e7ac376.png

这里给出作者的参考style:

border:1px groove rgb(220,220,220);

background-color:rgb(243,243,243);

字体:

4908a4ae3967706b3aac380361c045f6.png

这里按个人喜好调整即可.

d.复制制作好的button,布好局

bd1ae1f151afac28289dac6f5f8e25e5.png

e.改内容

这里不仅把里面的字符改变,还要把相应的对象名也改变.

134a1e1bed2aafd68002d18b4b843a98.png

f1f7c375d1ce6191358d47c0546bffab.png

再细调每一个按键,包括大小,字体与颜色,使总体效果更好.

f438fc151e3251506c1f9f53c542108d.png

数字要注意有"加粗"效果,符号的话尽量"精细"一点.

f.整体修改大小,同时加上间隔

437edc8cc39f5b53de6e6634ee6a6c09.png

调整好间隔.注意细节.

下面是win10自带的计算器:

9defb0f70d85760e9a419f5de6b0f12d.png

看到间隔了没?

作者要的就是这种效果.

可以先运行看看.

54d11923bd68143fe543a4d49b24d168.png

两边的间隔的话一会配合widget的大小调整即可.

(2) 输出框

输出框很简单,就是一个QLineEdit.

a.添加QLineEdit

5f41162e324631ea02ba276c6c0b4923.png

b.调整好大小,设置好背景颜色

59d4edf2ac2e83a825b2fd6ac0b9d537.png

作者的qss:

border:0px groove rgb(243,243,243);

background-color:rgb(245,245,245);

c.设置字体,只读,对齐

b604b8365a170f49bb072f987c937b36.png

1bbd03ae27a6f0c46b5574c28d613679.png

cc706651470a2e1a815c4a768cb9937f.png

(3) 标题栏

标题栏其实也很简单,一个QBoxLayout

a.新建Horizontal Layout

d5368735a34f3d5ed927a90316307eb0.png

b.添加细节

842e65e8e42148fdbffbbb7ec56fbf3f.png

QLabel输入标题,两个QPushButton表示最小化与关闭,同时加入两个Spacer,让标题与左边空出一些距离.

其实就是模仿win10的标题栏的效果

c9a5ff298476f7c049219a172370d74d.png

这里就不做最大化了.因为涉及到按钮的重新排布问题,这个可以自己选择实现.

(4)整体处理

a.标题栏

把上一步做的标题栏移到合适的位置,同时删除自带的QMenuBar,QToolBar,QStatusBar.

434b906f4542b328a1c770c46366b9e4.png

b.调整整体大小,同时添加透明度

57845ecbc33163011f94947df054cdf2.png

调整好后大概就那样,透明度这里选择了0.9.

真是完美啊!

3.事件处理

(1)光标事件

A.标题栏

a.拖动效果

首先把本来那个标题栏去掉.

a716bab3048404d8e1006341ca6c8003.png

setWindowFlags(windowFlags() | Qt::FramelessWindowHint);

再在protected中加入鼠标监听函数:

746a5180b86997228bdd1f183cb8ee0c.png

void mousePressEvent(QMouseEvent *);

void mouseMoveEvent(QMouseEvent *);

私有成员中加入两个QPoint.分别表示当前窗口坐标与光标的坐标.

059e7cbe5892f46b9701ec0ce6382563.png

QPoint mousePoint;

QPoint windowPoint;

77fcbede43f02b21e53524fbe1ab112c.png

第一个函数是鼠标按下时触发的,根据event->button()判断是否是左键,是的话获取mouse坐标,在设置window坐标.

当触发第二个函数时,即先判断是否按住左键不放,使用MainWindow的move方法移动窗口.

event->globalPos()获取坐标后减去原来光标的坐标得到window坐标的变化量,再用原坐标加上这个变化量.

void MainWindow::mousePressEvent(QMouseEvent *event)

{

if(event->button() == Qt::LeftButton)

{

mousePoint = event->globalPos();

windowPoint = frameGeometry().topLeft();

}

}

void MainWindow::mouseMoveEvent(QMouseEvent *event)

{

if(event->buttons() & Qt::LeftButton)

{

move(windowPoint + event->globalPos() - mousePoint);

}

}

b.最小化与关闭

这里以最小化为例,关闭也一样的,改一下函数调用即可.

在最小化按钮中右键选择Go to slot:

4c29b78e5a788d5b257e7765a248889f.png

选择clicked()

84f26f276def565c0570ead7356f2be5.png

添加一个最小化函数:

c3409d1b24781772d30d81ca08578468.png

下面是关闭的函数:

1508cf79a1ac108d7de1471a07d6e8b7.png

B.按键

按键的鼠标事件包括两个:

光标移入与移出事件,为按键添加阴影,加深颜色等

单击事件,在输出框中增减对应的字符

a.移入与移出事件

这里的实现方式是通过事件过滤器实现的.增加一个eventFilter()函数

4be8bc4d2fcfc1466b5454db23245369.png

bool eventFilter(QObject *,QEvent *);

d110e4352422b2778be177274e4f4bbc.png

首先通过event->type()判断事件类型,如果是光标悬停,再判断对应的各个对象增加阴影效果.

addNumButtonEffet():

void MainWindow::addNumButtonEffect(QPushButton *button,QGraphicsDropShadowEffect *shadow)

{

shadow->setEnabled(true);

button->setStyleSheet(

"border:1px groove rgb(220,220,220);"

"background-color:rgb(193,193,193);"

);

}

这里QGraphicsDropShadowEffect *shadow事先初始化好了.

9797f9a69636c99689f823cae7bb4eb5.png

b4cf1a4f6c89dae2d0222bc5be65613c.png

然后在添加事件过滤器:

ecb9a34c1e7901e3f1ea47f0edb2cab8.png

这里可以对比一下有没有阴影的效果:

没有阴影:

1b8982ab5202ae6e683a3d11c48e7fb3.gif

加上阴影:

556e5a6fe673c708efbee77590c6eaeb.gif

呃....这里可能是截图工具的问题,看不来多大的效果,但是直接在机器上看是有比较大的区别的,建议还是加上阴影.

b.单击事件

单击事件就是单击了某个按键然后用户可以在输出框中看到对应的反应.

依次选择按键,右键Go to slot:

d1a9a00d58cd40c827e5da087371f0ca.png

选择clicked()

966983b0da5089ea63ca9384026165f0.png

然后添加处理函数,作者这里自己实现了一个添加文本与清除焦点的函数,添加文本就是对应按键被光标单击后添加到输出框,至于为什么要清除焦点....

因为...

因为空格.

因为作者的"良好"习惯,习惯在运算符前后加上空格

单击后会把焦点保留在这个按钮上,键盘上敲空格默认会帮你"按一次"这个按钮,因此如果不清除焦点的话,在光标单击了某个按钮,比如7,按空格就会在输出框上输出7,光标单击了8后,按空格就会在输出框上输出8.

795e0faf1d1cb5ed6d33ffa50cfb9206.png

1b60e605e34afd59d5edc68a7624850a.png

这里添加文本时还要注意默认的起提示作用的0.

void MainWindow::appendText(const QString &s)

{

if(ui->box->text() == "0")

ui->box->setText(s);

else

ui->box->setText(ui->box->text()+s);

}

void MainWindow::appendTextAndClearFocus(QPushButton *button, const QString &s)

{

appendText(s);

button->clearFocus();

}

(2)键盘事件

键盘事件就是主要处理各个按键按下时的阴影与输出框添加输出.

键盘事件通过以下两个函数处理:

fd72c7c5bcc7ac2e00bbb41769ce1575.png

void keyPressEvent(QKeyEvent *);

void keyReleaseEvent(QKeyEvent *);

第一个是按键按下时触发的,第二个是松开按键触发的.

A.添加阴影

在按键按下时添加上阴影与颜色加深效果.

3752fe18faa0781f91099962f8dcce81.png

通过event->key()依次判断各个键.

键位可以看这里

然后添加在keyRealeseEvent()中把对应的阴影去掉:

void MainWindow::keyReleaseEvent(QKeyEvent *event)

{

switch (event->key())

{

case Qt::Key_0:

case Qt::Key_1:

case Qt::Key_2:

case Qt::Key_3:

case Qt::Key_4:

case Qt::Key_5:

case Qt::Key_6:

case Qt::Key_7:

case Qt::Key_8:

case Qt::Key_9:

case Qt::Key_Plus:

case Qt::Key_Minus:

case Qt::Key_Asterisk:

case Qt::Key_Slash:

case Qt::Key_AsciiCircum:

case Qt::Key_Percent:

case Qt::Key_ParenLeft:

case Qt::Key_ParenRight:

case Qt::Key_BraceLeft:

case Qt::Key_BraceRight:

case Qt::Key_BracketLeft:

case Qt::Key_BracketRight:

case Qt::Key_Backspace:

case Qt::Key_Space:

case Qt::Key_Period:

case Qt::Key_Escape:

case Qt::Key_Equal:

case Qt::Key_Return:

removeNumButtonEffect(ui->num0,num0_shadow);

removeNumButtonEffect(ui->num1,num1_shadow);

removeNumButtonEffect(ui->num2,num2_shadow);

removeNumButtonEffect(ui->num3,num3_shadow);

removeNumButtonEffect(ui->num4,num4_shadow);

removeNumButtonEffect(ui->num5,num5_shadow);

removeNumButtonEffect(ui->num6,num6_shadow);

removeNumButtonEffect(ui->num7,num7_shadow);

removeNumButtonEffect(ui->num8,num8_shadow);

removeNumButtonEffect(ui->num9,num9_shadow);

removeSignButtonEffect(ui->plus,plus_shadow);

removeSignButtonEffect(ui->minus,minus_shadow);

removeSignButtonEffect(ui->mutiply,mutiply_shadow);

removeSignButtonEffect(ui->divide,divide_shadow);

removeSignButtonEffect(ui->pow,pow_shadow);

removeSignButtonEffect(ui->percent,percent_shadow);

removeSignButtonEffect(ui->parentheses,parentheses_shadow);

removeSignButtonEffect(ui->parentheses,parentheses_shadow);

removeSignButtonEffect(ui->brace,brace_shadow);

removeSignButtonEffect(ui->brace,brace_shadow);

removeSignButtonEffect(ui->bracket,bracket_shadow);

removeSignButtonEffect(ui->bracket,bracket_shadow);

removeSignButtonEffect(ui->backspace,backspace_shadow);

removeSignButtonEffect(ui->blank,space_shadow);

removeSignButtonEffect(ui->dot,dot_shadow);

removeSignButtonEffect(ui->C,c_shadow);

removeSignButtonEffect(ui->equal,equal_shadow);

break;

}

}

这里之所以没有一个个按键去判断是因为有可能同时多个按键按下,然后同时松开后发现某个按键还存在阴影,因此统一当其中一个按键释放时去除所有按键的阴影.

B.添加输出

在输出框中添加输出,调用一个函数即可:

afebeb973c7cfa3c0e75c380a5e58506.png

4.整体细节再处理

(1)淡入效果

看看效果:

490489af91d7cfe296019a26ebe4f973.gif

这里实际使用了Qt的动画,针对透明度改变的动画.

4fa64f2fae3fe637ab45676fffd2bd94.png

void MainWindow::fadeIn(void)

{

QPropertyAnimation * changeOpacity = new QPropertyAnimation(this,"windowOpacity");

changeOpacity->setStartValue(0);

changeOpacity->setEndValue(0.91);

changeOpacity->setDuration(2500);

changeOpacity->start();

}

第一行表示改变的是透明度,第二三行设置起始值与结束值,接下来设置动画时间(单位ms),然后开始动画.

(2)设置固定尺寸

这里可以不设置最大尺寸,但一定要设置最小尺寸.

2806c8d0d3392f527477b66a743e9f9b.png

设置这个实际上禁止了拖拽去改变大小.

(3)淡出效果

淡出效果与淡入效果类似.

不同的时需要添加计时处理,不能直接在exit(0)前调用fadeOut()函数,因为动画会在另一个线程启动,所以需要在主线程休眠指定秒数,等待淡出效果完成后,主线程再调用exit(0);

d7811a6ced6efaaef873b1f2178fb119.png

void MainWindow::fadeOut(void)

{

QPropertyAnimation * changeOpacity = new QPropertyAnimation(this,"windowOpacity");

changeOpacity->setStartValue(0.9);

changeOpacity->setEndValue(0);

changeOpacity->setDuration(2500);

changeOpacity->start();

QTime start = QTime::currentTime().addMSecs(2500);

while(QTime::currentTime() < start)

QCoreApplication::processEvents(QEventLoop::AllEvents, 100);

}

其中addMSecs()表示要延迟的秒数,while循环体中表示处理本线程的事件,其中100表示处理事件最多100ms就返回本语句.

216249a35b7635b49c7266f6e282fdde.png

这里就不放淡出效果的图片了.

5.表达式处理

由于这是整个字符串作为表达式进行输入,需要先进行判断再计算.所以分为判断与计算两部分.

这里使用了一个新开的控制台工程,后面会把这个整合起来.

(1)判断

使用了一个check类判断,由于只有10个数字按键,加减乘除,小数点,求余,求次幂,大中小括号,空格,所以可以分成这几类进行判断.

a.去除所有空格

void removeAllBlank(void)

{

size_t i = 0;

while((i = s.find(' ',i)) != string::npos)

s.erase(i,1);

}

首先把所有空格去除,避免之后的判断.

b.分类判断

把表达式中的所有字符分成5类:

数字

小数点

运算符号 + - * / ^ %

左括号类 ( [ {

右括号类 ) ] }

然后就是针对每个类型判断它的下一个字符是否是允许的类型,不是的话返回false.

比如碰上了一个 ( 或 [ 或 {

则它的下一个不能是运算符号或者小数点,当然允许-与+,因为有

(-7) (+234)

这种情况.

然后把这个符号保存下来判断后面是否是对应的右括号.

if(isLeftBrace(i))

{

if(isSignOrDot(i+1))

{

if(s[i+1] != '-' && s[i+1] != '+')

return false;

}

braces.push(s[i]);

}

整个判断函数如下:

bool valid(void)

{

if(isSignOrDot(0) || isRightBrace(0))

return false;

len = s.size();

stack braces;

for(size_t i=0;i

{

if(isLeftBrace(i))

{

if(isSignOrDot(i+1))

{

if(s[i+1] != '-' && s[i+1] != '+')

return false;

}

if(isRightBrace(i+1))

return false;

braces.push(s[i]);

}

else if(isRightBrace(i))

{

if(isDot(i+1) || isDigit(i+1) || isLeftBrace(i+1))

return false;

if(isRightBrace(i+1))

{

stack braces_copy(braces);

if(braces_copy.empty())

return false;

braces_copy.pop();

if(braces_copy.empty())

return false;

}

if(braces.empty())

return false;

char brace = braces.top();

if((brace == '(' && s[i] != ')') || (brace == '[' && s[i] != ']') || (brace == '{' && s[i] != '}'))

return false;

braces.pop();

}

else if(isSign(i))

{

if(isSign(i+1) || isDot(i+1) || isRightBrace(i+1))

return false;

}

else if(isDot(i))

{

if(isSignOrDot(i+1) || isBrace(i+1))

return false;

}

else if(isDigit(i))

{

if(isRightBrace(i+1))

{

if(braces.empty())

return false;

char brace = braces.top();

if((brace == '(' && s[i+1] != ')') || (brace == '[' && s[i+1] != ']') || (brace == '{' && s[i+1] != '}'))

return false;

}

}

}

return braces.empty();

}

特别要注意下的就是碰到右括号的情况,除了要判断是否是单独存在的右括号,还有判断是否与前一个左括号匹配.

c.加0

这是针对单目运算符-的情况,比如(-7),然后把它转化为(0-7):

string getResult(void)

{

size_t len = s.size();

for(size_t i = 0;i

{

if(s[i] == '(' && (s[i+1] == '-' || s[i+1] == '+'))

s.insert(i+1,"0");

}

return s;

}

在左小括号后判断是否是-或+,是的话对应位置插入0.

(2)计算

a.calc辅助类

calc辅助类中使用了两个栈,运算符栈与操作数栈.

private:

stack operators;

stack operands;

其中有两个重要的方法:

bool canCalculate(char sign);

void calculate(void);

第一个方法将下一个准备进入的符号作为参数,判断是否可以计算操作数栈的前两个数,如果可以的话,使用第二个函数进行计算.

calculate()会将出栈两个操作数与一个运算符,得出结果后在将其压回操作数栈.

void calculate(void)

{

double post = popAndGetNum();

char sign = popAndGetSign();

double pre = popAndGetNum();

double result = 0.0;

switch (sign)

{

case '+':

result = pre+post;

break;

case '-':

result = pre-post;

break;

case '*':

result = pre*post;

break;

case '/':

if(fabs(post) < 1e-6)

{

cout<

exit(EXIT_FAILURE);

}

else

result = pre / post;

break;

case '^':

result = pow(pre,post);

break;

case '%':

result = static_cast(pre) % static_cast(post);

break;

}

push(result);

}

bool canCalculate(char sign)

{

if(sign == '(' || sign == '[' || sign == '{' || operators.empty())

return false;

char t = getSign();

if(t == '^')

return true;

switch (t)

{

case '+':

case '-':

return sign == '+' || sign == '-';

case '*':

case '/':

case '%':

return sign == '+' || sign == '-' || sign == '*' || sign == '/' || sign == '%';

}

return false;

}

下面是calc类:

class calc

{

private:

stack operators;

stack operands;

char getSign(void)

{

return operators.top();

}

double getNum(void)

{

return operands.top();

}

void popSign(void)

{

operators.pop();

}

void popNum(void)

{

operands.pop();

}

double popAndGetNum(void)

{

double num = getNum();

popNum();

return num;

}

char popAndGetSign(void)

{

char sign = getSign();

popSign();

return sign;

}

public:

void push(double num)

{

operands.push(num);

}

void push(char sign)

{

operators.push(sign);

}

char get(void)

{

return getSign();

}

void pop(void)

{

popSign();

}

double result(void)

{

return getNum();

}

void calculate(void)

{

double post = popAndGetNum();

char sign = popAndGetSign();

double pre = popAndGetNum();

double result = 0.0;

switch (sign)

{

case '+':

result = pre+post;

break;

case '-':

result = pre-post;

break;

case '*':

result = pre*post;

break;

case '/':

if(fabs(post) < 1e-6)

{

cout<

exit(EXIT_FAILURE);

}

else

result = pre / post;

break;

case '^':

result = pow(pre,post);

break;

case '%':

result = static_cast(pre) % static_cast(post);

break;

}

push(result);

}

bool canCalculate(char sign)

{

if(sign == '(' || sign == '[' || sign == '{' || operators.empty())

return false;

char t = getSign();

if(t == '^')

return true;

switch (t)

{

case '+':

case '-':

return sign == '+' || sign == '-';

case '*':

case '/':

case '%':

return sign == '+' || sign == '-' || sign == '*' || sign == '/' || sign == '%';

}

return false;

}

bool empty(void)

{

return operators.empty();

}

};

private封装了一些简单的对两个栈进行操作的工具方法,公有的pop()与get()是对运算符栈进行的操作.因为外部不需要对操作数栈进行操作,由calculate()进行操作,公有的push重载了,可以push到操作数栈或运算符栈.

b.计算部分

计算部分在这里直接放在了main中:

int main(void)

{

check chk;

while(!chk.inputAndCheck())

cout<

string s = chk.getResult();

size_t len = s.size();

calc c;

for(size_t i=0;i

{

if(isdigit(s[i]))

{

double num;

size_t i1 = i+1;

while(i1 < len && (isdigit(s[i1]) || s[i1] == '.'))

++i1;

istringstream input(s.substr(i,i1));

input>>num;

i = i1-1;

c.push(num);

}

else if(s[i] == '}' || s[i] == ']' || s[i] == ')')

{

char sign;

char start = (s[i] == '}' ? '{' : ( s[i] == ']' ? '[' : '('));

while((sign = c.get()) != start)

c.calculate();

c.pop();

}

else //s[i] is [ ( { + - * / ^ %

{

while(c.canCalculate(s[i]))

c.calculate();

c.push(s[i]);

}

}

while(!c.empty())

c.calculate();

cout<

return 0;

}

对表达式的每个字符逐个处理,若是数字,提取出来并压栈.

若是右括号类,不断从运算符栈中提取直到把这段括号内的表达式计算完成.

否则若是左括号或者是运算符,当可以计算的时候一直计算,提取两个操作数运算并压栈,再把新的运算符压栈.

最后使用result()获取结果.

c.测试

这里就显示几个很长的例子算了

当然作者测试了很多的例子

bcc6a8b420b40c25b056779360f63ecb.png

7af0951f21097d5424edadf5f5be1e98.png

dd92543982abfaef72a907017cd8cd72.png

6.6/{2.3+34.3*2.22-5%2+22%4*[2+3.4/5-(4.3+3.2*33.3)]+34.3} + 7.8*{2.4-6/6+0-0*[23.4-3.4/6+4*(2.2+3)]}+0 - 0 + 0.0

= 10.8569

3.4 - (+3.34) + 34.3 * (-2) / 3.34 + {[(-3.4)^2/3.4+3.4/3]-3.32+[3*(-3)]}

= -28.2656

9^5-34.4^2.3+5%6-34+66%78-78%4 + (-3)*3.4 / {3*(-7)+[3*(-8)+3*(3.4+4.34)/9.3-3.2 + 0.0 - 0]+0.0 - 0}+3.4^4/6.888

= 55683.2

不信的话可以手工计算一下.

6.整合

这部分把界面部分与表达式处理部分整合起来.

(1)设置界面的调用进程,并获取输出结果

计算表达式的程序叫MyCalc.exe,注意把它放在对应的工程文件夹下面,然后使用QProcess调用.

8ffe43100f3c89561fa37f04f4ef4abd.png

使用execute执行,表达式先去除所有的空格,然后作为命令行参数传递给计算程序,然后计算程序把计算结果写入到result.txt文件,Qt读取这个文件,如果读到#表示表达式输入错误,否则,则是正确的计算结果.

对于结果因为在计算程序中设置了fixed格式,因此对于

1+2

也会返回

3.000000

这步把多余的0去掉,还要注意小数点的情况.

(2)修改一些细节地方

a.鼠标键盘修改事件

da346732647094bd4e305d8e161a5b80.png

2f523ff9510ddefc6bb5fa9345ecee17.png

修改setText的内容,把结果传递过去.

b.exe中设置数字的格式

08af2996857d71b8821e18ccab1c2631.png

设置fixed格式,否则的话显示的是科学计数法,对小数位数有要求的话可以设置setprecision.

c.设置错误提示

这里出现错误时,输出"#",然后主程序读取到就会提示"表达式错误,请重新输入."

ac1f5174656984a23fcabe7d24a7e856.png

还有除数为0的错误提示,这个要注意一下:

7a51e9b339efaa18055f4acf410d2bd4.png

13d59b8e64f102a4de183b7e3d9a576c.png

d.可以考虑把错误处理整合过来

比如输入了一个点,不能继续输入点,输入了一个乘号或者除号不能再继续输入另一个符号:

5ddc41dfe24fcaceabf665b7f909dfd9.gif

7.打包发布

(1) 首先去下载Enigma Virtual Box

(2) 添加环境变量

b9c5e6c51c90742e29e19da11b7a52bd.png

把Qt文件夹下的如图所示的bin添加到Path环境变量,

(3) 打包库文件

使用windeployqt打包,首先把程序调成release模式,运行一次,生成release的exe,然后把exe复制到一个单独的文件夹,再用命令行进入到这个文件夹,运行

windelpoyqt xxx.exe

c2888a9a894f1c6e4bc69d260f196e8e.png

443471e932841c87b738ef7ce0146473.png

这个命令把需要的dll复制到当前所在文件夹.

(4) 生成单个exe

打开Enigma Virtual Box,选择

0b123e8e0164008a7daca1643efa3cd0.png

c3a4bcf9d4407491bc64d7728bde0b48.png

第一个选择release的exe,第二个选择打包之后的文件夹,然后选择添加文件,选择递归添加,添加上一步生成的所有文件(夹).

233669708c6eea0b06b0855a306d8ad7.png

这里选择压缩文件.

然后选择压缩等待完成即可.

(5) 测试

点击运行.

8b22bfabf73e39651995c5902dadd270.png

大功告成!!

8.源码

1.github(里面包含完整可执行的单个exe)

注:由于使用了lfs上传大文件,所以clone的时候请使用

git lfs clone

2.码云

9.参考链接

10.最后

这个简单的计算器有很大的改进空间,比如可以添加各种"数":

正弦函数,余弦函数,正切函数,反正弦函数,指数函数,对数函数,高阶导数,抽象函数,复合函数.心里没数

等等.另外还可以改进矩形的按钮,可以改成圆角矩形或者椭圆形.

另外,对于阴影的处理可以添加淡入淡出效果.

最后就是磨砂.因为win10的是有磨砂效果的,这个作者还不会....

最后再上几个图,看看效果(由于动图大小的限制只是简单的表达式...):

db11eeeb4baccf95582f84bf6ce5dfc1.gif

f67d45a07162065dc8b7045736ba9427.gif

afae9f1a64dbdecac0f6a19e2423f2c1.gif

ba2457c74478ccde472391f54d7bd68a.gif

希望你们也有一个属于自己的计算器!

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值