The first step is to create a window
//有且只有一个应用程序类的对象
QApplication a(argc, argv);
//MyWidget继承与QWidget, QWidget是一个窗口基类
//所以MyWidget也是窗口类
//w就是一个窗口
MyWidget w;
//窗口创建默认是隐藏,需要人为显示
w.show();
//让程序一直执行,等待用户操作
//等待事件的发生
a.exec();
return 0;
The next step is to specify the parent object as the child window
Here is a button
int main(int argc, char **argv)
{
QApplication app(argc, argv);
QWidget w;
w.setWindowTitle(QString("我是靓仔")); //设置标题
/*如果不指定父对象,对象和对象(窗口和窗口)没有关系,独立
* a指定b为它的父对象,a放在b的上面
* 指定父对象,有2种方式:
* 1)setParent
* 2)通过构造函数传参
* 指定父对象,只需要父对象显示,上面的子对象自动显示
*/
QPushButton b;
b.setText("^_^"); //给按钮设置内容
b.setParent(&w); //指定父对象
b.move(100, 100); //移动坐标
QPushButton b1(&w); //通过构造函数传参
b1.setText("abc");
w.show();
app.exec();
return 0;
}
Next is the core of the interface, signal and slot
b2 = new QPushButton(this);
b2->setText("abc");
connect(b2, &QPushButton::released, this, &MainWidget::mySlot);
Signals and slots are used like software interrupts in hardware development
Then we create a new cpp file to create a child window, and then switch back and forth with the main window
Main window code
MainWidget::MainWidget(QWidget *parent)
: QWidget(parent)
{
setWindowTitle("老大");
//this->setWindowTitle("老大");
b3.setParent(this);
b3.setText("切换到子窗口");
b3.move(50, 50);
//显示子窗口
//subWin.show();
connect(&b3, &QPushButton::released, this, &MainWidget::changeWin);
//处理子窗口的信号
// void (SubWidget::*funSignal)() = &SubWidget::mySignal;
// connect(&subWin, funSignal, this, &MainWidget::dealSub);
// void (SubWidget::*testSignal)(int, QString) = &SubWidget::mySignal;
// connect(&subWin, testSignal, this, &MainWidget::dealSlot);
//Qt4信号连接
//Qt4槽函数必须有slots关键字来修饰
connect(&subWin, SIGNAL(mySignal()), this, SLOT(dealSub()) );
connect(&subWin, SIGNAL(mySignal(int,QString)),
this, SLOT(dealSlot(int,QString)) );
// SIGNAL SLOT 将函数名字 -> 字符串 不进行错误检查
//Lambda表达式, 匿名函数对象
//C++11增加的新特性, 项目文件: CONFIG += C++11
//Qt配合信号一起使用,非常方便
QPushButton *b4 = new QPushButton(this);
b4->setText("Lambda表达式");
b4->move(150, 150);
int a = 10, b = 100;
connect(b4, &QPushButton::clicked,
// = :把外部所有局部变量、类中所有成员以值传递方式
// this: 类中所有成员以值传递方式
// & : 把外部所有局部变量, 引用符号
[=](bool isCheck)
{
qDebug() << isCheck;
}
);
resize(400, 300);
}
void MainWidget::dealSlot(int a, QString str)
{
// str.toUtf8() -> 字节数组QByteArray
// ……data() -> QByteArray -> char *
qDebug() << a << str.toUtf8().data();
}
void MainWidget::mySlot()
{
b2->setText("123");
}
void MainWidget::changeWin()
{
//子窗口显示
subWin.show();
//本窗口隐藏
this->hide();
}
void MainWidget::dealSub()
{
//子窗口隐藏
subWin.hide();
//本窗口显示
show();
}
MainWidget::~MainWidget()
{
}
Subwindow code
SubWidget::SubWidget(QWidget *parent) : QWidget(parent)
{
this->setWindowTitle("小弟");
b.setParent(this);
b.setText("切换到主窗口");
connect(&b, &QPushButton::clicked, this, &SubWidget::sendSlot);
resize(400, 300);
}
void SubWidget::sendSlot()
{
emit mySignal();
emit mySignal(250, "我是子窗口");
}
And then there’s the coordinates
/* 子窗口,坐标系统相对于父窗口
* 原点:相对于窗口空白区域左上角(不包括边框)
* x: 往右递增
* y: 往下递增
*/
QPushButton *b1 = new QPushButton(this);
b1->move(100, 100);
b1->setText("^_^");
b1->resize(200, 100);
QPushButton *b2 = new QPushButton(b1);
b2->move(10, 10);
b2->setText("@_@");
Let’s write a small case
Resource preparation
Code
//开始游戏
void MyWidget::on_pushButtonStart_clicked()
{
//获取下拉框的时间 .toInt():字符串转换为 int
gameTime = ui->comboBox->currentText().toInt();
qDebug() << gameTime << "s";
//切换到游戏界面
//ui->stackedWidget->setCurrentIndex(1);
ui->stackedWidget->setCurrentWidget(ui->pageGame);
int num;
//以从0时0分0秒到现在的秒数为种子
qsrand( QTime(0,0,0).secsTo( QTime::currentTime() ) );
//调用全局的qrand()函数生成随机数,对10000取余,保证位于10000的范围内
while( ( num = qrand()%10000 ) < 999 );
randStr = QString::number(num);
qDebug() << "randNum = " << randStr;
//设置进度条
ui->progressBar->setMinimum(0);//最小值
ui->progressBar->setMaximum(gameTime);//最大值
ui->progressBar->setValue(gameTime); //当前值
gameTimerId = 0;
//启动定时器
gameTimerId = startTimer(1000); //以 1000 毫秒(即1s)作为时间间隔
resultStr.clear();
ui->textEdit->clear();
}
//退出游戏
void MyWidget::on_pushButtonEnd_clicked()
{
this->close(); //关闭窗口
}
void MyWidget::timerEvent(QTimerEvent *e)
{
if(e->timerId() == gameTimerId)//游戏时间
{
gameTime--;
//设置进度条
ui->progressBar->setValue(gameTime); //当前值
if(0 == gameTime)//时间到
{
//关闭定时器
killTimer(gameTimerId);
QMessageBox::information(this, "失败", "时间到了啊!!!");
overMovie.start();//启动动画
//切换失败动画页面
//ui->stackedWidget->setCurrentIndex(2);
ui->stackedWidget->setCurrentWidget(ui->pageOver);
overTimerId = startTimer(5000); //启动定时器
}
}
else if(e->timerId() == overTimerId)//失败动画时间
{
//停止动画,停止定时器,回到游戏设置页面
overMovie.stop();//停止动画
killTimer(overTimerId); //停止定时器
//切换到游戏设置页面
ui->stackedWidget->setCurrentWidget(ui->pageSet);
}
else if(e->timerId() == winTimerId)//胜利动画时间
{
winMovie.stop();//停止动画
killTimer(winTimerId); //停止定时器
//切换到游戏设置页面
ui->stackedWidget->setCurrentWidget(ui->pageSet);
}
}
UI interface design
Operation results
This is the source code of the video. The video comes from bilibili