1、QT的编译过程(简单熟悉一下)
为了实现以下窗口的创建

首先在记事本中编写代码并保存在地址a:
#include <QApplication>//程序
#include<QLabel>//标签
#include<QLineEdit>//编辑框
#include<QPushButton>//按钮
#include<QHBoxLayout>//水平布局
#include<QVBoxLayout>//垂直布局
#include<QWidget>//窗口
int main(int argc,char *argv\[\])
{
QApplication app(argc,argv);
QLabel *infoLabel=new QLabel;
QLabel *openLabel=new QLabel;
QlineEdit *cmdLineEdit=new QLineEdit;
QPushButton *commitButton=new QPushButton;
QPushButton *cancelButton=new QPushButton;
QPushButton *browseButton=new QPushButton;
infoLabel->setText("input cmd:")
openLabel->setText("open")
commitButton->setText("commit");
cancelButton->setText("cancel");
browseButton->setText("browse");
QHBoxLayout *cmdLayout=new QHBoxLayout;//水平布局对象
cmdLayout->addWidget(openLabel);
cmdLayout->addWidget(cmdLineEdit);
QHBoxLayout *buttonLayout=new QHBoxLayout;
buttonLayout->addWidget(commitButton);
buttonLayout->addWidget(cancelButton);
buttonLayout->addWidget(browseButton);
QVBoxLayout *mainLayout=new QVBoxLayout;
mainLayout->addWidget(infoLabel);
mainLayout->addLayout(cmdLayout);//垂直布局中添加水平布局
mainLayout->addLayout(buttonLayout);
QWidget w;
w.setLayout(mainLayout);
w.show();
return app.exec();
}
首先可以在记事本中编写以上代码
之后在QT下载的包中寻找类似于以下的控制台:

打开控制台,先打开QT下载在某个盘(假设下载在C盘),输入指令:

之后将地址a进行复制 并打开:

打开之后先创建一个工程文件(如果失败需要新增环境变量,在高级设置中,将QT所在的bin文件夹整体加到path路径中并保存,之后重启电脑(如果设置之后还没用)):

会自动生成一个文件,用记事本打开之后添加一句话:

之后再在控制台输入命令:qmake
最终生成情况:

之后再在控制台输入:

之后在release中打开qmake.exe,生成的结果就是刚刚编写的代码:
添加一行代码:设置窗口的窗口名

结果如下:

2、Qt Creator
widget类似于一个弹窗,上边演示的就是这个类
mainwindow相当于一个包含菜单的窗口
在设计界面可以设计显示的界面布局,右边可以修改属性

生成结果:

3、信号与槽
实现文本框输入内容能打开该快捷方式
(1)点击按钮实现跳转
首先在ui界面右键点击按钮:


之后对函数进行编写:
void Widget::on_browseButton_clicked()
{
QString program=ui->cmdLineEdit->text();//获取文本框的数据
//创建process对象
QProcess *myProcess = new QProcess(this);
myProcess->start(program);//获取lineedit中的数据
}
点击运行之后,在文本框中输入某快捷键的目标内容之后,点击按钮成功运行快捷键内容!
(2)在文本框中输入快捷方式之后按下回车实现跳转
除了转到信号槽的方法之外,还可以选择直接在程序的构造函数中添加代码,记住文本框的命名,之后在widget.cpp中继续修改构造函数,使用connect连接函数进行处理:
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
connect(ui->cmdLineEdit,SIGNAL(returnPressed()),this,SLOT(on_browseButton_clicked()));//连接信号与槽 谁发出信号、发出什么信号、谁处理信号、怎么处理信号(调用按下按钮的函数)
}
最终实现在文本框内输入内容,按下回车也可以打开快捷方式!
(3)地址(指针)实现取消的功能
首先在头文件中添加(实现取消的功能)槽函数:
private slots:
void on_browseButton_clicked();
void on_cancelButton_clicked();
之后在widget.cpp中新添加该函数的实现方法:
void Widget::on_cancelButton_clicked()
{
this->close();
}
之后再在构造函数中新增加一行连接函数的代码:
connect(ui->cancelButton,&QPushButton::clicked,this,&Widget::on_cancelButton_clicked);
(4)不使用函数,直接使用表达式进行连接(函数中只有一句话,代码较少)
实现点击浏览时跳出弹框
先在头文件添加以下代码:
#include<QMessage>
之后再在widget.cpp的构造函数中添加一个连接:
connect(ui->commitButton,&QPushButton::clicked,[this]()
{
QMessageBox::information(this,"信息","点击浏览");
});
结果如下:

