自学内容网 自学内容网

Qt学习笔记第41到50讲

第41讲 UI美化遗留问题解决

如上图所示目前记事本的雏形已现,但是还是有待优化,比如右下角的拖动问题。

解决方法:

①首先修改了Widget类的构造函数。

Widget::Widget(QWidget *parent) : QWidget(parent) , ui(new Ui::Widget)
{
    ui->setupUi(this);
    this->setLayout(ui->verticalLayout);
    ui->widgetBottom->setLayout(ui->horizontalLayout);
}

下面开始逐步讲解,在Widget构造函数当中,我们首先初始化了成员变量:

 ui(new Ui::Widget)

这里为类的成员变量 ui 分配内存并进行初始化。ui 通常是一个指向特定用户界面类的指针,这个类是由 Qt 的 UI 设计工具生成的。通过初始化 ui,可以在后续的代码中访问和操作由设计师创建的用户界面元素。

然后设置父窗口和布局:

QWidget(parent)

调用父类 QWidget 的构造函数并传入 parent 参数。这使得当前创建的 Widget 实例能够与指定的父窗口建立关系。如果有父窗口,当父窗口被销毁时,子窗口也会被自动销毁,有助于管理窗口资源和层次结构。

ui->setupUi(this)

这个函数通常由 Qt 的 UI 设计工具生成的代码调用。它负责设置用户界面,将各种界面元素(如按钮、文本框等)与对应的成员变量关联起来,并根据设计设置初始状态和属性。

this->setLayout(ui->verticalLayout)

这一行是我们自己写的,将当前窗口的布局设置为 ui->verticalLayout。布局管理器用于自动管理窗口内的子部件的大小和位置。通过设置布局,可以确保界面元素在窗口大小变化时能够正确地调整位置和大小,提高用户界面的适应性。

ui->widgetBottom->setLayout(ui->horizontalLayout)

这一行也是我们自己写的,这里为特定的子部件 ui->widgetBottom 设置布局为 ui->horizontalLayout。这使得该子部件内的元素能够按照水平布局进行排列和调整。

②在UI底部添加两个弹簧控件;

左侧可拉伸,右侧选择fixed锁死长度。

第42讲 信号与槽的引入

基本概念

1. 信号 (Signals) :是由对象在特定事件发生时发出的消息。例如, QPushButton 有一个clicked() 信号,当用户点击按钮时发出。
2. (Slots) :是用来响应信号的方法。一个槽可以是任何函数,当其关联的信号被发出时,该槽函数将被调用。
3. 连接信号和槽 :使用 QObject::connect() 方法将信号连接到槽。当信号发出时,关联的槽函数
会自动执行。(PS:connect属于静态函数,通过“类名::函数名”可以直接使用。)

控件案例

下面我提供一个案例帮助大家理解。

①在主窗口放置了一个按键;

②切换到信号与槽的编辑器,点击绿色的+号增添一位信号发送者;

③双击“发送者”下面的单元格,一次选择发送者为pushButton,信号为click,接受者为MainWindow,槽选择为close;(达成的效果是按下按键后,组件发送信号给主窗口,主窗口关闭)

第43讲 信号与槽的四种代码实现方式

简介

使用QObject::connect

尝试在在构造函数内部进行信号与槽的绑定。

①在UI界面处布置控件并且命名

②对项目进行整体重构,让编译器识别到新建的控件对象

③使用QObject内部的静态函数connect实现信号量与槽的关联

connect函数原型:

static QMetaObject::Connection connect(const QObject *sender, const QMetaMethod &signal,
                        const QObject *receiver, const QMetaMethod &method,
                        Qt::ConnectionType type = Qt::AutoConnection);

参数列表介绍:

sender参数

类型为const QObject*,它是信号的发送者对象的指针。这个对象通常是继承自QObject类的。例如,在一个简单的图形用户界面应用中,QPushButton按钮对象就可以作为信号发送者。当按钮被点击时,它会发送clicked信号。

signal参数

类型为const QMetaMethod&,它代表发送者对象的信号。信号是在QObject的子类中使用signals关键字声明的成员函数。信号没有函数体,它的作用是在特定事件发生时(如按钮点击、定时器超时等)发出通知。例如,QPushButton类中的clicked(bool)信号,当按钮被点击时会发出这个信号,并且可以携带一个布尔值(表示按钮是否被选中状态等相关信息)。

receiver参数

类型为const QObject*,它是信号接收者对象的指针。接收者也是QObject或其派生类的对象。比如,可能是一个自定义的窗口类对象,用于处理按钮点击后的操作。

method参数

类型为const QMetaMethod&,它代表接收者对象中的槽函数。槽函数是普通的成员函数,使用slots关键字(在旧版本的 Qt 中使用,现在也可以是普通成员函数)或者是普通的publicprivate等访问权限的成员函数来定义。当信号被发射时,对应的槽函数会被调用。例如,在接收者类中有一个onButtonClicked()函数,它可以作为槽函数来处理按钮点击信号。

type参数

类型为Qt::ConnectionType,默认值是Qt::AutoConnection。这个参数用于指定信号和槽的连接类型。主要有以下几种连接类型:

  • Qt::AutoConnection
    • 这是默认的连接类型。如果信号发射和接收者在同一个线程中,那么会使用Qt::DirectConnection方式连接;如果信号发射和接收者在不同的线程中,会使用Qt::QueuedConnection方式连接。这种自动选择的方式使得信号 - 槽机制在多线程和单线程环境下都能比较方便地工作。
  • Qt::DirectConnection
    • 当信号被发射时,槽函数会立即被调用,就好像直接调用普通函数一样。这种连接方式在信号发射者和接收者在同一线程中使用时比较合适。但是如果在多线程环境下这样连接,并且槽函数执行时间较长,可能会导致信号发射线程阻塞。
  • Qt::QueuedConnection
    • 当信号被发射时,槽函数的调用会被放到接收者对象所在线程的事件队列中。这意味着槽函数会在接收者线程的事件循环处理到这个队列项时才会被调用。这种方式在多线程环境下可以确保接收者线程的事件循环正常工作,不会被信号发射线程随意干扰。
  • Qt::BlockingQueuedConnection
    • 这种连接方式和Qt::QueuedConnection类似,但是信号发射线程会阻塞,直到槽函数执行完毕。不过要注意,不能在同一线程中使用这种连接方式,否则会导致死锁。
  • Qt::UniqueConnection
    • 这种连接方式可以确保相同的信号和槽之间只有一个连接。如果已经存在这样的连接,再次尝试建立连接时会被忽略。

实际使用:

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    QObject::connect(ui->btnCon,SIGNAL(clicked()),this,SLOT(on_btnui_clickedMyself()));
}

其中ui->btn是我们在UI界面新建的控件,SIGNAL宏内包含了clicked代表按下控件时发出消息,on_btnui_clickedMyself()函数需要我们进行外部实现。

出于代码规范考虑优先在Widget.h2文件内部定义;

右键选择Refactor进行重构,位置在Widget.c文件中

void Widget::on_btnui_clickedMyself()
{
    std::cout<<"ObjCon clicked"<<std::endl;
}

测试结果:

自动连接

①拖动控件并且完成命名

②右击选中控件->转到槽

③转到widget.cpp里面进行编辑,撰写槽的函数体,

简单编写一个标准输出语句进行功能测试:


原文地址:https://blog.csdn.net/qq_59757948/article/details/143522447

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!