Qt5 -- 基本控件 / 信号 / 槽

作者及原代码链接:跟小豆君学Qt

跟着学习;完整实现代码;示例截图;

QPushButton:

#include <QPushButton>

QPushButton button;
button.setText("This is a button");
button.resize(200, 100);
button.show();


// 从大到小变化的三个button
for(int i = 0; i < 3; ++i){
    QPushButton* buttonChild =  new QPushButton(this);
    buttonChild->setText(QString("This is a widget %1").arg(3-i));
    buttonChild->resize(100 * (3-i), 100);
    connect(buttonChild, SIGNAL(clicked()), buttonChild, SLOT(close()));    // 点击即关闭
}

Horizontal Slider:

// 设定滑动条范围
int max = 100;
int min = 0;
ui->horizontalSlider->setMaximum(max);
ui->horizontalSlider->setMinimum(min);

QWidget:所有GUI控件的基类

ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    setGeometry(0, 0, 800, 600);    // top, left, width, height
    move(100, 100);                 // 窗口移动
    setWindowFlags(Qt::CustomizeWindowHint|Qt::WindowStaysOnTopHint);    // 隐藏标题栏
}

常用标志:

Qt::Widget 默认窗口
Qt::Dialog 对话框
Qt::SplashScreen 启动窗口
Qt::SplashScreen 在还没有展示出主界面前的启动画面
Qt::FramelessWindowHint 隐藏标题栏,并且去掉窗口的边框,窗口不能移动和缩放。
Qt::CustomizeWindowHint 隐藏标题栏,不会去掉窗口的边框,窗口不能移动,但可以缩放。
Qt::WindowStaysOnTopHint 使窗口始终处于最顶部。类似于播放器中的总在最前功能。

设置背景色:

setAutoFillBackground(true);
QPalette pa = this->palette();
pa.setBrush(QPalette::Background, QBrush(Qt::cyan));
setPalette(pa);

窗口属性:

setWindowOpacity(0.8);	// 透明度

setWindowTitle("LX Demo");  // 标题

setToolTip("hang");	 // 鼠标悬停提示

resize(400, 200);	// 调整窗口大小

信号和槽:Qt最明显区别于其它开发框架的特征

信号就是命令,槽就是执行命令;

/***
static QMetaObject::Connection connect(
    const QObject *sender, //信号发送对象指针
    const char *signal,    //信号函数字符串,使用SIGNAL()
    const QObject *receiver, //槽函数对象指针
    const char *member, //槽函数字符串,使用SLOT()
    Qt::ConnectionType = Qt::AutoConnection//连接类型,一般默认即可
);
***/
connect(object1, signal, object2, slot);
// e.g 
connect(pushButton, SIGNAL(clicked()), dialog, SLOT(close()));
/***
static QMetaObject::Connection connect(
    const QObject *sender, //信号发送对象指针
    const QMetaMethod &signal,//信号函数地址
    const QObject *receiver, //槽函数对象指针
    const QMetaMethod &method,//槽函数地址
    Qt::ConnectionType type = Qt::AutoConnection//连接类型,一般默认即可
);
Qt5新增,使得在编译期间就可以进行拼写检查,参数检查,类型检查,并且支持相容参数的兼容性转换;
***/ 
// e.g
connect(pushButton, QPushButton::clicked, dialog,  QDialog::close);

信号:

1. 声明信号使用signals关键字,发送信号使用emit关键字;

2. 信号声明是公共的,不能在signals前加public,private, protected;

3. 信号没有返回值,返回值都用void;

4. 信号都不需要定义;

5. 必须直接或间接继承自QOBject类,并且开头私有声明包含Q_OBJECT;

6. 当一个信号发出时,会立即执行其槽函数,等待槽函数执行完毕后,才会执行后面的代码,如果一个信号链接了多个槽,那么会等所有的槽函数执行完毕后才执行后面的代码,槽函数的执行顺序是按照它们链接时的顺序执行的;

7. 在链接信号和槽时,可以设置链接方式为:在发出信号后,不需要等待槽函数执行完,而是直接执行后面的代码;

8. 信号参数的个数不得少于槽参数的个数;