4、四则运算器
首先在Ui设置计算器的界面:
使用Buttons中的Push Button为按键,并将该按键的最小最大都设置为40,之后复制按钮,按住ctrl鼠标点击空白处即可复制一个
使用Input Widgets中的Line Edit即可生成显示框
之后将所有按键选择栅格布局即可
里边有加减乘除以及清空、回退(在按键上可加图片进行显示)和括号的功能:

之后对按键的命名进行更改:

之后无论输入什么,都需要在编辑框内进行显示,因此需要在头文件中添加一个对象,用于记录表达式:
private:
Ui::Widget *ui;
QString expression;
};
之后在Ui界面的1按键右键选择转到槽,加入以下代码:
void Widget::on_oneButton_clicked()
{
expression+="1";
ui->mainlineEdit->setText(expression);
}
运行即可实现1的显示:

之后对除了c和←箭头外的其余按键都进行转到槽,代码类似上边:

之后对c(清空)功能进行编写:
void Widget::on_clearButton_clicked()
{
expression.clear();
ui->mainlineEdit->clear();
}
在回退按钮上添加图片:
在widget的构造函数中添加:
//按钮上放图片
QIcon con("C:\\Users\\xzhao\\Desktop\\daima\\QTOnline\\calculator\\huitui.png");
ui->delButton->setIcon(con);
如果图片太小,可以在右下角这里设置宽高:

同样在构造函数中对标题和字体进行设置:
ui->setupUi(this);
this->setWindowTitle("计算器");
QFont f("仿宋",14);//字体设置
ui->mainlineEdit->setFont(f);
之后对回退按钮的逻辑进行编写:
void Widget::on_delButton_clicked()
{
expression.chop(1);//参数表示从字符串最后往前删除的位数
ui->mainlineEdit->setText(expression);
}
如果需要给按钮添加颜色,依然在构造函数中添加:
//给按钮添加颜色
ui->equalButton->setStyleSheet("background:orange");

