GEC6818的QT计算器计算的结果控制LED的亮灭
基于GEC6818开发板的QT实验
实现功能:
利用A53完成QT界面加减乘除开方等功能.运算结果为5的倍数时,打开LED1灯,当结果为7的位数时,打开LED2,其它结果,关闭所有LED灯。
工程演示视频地址:基于GEC6818的QT实验-可平方和开根号的计算器运算结果控制LED灯的亮灭
一、创建工程
工程的创建可以参考QT工程的创建与GEC6818交叉编译实现LED的亮灭控制,注意需要看第二个与LED相关的工程的创建。
二、设计计算器的UI界面
由于考虑到除开加减乘除之外还有开方和开根号的操作,所以将ui界面设计如下:
接下来是详细操作:
2.1 计算器的显示框lineEdit
计算器的显示框是一个lineEdit
,一个单行文本输入的组件,它允许用户在文本框中输入和编辑文本内容。
关于这个控件的一些属性大家可以参考文章QT控件——LineEdit;
我们调整一下该组件的相关属性:
调节完基本的之后,我们还可以给计算器的显示加一个其他的样式,对控件右键
选择改变样式表
在这里面进行样式的自定义,比如我设置的背景颜色以及字体属性,写好后点击apply
进行应用:
QLineEdit{
background-color:#b8b8b8;
border:1px solid gray;
color:#000000
}
效果:
2.2 计算器的其他按键
其他按键都是PushButton
,从左边拖动相应的按钮并进行布局,然后更改上面的文本
最后呈现这样
此时我们可以看到右边对象属性的这一栏中,按钮的名称是递增的,这样不利于我们编写代码,所以建议将对应按键的名称改为对应的英文名称。
按键的初始化基本完成了,但是为了美观,也可以和LineEdit一样进行样式更改,但是这么多的按键,我们可以不逐个进行更改,可以多选后进行更改
QPushButton{
background-color:#C0C0C0;
border:1px solid gray;
padding:5px;
}
QPushButton:pressed{//按键按下后呈现另一种颜色
background-color:#999999;
border:1px solid gray;
padding:5px;
}
其他的也都可以如此效仿,完成颜色的配置。
三、代码的编写
对于每一个按钮都添加一个槽,
每一个按钮都将执行不一样的。
完整代码
calculator.cpp
#include "calculator.h"
#include "ui_calculator.h"
#include <QDebug>
#include <QDesktopWidget>
#include <math.h> //sqrt()
#include<fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
#define TEST_MAGIC 'x' //定义幻数
#define TEST_MAX_NR 2 //定义命令的最大序数
//定义LED的魔幻数
#define LED1 _IO(TEST_MAGIC, 0)
#define LED2 _IO(TEST_MAGIC, 1)
#define LED3 _IO(TEST_MAGIC, 2)
#define LED4 _IO(TEST_MAGIC, 3)
int fd=-1;//ledfd
calculator::calculator(QWidget *parent) :
QWidget(parent),
ui(new Ui::calculator)
{
//fd
fd = -1;
fd = ::open("/dev/Led", O_RDWR);
if (fd < 0)
{
qDebug("open led dev fail!!");
}
//------------------------------------------------------------
ui->setupUi(this);
lefts=0;
connect(this,&calculator::whichBtn,&calculator::enableOp);
connect(this,&calculator::whichBtn,&calculator::enableLeft);
connect(this,&calculator::whichBtn,&calculator::enableEqual);
connect(this,&calculator::whichBtn,&calculator::enableRight);
connect(this,&calculator::whichBtn,&calculator::enableDigit);
init();
}
calculator::~calculator()
{
if (fd > 0)
{
::close(fd);
fd = -1;
}
delete ui;
}
/*
*public function//
*/
void calculator::LED(int num)
{
if (fd < 0)
return;
if(num%5==0)
{
::ioctl(fd, LED1, 0);
}
else if(num%7==0)
{
::ioctl(fd, LED2, 0);
}
else
{
::ioctl(fd, LED1, 1);
::ioctl(fd, LED2, 1);
::ioctl(fd, LED3, 1);
::ioctl(fd, LED4, 1);
}
}
//初始化操作.不仅开头调用,每次计算完结果都会调用。
void calculator::init()
{
if(!expStack.isEmpty())
expStack.clear();
if(!opStack.isEmpty())
opStack.clear();
opStack.push('#');
complete=true;
emit whichBtn(INIT);
}
// return num
void calculator::digitBtn(char ch)
{
QString s = ui->lineEdit->text();
if(!complete)
ui->lineEdit->setText(s+ch);
else
{
ui->lineEdit->setText(QString(ch));
complete = false;
}
emit whichBtn(DIGIT);
}
//open or close the num
void calculator::enableDigit(int type)
{
bool enable=true;
if(RIGHT==type)
enable=false;
ui->num0->setEnabled(enable);
ui->num1->setEnabled(enable);
ui->num2->setEnabled(enable);
ui->num3->setEnabled(enable);
ui->num4->setEnabled(enable);
ui->num5->setEnabled(enable);
ui->num6->setEnabled(enable);
ui->num7->setEnabled(enable);
ui->num8->setEnabled(enable);
ui->num9->setEnabled(enable);
//ui->btnDot->setEnabled(enable);
}
//------------------enableOp---------
//接受一个整数参数 type,根据这个参数的值来确定是否启用某些操作按钮。
void calculator::enableOp(int type)
{
bool enable = false;
switch(type)
{
case RIGHT:
case DIGIT:enable = true;
break;
case INIT:
case OPERA:
case LEFT:enable = false;
break;
default:return;
}
ui->mulButton->setEnabled(enable);
ui->excButton->setEnabled(enable);
ui->addButton->setEnabled(enable);
ui->subButton->setEnabled(enable);
}
//open"("
void calculator::enableLeft(int type)
{
bool enable = false;
switch(type)
{
case RIGHT:
case DIGIT:
break;
case INIT:
case LEFT:
case OPERA:enable = true;
break;
default:return;
}
ui->parentheseLeft->setEnabled(enable);
}
// enable ")"
void calculator::enableRight(int type)
{
bool enable = false;
switch(type)
{
case INIT:
case OPERA:
break;
case LEFT:enable = true;
case RIGHT:
case DIGIT:
if(lefts)
enable = true;
break;
default:return;
}
ui->parentheseRight->setEnabled(enable);
}
//enable "="
void calculator::enableEqual(int type)
{
bool enable = false;
switch(type)
{
case OPERA:
case LEFT:
break;
case ROOT:
case RIGHT:
case DIGIT:
enable = true;
break;
default:return;
}
ui->equButton->setEnabled(enable);
}
//just delete one--->back
void calculator::on_clearButton_clicked()
{
QString s = ui->lineEdit->text();
s=s.mid(0,s.size()-1);
ui->lineEdit->setText(s);
}
void calculator::on_num0_clicked()
{
digitBtn('0');
}
void calculator::on_num1_clicked()
{
digitBtn('1');
}
void calculator::on_num2_clicked()
{
digitBtn('2');
}
void calculator::on_num3_clicked()
{
digitBtn('3');
}
void calculator::on_num4_clicked()
{
digitBtn('4');
}
void calculator::on_num5_clicked()
{
digitBtn('5');
}
void calculator::on_num6_clicked()
{
digitBtn('6');
}
void calculator::on_num7_clicked()
{
digitBtn('7');
}
void calculator::on_num8_clicked()
{
digitBtn('8');
}
void calculator::on_num9_clicked()
{
digitBtn('9');
}
void calculator::on_addButton_clicked()
{
QString s = ui->lineEdit->text();
ui->lineEdit->setText(s+"+");
emit whichBtn(OPERA);
}
void calculator::on_subButton_clicked()
{
QString s = ui->lineEdit->text();
ui->lineEdit->setText(s+"-");
emit whichBtn(OPERA);
}
void calculator::on_mulButton_clicked()
{
QString s = ui->lineEdit->text();
ui->lineEdit->setText(s+"*");
emit whichBtn(OPERA);
}
void calculator::on_excButton_clicked()
{
QString s = ui->lineEdit->text();
ui->lineEdit->setText(s+"/");
emit whichBtn(OPERA);
}
//根号
void calculator::on_rootnumButton_clicked()
{
QString s = ui->lineEdit->text();
ui->lineEdit->setText(s+"√");
emit whichBtn(ROOT);
}
//平方
void calculator::on_squButton_clicked()
{
QString s = ui->lineEdit->text();
ui->lineEdit->setText(s+"^");
emit whichBtn(ROOT);
}
void calculator::on_parentheseLeft_clicked()
{
QString s = ui->lineEdit->text();
if(!complete)
ui->lineEdit->setText(s+"(");
else
{
ui->lineEdit->setText("(");
complete = false;
}
emit whichBtn(LEFT);
lefts++;
}
void calculator::on_parentheseRight_clicked()
{
QString s = ui->lineEdit->text();
if(!complete)
ui->lineEdit->setText(s+")");
lefts--;
emit whichBtn(RIGHT);
}
//得到运算符的优先级
quint16 calculator::getLevel(const QChar &oper)
{
switch(oper.cell())
{
case '#':
case '(':return 0;
case '+':
case '-':return 1;
case '*':
case '/': return 2;
case '^': // Added case for square operator
case 0x221A:return 3; // Added case for root operator
}
return 0;
}
//转换为后缀表达式,实现最主要功能
void calculator::toPostfix()
{
QString exp = ui->lineEdit->text();
for(int i = 0; i < exp.length(); i++)
{
if(exp[i].isDigit() || exp[i] == '.')
{
postfix.push_back(exp[i]);
}
else if(exp[i] == '(')
{
opStack.push(exp[i]);
}
else if(exp[i] == ')')
{
postfix.push_back(' ');
while(opStack.top() != '(')
{
postfix.push_back(opStack.pop());
}
opStack.pop(); // Pop '('
}
else if(exp[i] ==0x221A)
{
opStack.push(exp[i]);
}
else if(getLevel(exp[i]) > getLevel(opStack.top()))
{
postfix.push_back(' ');
opStack.push(exp[i]);
}
else
{
postfix.push_back(' ');
while(getLevel(exp[i]) <= getLevel(opStack.top()))
{
postfix.push_back(opStack.pop());
}
opStack.push(exp[i]);
}
}
while(opStack.top() != '#')
{
QChar c = opStack.pop();
postfix.push_back(' ');
postfix.push_back(c);
}
}
void calculator::evaluation()
{
QString tem;
QStack<double> ans;
for(int i = 0; i < postfix.size(); i++)
{
if(postfix[i].isDigit() || postfix[i] == '.')
{
tem.push_back(postfix[i]);
}
else if(postfix[i] == 0x221A)
{
if(ans.isEmpty()) {
qDebug() << "Not enough operands on stack for square root";
return;
}
double a = ans.pop();
if (a < 0) {
qDebug() << "Square root of a negative number is undefined";
return;
}
ans.push(sqrt(a));
}
else if(postfix[i] == '^')
{
if(ans.isEmpty()) {
qDebug() << "Not enough operands on stack for square";
return;
}
double a = ans.pop();
ans.push(pow(a, 2)); // 使用 pow 函数计算平方
}
else if(postfix[i] == ' ')
{
if(!tem.isEmpty())
{
ans.push(tem.toDouble());
tem.clear();
}
}
else
{
if(ans.size() < 2) {
qDebug() << "Not enough operands on stack";
return;
}
double a = ans.pop();
double b = ans.pop();
switch(postfix[i].cell())
{
case '+': ans.push(b + a); break;
case '-': ans.push(b - a); break;
case '*': ans.push(b * a); break;
case '/': ans.push(b / a); break;
//case '%': ans.push((int)b % (int)a); break;
}
}
}
if(ans.isEmpty()) {
qDebug() << "No result found";
return;
}
LED(ans.top());//
ui->lineEdit->setText(QString::number(ans.top()));
}
void calculator::on_equButton_clicked()
{
//如果还没输入,那么等于号不起作用
if(ui->lineEdit->text()=="0")
return;
toPostfix();
evaluation();
init();
}
calculator.h
#ifndef CALCULATOR_H
#define CALCULATOR_H
#include <QWidget>
#include <QStack>
const int INIT = 0;
const int DIGIT = 1;
const int OPERA = 2;
const int LEFT = 3;
const int RIGHT = 4;
const int ROOT = 5;
namespace Ui {
class calculator;
}
class calculator : public QWidget
{
Q_OBJECT
public:
explicit calculator(QWidget *parent = 0);
~calculator();
void init();//Init
void digitBtn(char ch);//num button
quint16 getLevel(const QChar& oper);//得到运算符等级
void toPostfix();//转换成后缀表达式
void evaluation();//求值
void LED(int num);//LED
private slots:
void enableDigit(int type);//open or close the num
void enableOp(int type);//接受一个整数参数 type,根据这个参数的值来确定是否启用操作按钮。
void enableLeft(int type);// enable "("
void enableRight(int type);// enable ")"
void enableEqual(int type);//enable "="
void on_clearButton_clicked();
//void timerSingleClick(); //定时器事件,处理单击任务
void on_num0_clicked();
void on_num1_clicked();
void on_num2_clicked();
void on_num3_clicked();
void on_num4_clicked();
void on_num5_clicked();
void on_num6_clicked();
void on_num7_clicked();
void on_num8_clicked();
void on_num9_clicked();
void on_addButton_clicked();
void on_subButton_clicked();
void on_mulButton_clicked();
void on_excButton_clicked();
void on_parentheseLeft_clicked();
void on_parentheseRight_clicked();
void on_equButton_clicked();
void on_rootnumButton_clicked();
void on_squButton_clicked();
private:
Ui::calculator *ui;
QStack<QChar> expStack;//后缀表达式栈
QStack<QChar> opStack;//运算符栈
QString postfix;//存储后缀表达式
bool complete;//表达式是否计算完成
int lefts;
signals:
void whichBtn(int type);
};
#endif // CALCULATOR_H
编译烧录
进入工程所在的终端然后依次执行,具体可以参考GEC6818交叉编译的文章后面部分。
source /usr/local/Qt-Embedded-5.7.0-env
qmake
make
编译后使用软件secureCRT
软件,使用rx+文件名
(可以自定义)进行文件传输,传输后检查驱动(上面文章中有详细介绍),更改权限,即可以运行程序了。命令如下:
insmod led.ko //加载驱动
rx calculator //传输文件
chmod +x calculator //增加可执行权限
./calculator //运行
本文中涉及的工程代码在我的github中可以进行下载02-calculator2