槽:

1. 槽其实就是普通的C++函数,它唯一特点就是能和信号链接。当和它链接的信号被发出时,这个槽就会被调用;

2. Qt5中每个函数都可以被当作是槽函数,可以使用Lambda表达式来作为槽;

// 新建一个widget项目, ui中拖入horizontal slider, lineEdit, label
// 效果:lineEdit中输入0-100整数,滑动条跟着动,label文字和lineEdit保持一致
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    int max = 100;
    int min = 0;
    ui->horizontalSlider->setMaximum(max);
    ui->horizontalSlider->setMinimum(min);    // 滑动条上下限

    QIntValidator* validator = new QIntValidator(min, max, this);
    ui->lineEdit->setValidator(validator);    // 规范输入只能是整数值

    // lineEdit 发出 textChanged 信号, horizontalSlider 执行 lineEditChanged 槽函数
    connect(ui->lineEdit, &QLineEdit::textChanged, this, &Widget::lineEditChanged);
    
    // horizontalSlider 发出 sigShowVal 信号, label 执行 setText 槽函数
    connect(this, SIGNAL(sigShowVal(QString)), ui->label, SLOT(setText(QString)));
}


void Widget::lineEditChanged(const QString &text){
    int val = text.toInt();
    ui->horizontalSlider->setValue(val);
    emit sigShowVal(text);
}

UI中编辑信号和槽:

1. F4编辑:将控制控件和被控制控件连起来,选择相应的槽函数(内置);

2. F3退出编辑 ;

3. 右键选择控制控件,转到槽函数,进行进一步编辑;

4. QObject::setObjectName()方法为对象设置名称;

5. QMetaObject::connectSlotsByName()启用自动关联;

6. 用下划线"_"将"on",“对象名”,“信号名”连接后命名的函数,即:on_对象名_信号名(参数)

// .h 文件中自动生成
private slots:
    void on_pushButton_toggled(bool checked);

QSignalMapper:

这个类可以连接多个按钮,匹配发送信号的对象对应的整数、字符串,窗口指针,继承于QObject的对象参数重新发送它们。

// 计算器界面Demo,点击button显示数字
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);

    QVBoxLayout* vLayout = new QVBoxLayout(this);    // 垂直布局
    QLineEdit* edit = new QLineEdit;                 // 文本框
    edit->setAlignment(Qt::AlignRight);              // 靠右对齐
    vLayout->addWidget(edit);

    // 创建信号匹配器
    QSignalMapper* signalMapper = new QSignalMapper(this);
    QGridLayout* gridLayout = new QGridLayout;           // 网格布局
    for(int i=0; i<10; ++i){
        QString txt = QString::number(i);
        QPushButton* button_1 = new QPushButton(txt);    // 定义button 
        // button_1 发射 clicked 信号, signalMapper信号匹配器 执行 匹配槽函数 
        connect(button_1, SIGNAL(clicked()), signalMapper, SLOT(map()));
        signalMapper->setMapping(button_1, txt);         // 信号匹配
        gridLayout->addWidget(button_1, i / 3, i % 3);   // 添加布局,(widget, row, col)
    }
    // 信号匹配器 发送 mapped 信号, 文本框 执行 setText 槽函数
    connect(signalMapper, SIGNAL(mapped(QString)), edit, SLOT(setText(QString)));
    vLayout->addLayout(gridLayout);         // 将网格布局添加至垂直布局
    resize(200, 200);
}

其他:

1. 判断信号是哪个对象发来的,调用sender()函数获取对象指针,返回为QObject指针:QObject* sender() ;

2. 不需要信号槽连接时,可使用disconnect()进行解绑定,写法和connect一样,只需要将connect换成disconnect即可;

moc预编译器 moc(Meta-Object Compiler)元对象预编译器

moc读取一个c++头文件。如果它找到包含Q_OBJECT宏的一个或多个类声明,它会生成一个包含这些类的元对象代码的c++源文件,并且以moc_作为前缀。信号和槽机制、运行时类型信息和动态属性系统需要元对象代码。

猜你喜欢

转载自blog.csdn.net/francislucien2017/article/details/85229913