之后实现=的功能:
在头文件中添加:
#include<QStack>
#include <cmath>
#include <cctype> // for isdigit
#include <cstdlib> // for strtod
之后为实现运算完成后就自动清空编辑框在头文件的私有成员中添加标记:
bool needClear; // 是否需要清屏(刚完成一次计算)
之后cpp完整代码如下:
#include "widget.h"
#include "ui_widget.h"
#include <QStack>
#include <cmath>
#include <cctype>
#include <cstdlib>
#include <cstring>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
, needClear(false) // 初始化清屏标志
{
ui->setupUi(this);
this->setWindowTitle("计算器");
QFont f("仿宋",14);
ui->mainlineEdit->setFont(f);
QIcon con("C:\\Users\\xzhao\\Desktop\\daima\\QTOnline\\calculator\\huitui.png");
ui->delButton->setIcon(con);
ui->equalButton->setStyleSheet("background:orange");
}
Widget::~Widget()
{
delete ui;
}
// 数字按钮 0-9
void Widget::on_zeroButton_clicked()
{
if (needClear) {
ui->mainlineEdit->clear();
expression.clear();
needClear = false;
}
expression += "0";
ui->mainlineEdit->setText(expression);
}
void Widget::on_oneButton_clicked()
{
if (needClear) {
ui->mainlineEdit->clear();
expression.clear();
needClear = false;
}
expression += "1";
ui->mainlineEdit->setText(expression);
}
void Widget::on_twoButton_clicked()
{
if (needClear) {
ui->mainlineEdit->clear();
expression.clear();
needClear = false;
}
expression += "2";
ui->mainlineEdit->setText(expression);
}
void Widget::on_thereButton_clicked()
{
if (needClear) {
ui->mainlineEdit->clear();
expression.clear();
needClear = false;
}
expression += "3";
ui->mainlineEdit->setText(expression);
}
void Widget::on_fourButton_clicked()
{
if (needClear) {
ui->mainlineEdit->clear();
expression.clear();
needClear = false;
}
expression += "4";
ui->mainlineEdit->setText(expression);
}
void Widget::on_fiveButton_clicked()
{
if (needClear) {
ui->mainlineEdit->clear();
expression.clear();
needClear = false;
}
expression += "5";
ui->mainlineEdit->setText(expression);
}
void Widget::on_sixButton_clicked()
{
if (needClear) {
ui->mainlineEdit->clear();
expression.clear();
needClear = false;
}
expression += "6";
ui->mainlineEdit->setText(expression);
}
void Widget::on_sevenButton_clicked()
{
if (needClear) {
ui->mainlineEdit->clear();
expression.clear();
needClear = false;
}
expression += "7";
ui->mainlineEdit->setText(expression);
}
void Widget::on_eightButton_clicked()
{
if (needClear) {
ui->mainlineEdit->clear();
expression.clear();
needClear = false;
}
expression += "8";
ui->mainlineEdit->setText(expression);
}
void Widget::on_nineButton_clicked()
{
if (needClear) {
ui->mainlineEdit->clear();
expression.clear();
needClear = false;
}
expression += "9";
ui->mainlineEdit->setText(expression);
}
// 运算符按钮
void Widget::on_addButton_clicked()
{
if (needClear) {
ui->mainlineEdit->clear();
expression.clear();
needClear = false;
}
expression += "+";
ui->mainlineEdit->setText(expression);
void Widget::on_subButton_clicked()
{
if (needClear) {
ui->mainlineEdit->clear();
expression.clear();
needClear = false;
}
expression += "-";
ui->mainlineEdit->setText(expression);
}
void Widget::on_mulButton_clicked()
{
if (needClear) {
ui->mainlineEdit->clear();
expression.clear();
needClear = false;
}
expression += "×";
ui->mainlineEdit->setText(expression);
}
void Widget::on_divButton_clicked()
{
if (needClear) {
ui->mainlineEdit->clear();
expression.clear();
needClear = false;
}
expression += "/";
ui->mainlineEdit->setText(expression);
}
// 括号按钮
void Widget::on_leftButton_clicked()
{
if (needClear) {
ui->mainlineEdit->clear();
expression.clear();
needClear = false;
}
expression += "(";
ui->mainlineEdit->setText(expression);
}
void Widget::on_rightButton_clicked()
{
if (needClear) {
ui->mainlineEdit->clear();
expression.clear();
needClear = false;
}
expression += ")";
ui->mainlineEdit->setText(expression);
}
// 清除按钮
void Widget::on_clearButton_clicked()
{
expression.clear();
ui->mainlineEdit->clear();
needClear = false; // 手动清除时重置标志
}
// 退格按钮
void Widget::on_delButton_clicked()
{
// 退格时如果是刚计算完的状态,不做清屏,直接删除当前结果(或者可以先清屏再删除?为了合理,我们让退格也清除标志)
if (needClear) {
// 刚计算完,按退格应该清空并开始新输入,但退格一般用于删除上一个字符,这里简单处理:清空并重置
ui->mainlineEdit->clear();
expression.clear();
needClear = false;
return;
}
expression.chop(1);
ui->mainlineEdit->setText(expression);
}
// 等号按钮
void Widget::on_equalButton_clicked()
{
// 如果刚计算完且未开始新输入,再按等号无效
if (needClear) return;
QString expr = ui->mainlineEdit->text();
if (expr.isEmpty()) {
ui->mainlineEdit->setText("0");
return;
}
expr.replace("×", "*");
expr.replace("÷", "/");
QByteArray ba = expr.toLocal8Bit();
const char* opt = ba.data();
auto priority = [](char op) -> int {
switch (op) {
case '+': return 1;
case '-': return 1;
case '*': return 2;
case '/': return 2;
default: return 0;
}
};
auto applyOp = [](double a, double b, char op) -> double {
switch (op) {
case '+': return a + b;
case '-': return a - b;
case '*': return a * b;
case '/': return a / b;
default: return 0.0;
}
};
QStack<double> valStack;
QStack<char> opStack;
int i = 0;
int len = strlen(opt);
while (i < len) {
char ch = opt[i];
if (ch == ' ') { i++; continue; }
if (isdigit(ch) || ch == '.') {
char* end;
double num = strtod(opt + i, &end);
valStack.push(num);
i = end - opt;
continue;
}
if (ch == '(') {
opStack.push('(');
i++;
continue;
}
if (ch == ')') {
while (!opStack.isEmpty() && opStack.top() != '(') {
char op = opStack.pop();
double b = valStack.pop();
double a = valStack.pop();
valStack.push(applyOp(a, b, op));
}
if (!opStack.isEmpty() && opStack.top() == '(')
opStack.pop();
i++;
continue;
}
if (ch == '+' || ch == '-' || ch == '*' || ch == '/') {
if (ch == '-' && (i == 0 || opt[i-1] == '(')) {
char* end;
double num = strtod(opt + i, &end);
valStack.push(num);
i = end - opt;
continue;
}
while (!opStack.isEmpty() && opStack.top() != '(' &&
priority(ch) <= priority(opStack.top())) {
char op = opStack.pop();
double b = valStack.pop();
double a = valStack.pop();
valStack.push(applyOp(a, b, op));
}
opStack.push(ch);
i++;
continue;
}
i++;
}
while (!opStack.isEmpty()) {
char op = opStack.pop();
if (op == '(') {
ui->mainlineEdit->setText("Error");
return;
}
if (valStack.size() < 2) {
ui->mainlineEdit->setText("Error");
return;
}
double b = valStack.pop();
double a = valStack.pop();
valStack.push(applyOp(a, b, op));
}
if (valStack.size() != 1) {
ui->mainlineEdit->setText("Error");
return;
}
double result = valStack.pop();
QString resultStr;
if (std::abs(result - std::round(result)) < 1e-9)
resultStr = QString::number(static_cast<long long>(result));
else
resultStr = QString::number(result, 'g', 10);
ui->mainlineEdit->setText(resultStr);
expression.clear(); // 清空成员变量,避免下次累加
needClear = true; // 下次输入自动清屏
}
之后计算器能正常使用!!!
5、QObject定时器
实现电子相册的功能:1s切换一张图片
在头文件中添加宏定义:
#define TIMEOUT (1*1000)//ms是单位
并添加图片编号、定时器编号以及一个公开函数(名字一定要写对!timerEvent):
public:
Widget(QWidget *parent = nullptr);
virtual void timerEvent(QTimerEvent *event);
~Widget();
private slots:
void on_startButton_clicked();
private:
Ui::Widget *ui;
int myTimerid;//定时器编号
int pictureId;//图片编号
};
之后在ui界面中添加两个push button按钮:
并在开始按钮右键转为槽,其中开始按钮的命名为startButton,暂停按钮的命名为stopButton

