界面编程
提供一个已知界面需求,它的实现思路是什么?
● 先去搜索引擎搜一下相关的类或者方法;
● 查看帮助文档,先找到相关的属性,再看相对应的操作方法。
修改默认界面大小为 480 * 300
// widget.cpp
#include "widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
resize(480, 300);
// this->resize(480, 300); // 两句话等价
}
Widget::~Widget()
{
}
窗口增加一个按钮
QPushButton::QPushButton(QWidget *parent = 0);
凡是在构造方法中看到parent,代表把自己放到parent代表的窗体上
void move(int x, int y);
移动部件到父部件的某个位置
void setStyleSheet(const QString & styleSheet);
这个方法属于QWidget类,是个通用的方法,可以设置部件的各种样式。
styleSheet是一个样式表,兼容于css2,qt里叫qss
帮助文档直接搜索 Qt Style Sheets 即可看到一些demo
颜色查找:Qt::GlobalColor
颜色码对照表(👈 安全链接,放心点击即可)
设置显示文字
// widget.cpp
#include "widget.h"
#include <QPushButton>
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
resize(480, 300);
// this->resize(480, 300); // 两句话等价
QPushButton *btn = new QPushButton("Click me", this); // 需要在堆区创建,不能在栈区创建
}
Widget::~Widget()
{
}
设置按钮的颜色
// widget.cpp
#include "widget.h"
#include <QPushButton>
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
resize(480, 300);
// this->resize(480, 300); // 两句话等价
QPushButton *btn = new QPushButton("Click me", this); // 需要在堆区创建,不能在栈区创建
btn->setStyleSheet("color:yellow; background-color:blue");
}
Widget::~Widget()
{
}
改变按钮的位置
// widget.cpp
#include "widget.h"
#include <QPushButton>
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
resize(480, 300);
// this->resize(480, 300); // 两句话等价
QPushButton *btn = new QPushButton("Click me", this); // 需要在堆区创建,不能在栈区创建
btn->setStyleSheet("color:yellow; background-color:blue");
btn->move(200, 120);
}
Widget::~Widget()
{
}
QT 打印
信号与槽
对象和对象之间的通信
// QMetaObject::Connection QObject::connect
QMetaObject::Connection QObject::connect(const QObject * sender, const char * signal, \
const QObject * receiver, const char * method, \
Qt::ConnectionType type = Qt::AutoConnection) [static]
// receiver对象绑定了sender对象的signal信号,
// 一旦sender发出signal信号,那么receiver的method方法会被自动调用。
// 最后一个参数暂且忽略
点击按钮,关闭窗口
// widget.cpp
#include "widget.h"
#include <QPushButton>
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
resize(480, 300);
// this->resize(480, 300); // 两句话等价
QPushButton *btn = new QPushButton("Click me", this); // 需要在堆区创建,不能在栈区创建
btn->setStyleSheet("color:yellow; background-color:blue");
btn->move(200, 120);
QObject::connect(btn, SIGNAL(clicked()), this, SLOT(close()));
}
Widget::~Widget()
{
}
自定义槽
● 类似于 C++ 里定义一个方法,但是需要增加关键字修饰
● 槽方法本身就是一个可调用的方法
private/public slots:
点击按钮,打印 “Hello”
// widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
public slots:
void printSlot();
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
// widget.cpp
#include "widget.h"
#include <QPushButton>
#include <QDebug>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
resize(480, 300);
// this->resize(480, 300); // 两句话等价
QPushButton *btn = new QPushButton("Click me", this); // 需要在堆区创建,不能在栈区创建
btn->setStyleSheet("color:yellow; background-color:blue");
btn->move(200, 120);
QObject::connect(btn, SIGNAL(clicked()), this, SLOT(printSlot()));
}
void Widget::printSlot()
{
qDebug() << "Hello~";
}
Widget::~Widget()
{
}
添加一个标签组件(QLabel)
标签默认显示 “Hi~”,点击按钮后,标签的文字改为 “Hola!”,并且颜色变为红色。
// widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QPushButton>
#include <QLabel>
class Widget : public QWidget
{
Q_OBJECT
QPushButton *btn;
QLabel *label;
public:
Widget(QWidget *parent = 0);
~Widget();
public slots:
void printSlot();
};
// widget.cpp
#include "widget.h"
#include <QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
resize(480, 300);
// this->resize(480, 300); // 两句话等价
btn = new QPushButton("Click me", this); // 需要在堆区创建,不能在栈区创建
// btn->setStyleSheet("color:yellow; background-color:blue");
btn->move(200, 120);
// QObject::connect(btn, SIGNAL(clicked()), this, SLOT(printSlot()));
label = new QLabel("Hi~", this);
QObject::connect(btn, SIGNAL(clicked()), this, SLOT(printSlot()));
}
void Widget::printSlot()
{
qDebug() << "Hello~";
btn->setStyleSheet("color:yellow; background-color:blue");
label->setText("Hola!");
label->resize(80, 50); // 一开始的"Hi~"比"Hola!"短,所以重设一下大小
label->setStyleSheet("color:red");
}
Widget::~Widget()
{
}
点击按钮,记录点击的次数并输出
// widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QPushButton>
#include <QLabel>
class Widget : public QWidget
{
Q_OBJECT
QPushButton *btn;
QLabel *label;
int count;
public:
Widget(QWidget *parent = 0);
~Widget();
public slots:
void printSlot();
};
#endif // WIDGET_H
// widget.cpp
#include "widget.h"
#include <QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
count = 0;
resize(480, 300);
// this->resize(480, 300); // 两句话等价
btn = new QPushButton("Click me", this); // 需要在堆区创建,不能在栈区创建
// btn->setStyleSheet("color:yellow; background-color:blue");
btn->move(200, 120);
label = new QLabel("Hi~", this);
QObject::connect(btn, SIGNAL(clicked()), this, SLOT(printSlot()));
}
void Widget::printSlot()
{
qDebug() << "Hello~";
qDebug("count = %d", ++count);
}
Widget::~Widget()
{
}
自定义信号
● 与 C++ 里定义一个方法类似,但此方法只有声明没有实现;
● 本身不可以被直接调用,只能被发送;
● 信号可以携带参数,槽函数接收到以后可以直接拿到相应的参数数据。
signals: // 定义信号
emit: // 发送信号
自定义信号与槽的连接
在按钮的槽方法中记录点击次数,并作为参数发送信号。
重新定义槽函数与此信号做连接,槽函数打印其值。
// widget.h
#define WIDGET_H
#include <QWidget>
#include <QPushButton>
#include <QLabel>
class Widget : public QWidget
{
Q_OBJECT
QPushButton *btn;
QLabel *label;
int count;
public:
Widget(QWidget *parent = 0);
~Widget();
public slots:
void emitSlot();
void recvSlot(int);
signals:
void emitSignal(int);
};
#endif // WIDGET_H
// widget.cpp
#include "widget.h"
#include <QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
count = 0;
resize(480, 300);
// this->resize(480, 300); // 两句话等价
btn = new QPushButton("Click me", this); // 需要在堆区创建,不能在栈区创建
// btn->setStyleSheet("color:yellow; background-color:blue");
btn->move(200, 120);
label = new QLabel("Hi~", this);
QObject::connect(btn, SIGNAL(clicked()), this, SLOT(emitSlot()));
QObject::connect(this, SIGNAL(emitSignal(int)), this, SLOT(recvSlot(int)));
}
void Widget::emitSlot()
{
count++;
emit emitSignal(count);
}
void Widget::recvSlot(int cnt)
{
qDebug() << "count = " << cnt;
}
Widget::~Widget()
{
}
信号与槽的关联关系
信号与槽相连:
QObject::connect( sender, SIGNAL(signal), receiver, SLOT(method) );
信号与信号相连:
QObject::connect( sender, SIGNAL(signal1), receiver, SIGNAL(signal2) );
同一个信号连接到多个槽:
QObject::connect( sender, SIGNAL(signal), receiver, SLOT(method1) );
QObject::connect( sender, SIGNAL(signal), receiver, SLOT(method2) );
......
多个信号连接到同一个槽:
QObject::connect( sender, SIGNAL(signal1), receiver, SLOT(method) );
QObject::connect( sender, SIGNAL(signal2), receiver, SLOT(method) );
......
信号槽的参数对应关系
信号的参数个数必须 >= 槽的参数个数;
个数匹配的参数,其类型也必须匹配;
可以传递任意个参数,如果参数过多,那么应该考虑使用结构体或者类(对象)来传递。
💡 练习
写一个登录界面,上面可以输入用户名和密码(QLineEdit 实现),输入完成点击登录后,
校验账号密码,如果验证成功,那么打印“登录成功”,否则关闭窗体。
// widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QPushButton>
#include <QLabel>
#include <QLineEdit>
class Widget : public QWidget
{
Q_OBJECT
QPushButton *btn;
QLineEdit *username;
QLineEdit *password;
QString usr;
QString pwd;
QLabel *label;
QLabel *ulabel;
QLabel *plabel;
public:
Widget(QWidget *parent = 0);
~Widget();
public slots:
void verifySlot();
};
#endif // WIDGET_H
// widget.cpp
#include "widget.h"
#include <QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
resize(480, 300);
btn = new QPushButton("Login", this); // 需要在堆区创建,不能在栈区创建
btn->move(180, 220);
ulabel = new QLabel("Username: ", this);
ulabel->move(60, 80);
username = new QLineEdit(this);
username->move(180, 80);
username->setPlaceholderText("Please input...");
plabel = new QLabel("Password: ", this);
plabel->move(60, 160);
password = new QLineEdit(this);
password->move(180, 160);
password->setEchoMode(QLineEdit::Password);
password->setPlaceholderText("Please input...");
QObject::connect(btn, SIGNAL(clicked()), this, SLOT(verifySlot()));
label = new QLabel(this);
}
void Widget::verifySlot()
{
usr = username->text();
pwd = password->text();
label->resize(480, 300);
if (usr == "0828" && pwd == "0828")
{
// label->setText("Logined successfully!"); // 成功显示,但不美观
qDebug("Logined successfully!");
this->close();
QWidget *homePage = new QWidget;
homePage->resize(309, 500);
homePage->show();
}
else
{
// QObject::connect(btn, SIGNAL(clicked()), this, SLOT(close()));
// 不能这样写,需要点击两次按钮才会关闭小窗口
this->close();
}
}
Widget::~Widget()
{
}