再添加一个label:

之后在cpp文件中:
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
pictureId=2;
QPixmap pix("C:\\Users\\xzhao\\Desktop\\daima\\QTOnline\\QobjectTimer\\1.jpg");
ui->label->setPixmap(pix);
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_startButton_clicked()
{
//开启定时器,返回编号
myTimerid=this->startTimer(TIMEOUT);
}
void Widget::timerEvent(QTimerEvent *event){
if(event->timerId()!=myTimerid)
return;
QString path("C:\\Users\\xzhao\\Desktop\\daima\\QTOnline\\QobjectTimer\\");
path+=QString::number(pictureId);
path+=".jpg";
QPixmap pix(path);
ui->label->setPixmap(pix);
pictureId++;
if(pictureId==5)//目前只有4张图片,一旦超过四张就重新返回第一张
pictureId=1;
}
选中label之后,右下角处勾选这个,使得所有图片都适配label框!
运行程序,点击开始之后,结果如下:

1s换一张图片
之后对暂停按钮转向槽:
添加一句代码:
this->killTimer(myTimerid);
结果如下:点击开始就开始播放,暂停则停止播放

6、QTime定时器
新创建一个项目,命名为QTimer
头文件如下:
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include<QTimer>
#define TIMEOUT (1*1000)
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
private slots:
void on_pushButton_clicked();
void timeoutSlot();
void on_pushButton_2_clicked();
private:
Ui::Widget *ui;
QTimer *timer;
int pictureID;
};
#endif // WIDGET_H
cpp文件如下:
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
timer=new QTimer;
pictureID=2;
QImage img;
img.load("C:\\Users\\xzhao\\Desktop\\daima\\QTOnline\\QTimer\\1.jpg");
ui->label->setPixmap(QPixmap::fromImage(img));
connect(timer,&QTimer::timeout,this,&Widget::timeoutSlot);//定时器时间到发出timeout信号
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_pushButton_clicked()
{
timer->start(TIMEOUT);
}
void Widget::timeoutSlot()
{
QString path("C:\\Users\\xzhao\\Desktop\\daima\\QTOnline\\QTimer\\");
path+=QString::number(pictureID);
path+=(".jpg");
QImage img;
img.load(path);
ui->label->setPixmap(QPixmap::fromImage(img));
pictureID++;
if(pictureID==5)
pictureID=1;
}
void Widget::on_pushButton_2_clicked()
{
timer->stop();
}
运行后结果与上述一致
QTimer可以实现单次点击,在界面中新增一个单次的按钮,点击按钮后,等待1s后只运行一次程序(只换一次照片):
