QT的学习第三部分

QT学习笔记(三)单行文本输入框与自动补全 main.cpp#include <QApplication>#include "mywidget.h"#include <QPushButton>int main(int argc, char **argv){ QApplication app(argc, argv); MyWidget w; w.show(); return app.exec()... 阅读详情

一、QT的串口编程

1、串口通信的概念

串口通信:一种按位(bit)逐字节顺序传输数据的串行通信方式,通过 TX(发送)和 RX(接收) 两根数据线实现设备间的双向(全双工)数据传输,常用于工业控制、嵌入式设备等近距离低速通信场景。

2、串口设备的接线图

3、串口编程

(1)前置知识点

Qt串口模块提供了两个类:
    1、QSerialPort提供访问串口的函数
    2、QSerialPortInfo提供有关现有串行端口的信息。
如果要在你的项目中使用QSerialPort和QSerialPortInfo要包含下面两个头文件:
    #include <QSerialPort>
    #include <QSerialPortInfo>
编译的时候需要连接串口模块,可以在qmake.pro(项目工程文件中添加模块)
    QT += serialport

(2)串口编程中的QSerialPort

串口编程常用接口如下所示:
构造函数:
    QSerialPort(const QSerialPortInfo &serialPortInfo, QObject *parent = nullptr)
    QSerialPort(const QString &name, QObject *parent = nullptr)
    QSerialPort(QObject *parent = nullptr)
串口操作函数:
    1、open(QIODevice::OpenMode mode): 打开串口并指定打开模式。
    2、close(): 关闭串口。
    3、setBaudRate(qint32 baudRate, QSerialPort::Directions directions =             QSerialPort::AllDirections): 设置波特率。
    4、setDataBits(QSerialPort::DataBits dataBits): 设置数据位。
    5、setParity(QSerialPort::Parity parity): 设置校验位。
    6、setStopBits(QSerialPort::StopBits stopBits): 设置停止位。
    7、setFlowControl(QSerialPort::FlowControl flowControl): 设置流控制。
    8、clearError(): 清除错误状态。
    9、clear(): 清空输入输出缓冲区。
    10、read(char *data, qint64 maxSize): 从串口读取数据。
    11、write(const char *data, qint64 maxSize): 向串口写入数据。
    12、waitForReadyRead(int msecs): 等待串口有数据可读。

(3)具体的实例代码

①开发板下位机

widget.h:

#ifndef WIDGET_H
#define WIDGET_H
// ==================== 包含必要的头文件 ====================
#include <QWidget>          // Qt窗口基类
#include <QString>          // Qt字符串类
#include <QObject>          // Qt对象基类(信号槽机制)
#include <QDebug>           // Qt调试输出(qDebug())
#include <QSerialPort>      // 串口通信类
#include <QSerialPortInfo>  // 串口信息类(获取可用串口列表)
#include <QLabel>           // 标签控件
#include <QComboBox>        // 下拉列表控件
#include <QPushButton>      // 按钮控件
#include <QTextEdit>        // 多行文本编辑框控件
#include <QFont>            // 字体类
// ==================== Qt命名空间宏 ====================
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }  // 前向声明UI类(由Qt Designer生成)
QT_END_NAMESPACE
// ==================== Widget类定义 ====================
class Widget : public QWidget
{
    Q_OBJECT  // Qt元对象宏(支持信号槽)
public:
    Widget(QWidget *parent = nullptr);  // 构造函数
    ~Widget();                          // 析构函数
    void Serila_Init();                // 串口初始化函数
public slots:                          // 公共槽函数(响应信号)
    void open_serial();                // 打开串口的槽函数
    void close_serial();               // 关闭串口的槽函数
    void recv_serial_msg();            // 接收串口消息的槽函数
private:
    // ===== UI对象 =====
    Ui::Widget  * ui;                  // UI界面指针(由uic生成)
    // ===== 串口对象 =====
    QSerialPort * serial;              // 串口通信对象
    // ===== 字体对象 =====
    QFont       * font;                // 字体样式对象
    // ===== 串口信息列表 =====
    QList<QSerialPortInfo> * serial_inf;  // 存储可用串口信息的列表
    // ===== 端口信息文本框 =====
    QTextEdit   * com_inf;             // 显示串口参数信息的文本框
    // ===== 端口标签 =====
    QLabel      * com_port;            // "端口:" 标签
    // ===== 端口下拉列表 =====
    QComboBox   * com_port_cbox;       // 显示可用串口的下拉列表
    // ===== 选中的端口名 =====
    QString     * com_select_ack;      // 存储用户选中的端口名称
    // ===== 打开串口按钮 =====
    QPushButton * open_serial_btn;     // "打开串口"按钮
    // ===== 接收消息文本框 =====
    QTextEdit   * recv_msg_Text;       // 显示接收到的串口数据的文本框
};
#endif // WIDGET_H

widget.cpp

#include "widget.h"      // 包含头文件
#include "ui_widget.h"   // 包含自动生成的UI头文件
// ==================== 构造函数 ====================
Widget::Widget(QWidget *parent)
    : QWidget(parent)    // 调用父类构造函数
    , ui(new Ui::Widget) // 创建UI对象
{
    ui->setupUi(this);   // 设置UI界面(虽然本代码未使用UI文件)
    this->Serila_Init(); // 调用串口初始化函数
}
// ==================== 析构函数 ====================
Widget::~Widget()
{
    // 添加串口关闭
    if (this->serial && this->serial->isOpen())
        this->serial->close();
    delete this->serial;
    delete this->serial_inf;
    delete this->font;
    delete this->com_select_ack;
    delete ui;  // 释放UI对象内存
}
// ==================== 串口初始化函数 ====================
void Widget::Serila_Init()
{
    // ----- 设置窗口大小 -----
    this->setFixedWidth(800);   // 固定窗口宽度800像素
    this->setFixedHeight(480);  // 固定窗口高度480像素
    // ----- 创建串口信息列表对象 -----
    this->serial_inf = new QList<QSerialPortInfo>;
    // ----- 获取当前系统所有可用串口 -----
    // 使用解引用操作符(*)获取列表对象,然后赋值
    (*this->serial_inf) = QSerialPortInfo::availablePorts();
    // ----- 创建串口对象 -----
    this->serial = new QSerialPort;
    // ----- 设置串口参数(在打开前配置) -----
    this->serial->setBaudRate(QSerialPort::Baud115200);  // 波特率:115200
    this->serial->setDataBits(QSerialPort::Data8);       // 数据位:8位
    this->serial->setParity(QSerialPort::NoParity);      // 奇偶校验:无
    this->serial->setStopBits(QSerialPort::OneStop);     // 停止位:1位
    // ----- 创建字体对象 -----
    this->font = new QFont("Arial", 15);  // 字体:Arial,字号:15
    // ----- 创建"端口:"标签 -----
    this->com_port = new QLabel("端口:", this);  // 显示文本"端口:"
    this->com_port->setFont(*this->font);        // 设置字体
    // 设置标签大小和位置
    this->com_port->setFixedWidth(60);   // 宽度60像素
    this->com_port->setFixedHeight(30);  // 高度30像素
    this->com_port->move(10, 10);        // 移动到坐标(10, 10)
    // ----- 创建端口下拉列表 -----
    this->com_port_cbox = new QComboBox(this);
    // 修改字体大小为10
    this->font->setPointSize(10);
    this->com_port_cbox->setFont(*this->font);
    // 遍历串口列表,将端口名称添加到下拉列表
    for(int com_num = 0; com_num < this->serial_inf->size(); com_num++)
    {
        // 获取第com_num个串口信息,取出端口名称添加到下拉列表
        this->com_port_cbox->addItem(this->serial_inf->at(com_num).portName());
    }
    // 设置下拉列表大小和位置
    this->com_port_cbox->setFixedWidth(110);   // 宽度110像素
    this->com_port_cbox->setFixedHeight(30);   // 高度30像素
    this->com_port_cbox->move(80, 10);         // 移动到坐标(80, 10)
    // ----- 创建存储选中端口的字符串对象 -----
    this->com_select_ack = new QString;
    // ----- 创建"打开串口"按钮 -----
    this->font->setPointSize(15);  // 字体大小改为15
    this->open_serial_btn = new QPushButton("打开串口", this);
    this->open_serial_btn->setFont(*this->font);
    this->open_serial_btn->move(30, 70);  // 移动到坐标(30, 70)
    // ----- 创建串口信息文本框(显示参数) -----
    this->com_inf = new QTextEdit(this);
    // 添加串口参数信息
    this->com_inf->append("波特率:115200");
    this->com_inf->append("数据位:8");
    this->com_inf->append("奇偶检验:无");
    this->com_inf->append("停止位:1");
    // 设置字体大小12
    this->font->setPointSize(12);
    this->com_inf->setFont(*this->font);
    // 设置文本框大小和位置
    this->com_inf->setFixedWidth(180);   // 宽度180像素
    this->com_inf->setFixedHeight(180);  // 高度180像素
    this->com_inf->move(10, 150);        // 移动到坐标(10, 150)
    // ----- 创建接收消息显示文本框 -----
    this->recv_msg_Text = new QTextEdit(this);
    this->recv_msg_Text->setFont(*this->font);  // 设置窗口字体
    // 设置接收消息文本框大小和位置
    this->recv_msg_Text->setFixedWidth(500);   // 宽度500像素
    this->recv_msg_Text->setFixedHeight(320);  // 高度320像素
    this->recv_msg_Text->move(250, 10);        // 移动到坐标(250, 10)
    // ===== 连接信号与槽 =====
    // 1. 点击"打开串口"按钮 → 执行open_serial()槽函数
    QObject::connect(this->open_serial_btn, &QPushButton::clicked,
                     this, &Widget::open_serial);
    // 2. 串口有数据可读 → 执行recv_serial_msg()槽函数
    QObject::connect(this->serial, &QSerialPort::readyRead,
                     this, &Widget::recv_serial_msg);
    return;  // 函数结束(可省略)
}
// ==================== 打开串口槽函数 ====================
void Widget::open_serial()
{
    // 判空:下拉列表是否为空
    if (this->com_port_cbox->count() == 0) 
    {
        qDebug() << "没有可用的串口";
        return;
    }
    // 判空:是否选中有效项
    if (this->com_port_cbox->currentIndex() == -1) 
    {
        qDebug() << "未选择串口";
        return;
    }
    // ----- 获取用户选中的端口名 -----
    // currentIndex():获取当前选中项的索引
    // itemText():根据索引获取显示的文本
    *this->com_select_ack = this->com_port_cbox->itemText(
        this->com_port_cbox->currentIndex()
    );
    // ----- 设置串口要打开的端口号 -----
    this->serial->setPortName(*this->com_select_ack);
    // ----- 尝试打开串口(读写模式) -----
    if(this->serial->open(QIODevice::ReadWrite) == false)
    {
        // 打开失败,输出错误信息
        qDebug() << "error";
        return;  // 退出函数
    }
    else
    {
        // 打开成功,输出成功信息
        qDebug() << *this->com_select_ack << "open success";
    }
}
// ==================== 关闭串口槽函数 ====================
void Widget::close_serial()
{
    if (this->serial && this->serial->isOpen())
    {
        this->serial->close();
        qDebug() << "串口已关闭";
    }
}
// ==================== 接收串口消息槽函数 ====================
void Widget::recv_serial_msg()
{
    // 调试输出:表示收到了消息
    qDebug() << "have a msg!!";
    // ----- 读取串口所有数据 -----
    QByteArray data = this->serial->readAll();
    // ----- 将数据显示到文本框 -----
    this->recv_msg_Text->append(data);  // append()自动将QByteArray转为QString
}
②Windows下位机

widget.h:

#ifndef WIDGET_H                      // 防止头文件重复包含
#define WIDGET_H
// ==================== 包含必要的头文件 ====================
#include <QWidget>          // Qt窗口基类
#include <QString>          // Qt字符串类
#include <QObject>          // Qt对象基类(支持信号槽机制)
#include <QDebug>           // Qt调试输出(qDebug())
#include <QSerialPort>      // 串口通信类
#include <QSerialPortInfo>  // 串口信息类(获取可用串口列表)
#include <QLabel>           // 标签控件
#include <QComboBox>        // 下拉列表控件
#include <QPushButton>      // 按钮控件
#include <QTextEdit>        // 多行文本编辑框控件
#include <QFont>            // 字体类
// ==================== Qt命名空间宏 ====================
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }  // 前向声明UI类(由Qt Designer生成)
QT_END_NAMESPACE
// ==================== Widget类定义 ====================
class Widget : public QWidget
{
    Q_OBJECT  // Qt元对象宏(支持信号槽功能)
public:
    // ----- 构造函数和析构函数 -----
    Widget(QWidget *parent = nullptr);  // 构造函数
    ~Widget();                          // 析构函数
    // ----- 公共成员函数 -----
    void Serila_Init();   // 串口初始化函数(创建UI控件和串口对象)
    void Serila_Free();   // 串口资源释放函数(释放动态分配的内存)
public slots:  // 公共槽函数(响应信号)
    void open_serial();      // 打开串口槽函数(点击"打开串口"按钮触发)
    void send_serial_msg();  // 发送串口消息槽函数(点击"发送"按钮触发)
    void recv_serial_msg();  // 接收串口消息槽函数
private:
    // ===== UI对象 =====
    Ui::Widget *ui;          // UI界面指针(由uic工具生成)
    // ===== 串口对象 =====
    QSerialPort * serial;    // 串口通信对象
    // ===== 字体对象 =====
    QFont * font;            // 字体样式对象
    // ===== 串口信息列表 =====
    QList<QSerialPortInfo> * serial_inf;  // 存储可用串口信息的列表
    // ===== 串口参数信息文本框 =====
    QTextEdit * com_inf;     // 显示串口参数信息的文本框
    // ===== 端口标签 =====
    QLabel * com_port;       // "端口:" 标签
    // ===== 端口下拉列表 =====
    QComboBox * com_port_cbox;  // 显示可用串口的下拉列表
    // ===== 选中的端口名 =====
    QString * com_select_ack;   // 存储用户选中的端口名称
    // ===== 打开串口按钮 =====
    QPushButton * open_serial_btn;  // "打开串口"按钮
    // ===== 发送消息按钮 =====
    QPushButton * send_msg_btn;  // "发送"按钮
    // ===== 发送消息文本框 =====
    QTextEdit * send_msg_Text;   // 用户输入要发送数据的文本框
};
#endif // WIDGET_H

widget.cpp:

#include "widget.h"      // 包含头文件
#include "ui_widget.h"   // 包含自动生成的UI头文件
// ==================== 构造函数 ====================
Widget::Widget(QWidget *parent)
    : QWidget(parent)    // 调用父类QWidget的构造函数
    , ui(new Ui::Widget) // 创建UI对象
{
    ui->setupUi(this);   // 设置UI界面(虽然本代码未使用UI文件)
    this->Serila_Init(); // 调用串口初始化函数
}
// ==================== 析构函数 ====================
Widget::~Widget()
{    
    this->Serila_Free(); // 释放动态分配的资源
    delete ui;           // 释放UI对象内存
}
// ==================== 串口初始化函数 ====================
void Widget::Serila_Init()
{
    // ----- 设置窗口属性 -----
    this->setFixedWidth(800);            // 固定窗口宽度800像素
    this->setFixedHeight(480);           // 固定窗口高度480像素
    this->setWindowTitle("windows窗口上位机");  // 设置窗口标题
    // ----- 创建串口信息列表对象 -----
    this->serial_inf = new QList<QSerialPortInfo>;
    // ----- 获取当前系统所有可用串口 -----
    // QSerialPortInfo::availablePorts()返回QList<QSerialPortInfo>
    // 使用解引用操作符(*)获取列表对象并赋值
    (*this->serial_inf) = QSerialPortInfo::availablePorts();
    // ----- 创建串口对象 -----
    this->serial = new QSerialPort;
    // ----- 设置串口参数(在打开前配置) -----
    this->serial->setBaudRate(QSerialPort::Baud115200);   // 波特率:115200
    this->serial->setDataBits(QSerialPort::Data8);        // 数据位:8位
    this->serial->setParity(QSerialPort::NoParity);       // 奇偶校验:无
    this->serial->setStopBits(QSerialPort::OneStop);      // 停止位:1位
    // ----- 创建字体对象 -----
    this->font = new QFont("Arial", 15);  // 字体:Arial,字号:15
    // ----- 创建"端口:"标签 -----
    this->com_port = new QLabel("端口:", this);  // 显示文本"端口:"
    this->com_port->setFont(*this->font);        // 设置字体
    // 设置标签大小和位置
    this->com_port->setFixedWidth(60);   // 宽度60像素
    this->com_port->setFixedHeight(30);  // 高度30像素
    this->com_port->move(10, 10);        // 移动到坐标(10, 10)
    // ----- 创建端口下拉列表 -----
    this->com_port_cbox = new QComboBox(this);
    // 修改字体大小为10
    this->font->setPointSize(10);
    this->com_port_cbox->setFont(*this->font);
    // 遍历串口列表,将端口名称添加到下拉列表
    for(int com_num = 0; com_num < this->serial_inf->size(); com_num++)
    {
        // 获取第com_num个串口信息的端口名称,添加到下拉列表
        this->com_port_cbox->addItem(this->serial_inf->at(com_num).portName());
    }
    // 设置下拉列表大小和位置
    this->com_port_cbox->setFixedWidth(110);   // 宽度110像素
    this->com_port_cbox->setFixedHeight(30);   // 高度30像素
    this->com_port_cbox->move(80, 10);         // 移动到坐标(80, 10)
    // ----- 创建存储选中端口的字符串对象 -----
    this->com_select_ack = new QString;
    // ----- 创建"打开串口"按钮 -----
    this->font->setPointSize(15);  // 字体大小改为15
    this->open_serial_btn = new QPushButton("打开串口", this);
    this->open_serial_btn->setFont(*this->font);
    this->open_serial_btn->move(30, 70);  // 移动到坐标(30, 70)
    // ----- 创建串口参数信息文本框 -----
    this->com_inf = new QTextEdit(this);
    // 添加串口参数信息
    this->com_inf->append("波特率:115200");
    this->com_inf->append("数据位:8");
    this->com_inf->append("奇偶检验:无");
    this->com_inf->append("停止位:1");
    // 设置字体大小12
    this->font->setPointSize(12);
    this->com_inf->setFont(*this->font);
    // 设置文本框大小和位置
    this->com_inf->setFixedWidth(180);   // 宽度180像素
    this->com_inf->setFixedHeight(180);  // 高度180像素
    this->com_inf->move(10, 150);        // 移动到坐标(10, 150)
    // ----- 创建发送消息文本框(用户输入要发送的数据) -----
    this->send_msg_Text = new QTextEdit(this);
    this->send_msg_Text->setFont(*this->font);
    // 设置发送文本框大小和位置
    this->send_msg_Text->setFixedWidth(500);   // 宽度500像素
    this->send_msg_Text->setFixedHeight(320);  // 高度320像素
    this->send_msg_Text->move(250, 10);        // 移动到坐标(250, 10)
    // ----- 创建"发送"按钮 -----
    this->send_msg_btn = new QPushButton("发送", this);
    this->send_msg_btn->setFont(*this->font);
    this->send_msg_btn->move(650, 350);  // 移动到坐标(650, 350)
    // ===== 连接信号与槽 =====
    // 1. 点击"打开串口"按钮 → 执行open_serial()槽函数
    QObject::connect(this->open_serial_btn, &QPushButton::clicked,
                     this, &Widget::open_serial);
    // 2. 点击"发送"按钮 → 执行send_serial_msg()槽函数
    QObject::connect(this->send_msg_btn, &QPushButton::clicked,
                     this, &Widget::send_serial_msg);
    // 串口接收数据
    QObject::connect(this->serial, &QSerialPort::readyRead, 
                     this, &Widget::recv_serial_msg);
    return;  // 函数结束(可省略)
}
// ==================== 打开串口槽函数 ====================
void Widget::open_serial()
{
    // 判断下拉列表是否有选项
    if(this->com_port_cbox->count() == 0)
    {
        qDebug() << "没有可用的串口";
        return;
    }
    
    // 判断是否选中了有效项
    if(this->com_port_cbox->currentIndex() == -1)
    {
        qDebug() << "未选择串口";
        return;
    }
    // ----- 获取用户选中的端口名 -----
    // currentIndex():获取当前选中项的索引
    // itemText():根据索引获取显示的文本
    *this->com_select_ack = this->com_port_cbox->itemText(
        this->com_port_cbox->currentIndex()
    );
    // ----- 设置串口要打开的端口号 -----
    this->serial->setPortName(*this->com_select_ack);
    // 调试输出选中的端口名
    qDebug() << *this->com_select_ack;
    // ----- 尝试打开串口(读写模式) -----
    // QIODevice::ReadWrite:以读写方式打开
    if(this->serial->open(QIODevice::ReadWrite) == false)
    {
        // 打开失败,输出错误信息
        qDebug() << "error";
        return;  // 退出函数
    }
    else
    {
        // 打开成功,输出成功信息
        qDebug() << *this->com_select_ack << "open success";
    }
}
// ==================== 发送串口消息槽函数 ====================
void Widget::send_serial_msg()
{
    // 检查串口是否打开
    if(!this->serial || !this->serial->isOpen())
    {
        qDebug() << "串口未打开,无法发送";
        return;
    }
    // ----- 获取用户输入的消息文本 -----
    // toPlainText():获取QTextEdit中的纯文本内容
    QString msg = this->send_msg_Text->toPlainText();
    if(msg.isEmpty())
    {
        qDebug() << "消息为空,不发送";
        return;
    }
    // ----- 发送数据到串口 -----
    // toUtf8():将QString转换为QByteArray(UTF-8编码)
    // write():向串口写入数据
    // 下位机使用QByteArray接收,所以发送时也需要以QByteArray格式发送
    this->serial->write(msg.toUtf8(), msg.toUtf8().size());
}
// ==================== 接收串口消息槽函数 ====================
// 实现接收槽函数
void Widget::recv_serial_msg()
{
    QByteArray data = this->serial->readAll();
    // 显示到接收文本框(需要添加接收文本框成员变量)
    this->recv_msg_Text->append(data);
}
// ==================== 串口资源释放函数 ====================
void Widget::Serila_Free()
{
    if(this->serial && this->serial->isOpen())
    {
        this->serial->close();  // 先关闭串口
    }
    // 释放所有动态分配的内存
    delete this->serial;          // 释放串口对象
    delete this->font;            // 释放字体对象
    delete this->serial_inf;      // 释放串口信息列表
    delete this->com_inf;         // 释放串口信息文本框
    delete this->com_port;        // 释放端口标签
    delete this->com_port_cbox;   // 释放端口下拉列表
    delete this->com_select_ack;  // 释放选中的端口名字符串
    delete this->open_serial_btn; // 释放打开串口按钮
    delete this->send_msg_btn;    // 释放发送按钮
}

二、QT的数据库编程

1、QT的数据库

Qt 框架提供的一套跨平台数据库访问模块,通过统一的 QSqlDatabase 接口支持多种主流数据库(如 SQLite、MySQL、PostgreSQL、ODBC 等),并提供 QSqlQuery 执行 SQL 语句和 QSqlTableModel 等数据模型直接与 Qt 的视图组件(如 QTableView)绑定,实现数据的高效读写和界面展示。

2、QT数据库开发中常见的组合

3、前置知识点

(1)编译配置

在.pro文件中添加数据库模块依赖: QT += sql

(2)常用的3种类类型

①SQL数据库类(QSqlDatabase):负责连接数据库文件,管理数据的持久化存储(可存磁盘或内存),一个数据库文件可包含多个数据表。

②数据模型类(QSqlTableModel / QSqlQueryModel):负责从数据库类中获取数据,处理后提交给视图类显示,充当数据库与界面之间的数据中转站。

③数据库视图类(QTableView):一个Qt控件,负责将数据模型提供的数据以表格形式直观地展示给用户。

4、数据库的实现

(1)数据库的创建

调用数据库类的静态函数创建数据库对象:

结果:

(2)创建QSqlQuery对象

数据库表格QSqlQuery类:一个用于执行和处理数据库查询的类,提供了一系列函数来执行SQL语句、处理查询结果以及访问查询元数据等操作。
    QSqlQuery头文件:#include <QSqlQuery>
以下是类成员方法:
    prepare(const QString& query):准备一个SQL查询,将查询语句作为参数传入。
    bindValue(const QString& placeholder, const QVariant& val):绑定值到SQL查询中的占位符,可以使用冒号(:)或问号(?)作为占位符。
    exec():执行SQL查询,如果是SELECT语句,则返回true表示查询成功;如果是其他类型的SQL语句(如INSERT、UPDATE、DELETE等),则返回true表示执行成功。
    next():将查询结果的游标移到下一条记录,如果存在下一条记录,则返回true;否则返回false。
    value(int index)或value(const QString& name):获取当前记录中指定列的值,可以通过列索引或列名进行访问。
    record():返回当前记录的QSqlRecord对象,可以获取记录的详细信息,如字段数、字段名等。
    lastInsertId():返回最后插入的记录的ID值,通常在插入数据后调用。
    size()或numRowsAffected():返回受影响的行数,通常用于判断INSERT、UPDATE、DELETE等操作影响的行数。
    isValid():检查查询结果是否有效,即是否执行了exec()方法并且有可用的结果。

结果:

(3)数据库添加数据

(4)数据库删除数据

结果:

(5)数据库查询数据

结果:

(6)数据库修改数据

结果:

5、数据模型和数据库视图的实现

(1)数据模型的创建

QSqlTableModel:
    Qt提供的关系型数据库表格数据模型类,继承自 QAbstractTableModel,
    主要用于在 Qt 的视图组件(如 QTableView)中直接显示、编辑和提交数据库表数据,
    支持双向同步(视图修改自动同步到数据库,数据库更新自动刷新视图)。
成员函数具体如下:
    setTable(const QString& tableName) : 设置要操作的数据库表格名称。
    select(): 执行查询操作,从数据库中检索数据,并将其存储在数据模型中。
    setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole): 设置指定索引位置的单元格数据。
    data(const QModelIndex& index, int role = Qt::DisplayRole): 获取指定索引位置的单元格数据。
    insertRecord(int row, const QSqlRecord& record): 在指定位置插入一条记录。
    removeRecord(int row): 删除指定位置的记录。
    submitAll(): 将对模型的所有修改提交到数据库中。
    revertAll(): 撤销对模型的所有修改,恢复到最近的提交状态。
    rowCount() : 获取模型中记录的行数。
    columnCount(): 获取模型中列数。
    numRowsAffected():获取受影响的行的数量

(2)数据库视图的创建

QTableView:Qt框架中的一个类,用于显示二维表格数据的视图组件。
常用函数:
    设置模型: 使用setModel()方法将数据模型与QTableView关联起来。
    设置数据自动换行:void setWordWrap(bool on);
    获取行头对象:QHeaderView *verticalHeader();
    QAbstractItemModel *model() const;

6、知识点扩充

(1)数据太多如何换行

QTableView中启用文本自动换行需要两个条件:

①设置setWordWrap(true),默认已开启。

②通过verticalHeader()->setDefaultSectionSize()设置行高,否则行高固定无法显示换行后的多行文本。

// 行高 150px(垂直方向)
this->view->verticalHeader()->setDefaultSectionSize(150);
// 列宽 150px(水平方向)
this->view->horizontalHeader()->setDefaultSectionSize(150);

(2)QTableView中的列表宽度如何自适应视图的宽度

在QTableView中,列宽设置必须在setModel() 之后,且每次切换表格(模型数据变化)时,由于列数可能改变,需要重新调用列宽设置方法:

如setColumnWidth() 或 resizeColumnsToContents()。

//获取视图的总宽度
int total_width = sql_view->width();
// 计算每列应占的宽度(平均分配)
int num_columns = table_model->columnCount();
int column_width = total_width / num_columns;
// 设置每列的宽度
for(int n=0; n<num_columns; n++)
   this->sql_view->setColumnWidth(n, column_width);

(3)点击单元格删除该行

在数据库初始化时,将视图的点击信号(如clicked)连接到自定义槽函数,实现点击行后获取当前行数据并进行删除操作。

    QObject::connect(&view, &QTableView::clicked, [&](const QModelIndex &index) {
        int row = index.row(); // 获取被点击的行号0        、
    if(!sql_model.removeRow(row)) 
    {
        QMessageBox::warning(&view, "Error", "Failed to remove row!");
    }
    });

(4)暗黑风格的数据库

QWidget {
    background-color: #2d2d2d;
    color: #f0f0f0;

}
/* 按钮 */
QPushButton {
    background-color: #505050;
    border: 1px solid #707070;
    border-radius: 4px;
    padding: 5px;
}
QPushButton:hover {
    background-color: #606060;

}
QPushButton:pressed {
    background-color: #404040;

}
/* 表格视图 */
QTableView {
    background-color: #3a3a3a;
    alternate-background-color: #4a4a4a;
    gridline-color: #5a5a5a;
}
QHeaderView::section {
    background-color: #505050;
    color: white;
    padding: 4px;
    border: 1px solid #606060;
}

三、QT QSS(样式表)

1、基本概念

QT样式表:用于定制控件外观的样式机制,语法和用法类似于 CSS(层叠样式表),通过设置控件的 setStyleSheet() 方法或全局样式文件,可以灵活地改变界面颜色、字体、边框、背景、间距等视觉风格,而无需修改控件本身的代码。

选择器的分类:类型选择器、后代选择器、类选择器、ID选择器、子控件选择器、状态选择器
常见的属性:
    颜色相关:
        color: 文本颜色
        background-color: 背景颜色
        border-color: 边框颜色
    字体相关:
        font-family: 字体族
        font-size: 字体大小
        font-weight: 字体粗细
    边框相关:
        border-style: 边框样式(solid:实线边框, dashed:虚线边框, dotted:点线边框等)
        border-width: 边框宽度
        border-radius: 边框圆角半径
    布局相关:
        margin: 外边距
        padding: 内边距
    背景相关:
        background-image: 背景图片
        background-repeat: 背景重复方式
        background-position: 背景位置
    状态相关:
        hover: 鼠标悬停状态
        pressed: 鼠标按下状态
        checked: 选中状态(对于复选框和单选按钮)
    形状相关:
        border-radius: 边框圆角半径
        border-image: 边框图片 
    动画相关:
        animation: 动画效果
常见的值:
    颜色相关:
        color: 可以是预定义的颜色名称(如red, green, blue等)或十六进制RGB值(如#FF0000,#00FF00等)。
        background-color: 同color属性。
    字体相关:
        font-family: 可以是字体族名称(如Arial, Helvetica等)或字体文件路径。
        font-size: 可以是像素大小,也可以是相对大小(如smaller, larger等)。
        font-weight: 可以是预定义粗细(如bold, normal等)或数字值(如100,200等)。
    边框相关:
        border-style: 可以是预定义样式(如solid, dashed, dotted等)。
        border-width: 可以是像素大小,也可以是相对大小。
        border-radius: 可以是像素大小,也可以是相对大小。
    布局相关:
        margin: 可以是像素大小,也可以是相对大小。
        padding: 可以是像素大小,也可以是相对大小。
    背景相关:
        background-image: 可以是图片文件路径或线性渐变(如qlineargradient(x1, y1, x2, y2))。
        background-repeat: 可以是预定义方式(如repeat, repeat-x, repeat-y, no-repeat等)。
        background-position: 可以是像素大小,也可以是相对大小。
    状态相关:
        hover, :pressed, :checked: 可以是其他样式表属性,用于指定不同状态下的样式。
    形状相关:
        border-radius: 可以是像素大小,也可以是相对大小。
        border-image: 可以是图片文件路径或线性渐变。
    动画相关:animation: 可以是动画名称,也可以是动画效果参数。

2、类型选择器和类选择器

类型选择器(Type Selector):直接使用类名(如 QPushButton)作为选择器,用于匹配该类及其所有子类的控件实例,是最常用的基础选择器之一。

类选择器(Class Selector):以 点号(.)开头(如 .QPushButton),用于匹配特定类的所有控件实例,但与类型选择器不同的是,它只匹配该类本身,不匹配其子类,可以更精确地控制样式作用范围。

设置按钮的字体颜色和背景颜色:

3

设置标签的字体颜色和背景颜色

类选择器和类型选择器的区别:

类型选择器会匹配QAbstractButton及其所有子类,btn1和btn2是QAbstractButton的子类QPushbutton,所以btn1和btn2都应用了样式。

类选择器只匹配QAbstractButton本身,btn1和btn2不属于QAbstractButton,是它的子类QPushbutton,所以btn1和btn2都没有应用样式。

3、后代选择器

后代选择器:QSS 中用空格分隔的选择器组合(如 QGroupBox QPushButton),用于匹配父控件内部所有层级的指定子控件(即所有后代,不限层级)。

4、ID选择器

ID选择器:QSS 中以 # 号开头的选择器(如 #btnSave),用于精确匹配设置了 setObjectName() 的特定控件,是优先级最高的选择器之一。

5、子控件选择器

子控件选择器:QSS 中以 :: 双冒号开头的选择器(如 QComboBox::drop-down、QSpinBox::up-arrow),用于精确匹配复杂控件内部的子组件(如按钮、箭头、滑块等),实现对控件局部区域的精细化样式定制。

6、状态选择器

状态选择器:QSS 中以 : 冒号开头的选择器(如 :hover、:pressed、:disabled),用于匹配控件在不同交互状态(悬停、按下、禁用、选中等)下的样式,实现动态的视觉反馈。

未按下的效果:

按下后的效果:

渐变颜色的示例

未按下的效果:

按下后的效果

四、QT事件

1、基本概念

QT事件:用于处理用户交互(如鼠标点击、键盘输入)和系统通知(如定时器、窗口重绘)的核心机制,通过 QEvent 类及其子类封装各种事件,并由 event() 或特定事件处理函数(如 mousePressEvent())进行响应。该系统基于事件循环不断从事件队列中取出事件,并分发给对应控件处理,是 Qt 应用程序运行的核心驱动力。

2、常见的事件类型

常见事件类型,以下是一些常见的事件类型,它们继承自 QEvent 类:
    鼠标事件 (QMouseEvent):例如,鼠标点击、按下、释放、移动等。
    键盘事件 (QKeyEvent):例如,按键按下、释放等。
    窗口事件 (QWindowEvent):窗口的改变(如大小调整、最小化、关闭等)。
    绘制事件 (QPaintEvent):触发控件或窗口的重绘。
    定时器事件 (QTimerEvent):定时器触发时发生的事件。
    拖放事件 (QDragEnterEvent, QDropEvent):拖放操作相关的事件。
    聚焦事件 (QFocusEvent):控件获得或失去焦点时发生的事件。

3、事件处理机制

事件处理机制分三步走:事件生成➔事件传递➔事件处理

① 事件生成(Event Generation)

  • 触发条件:用户交互(点击、按键、拖拽)或系统通知(定时器、窗口重绘)

  • 结果:Qt 自动创建对应的 QEvent 子类对象(如 QMouseEvent、QKeyEvent)

② 事件传递(Event Delivery)

  • 路径:从事件源(产生事件的控件,如被点击的按钮)→ 放入事件队列 → 等待处理

  • 关键点:事件源是事件发生的起点,事件队列保证按顺序(FIFO)传递

③ 事件处理(Event Handling)

  • 方式:事件循环从队列取出事件,分发给目标控件

  • 实现:通过重写 event()(通用入口)或专用函数(如 mousePressEvent()、keyPressEvent())进行响应

4、鼠标事件应用:事件过滤器

事件过滤器机制:允许一个对象拦截另一个对象的事件,通过重载 eventFilter 函数来实现。

常见的用法:拦截和修改事件,例如监视控件的鼠标点击事件。

class MyEventFilter : public QObject 
{
    Q_OBJECT
public:
    // watched:被监视的对象(事件源)。
    // event:需要过滤的事件对象。
    bool eventFilter(QObject *watched, QEvent *event) override 
    {
        if (event->type() == QEvent::MouseButtonPress) 
        {
            qDebug() << "Mouse clicked!";
            return true; // 阻止事件进一步传播
        }
        //调用基类的事件过滤函数,继续事件标准传递
        return QObject::eventFilter(watched, event);
    }
};
MyEventFilter me; 创建过滤器对象。
w.installEventFilter(&me);  安装过滤器到目标对象。

五、自定义控件

1、自定义控件的概念

自定义控件:通过继承现有的 Qt 控件类或 QWidget 类,并重载相关的事件处理函数和绘制函数来实现你自己的控件。自定义控件使得你可以根据应用需求设计具有特定行为和外观的控件,它的本质是通过继承和重写来扩展 Qt 默认控件的功能。

通常自定义控件需要处理几个核心方面:
    绘制控件:通过重写控件的 paintEvent() 来绘制控件的外观。
    响应用户交互:通过重写事件处理函数(如 mousePressEvent()、keyPressEvent() 等)来处理用户输入。
    控件尺寸和布局:通过重写 sizeHint() 和 minimumSizeHint() 来设置控件的尺寸。
    信号和槽:通过定义自己的信号来与其他控件或类进行交互。

2、自定义控件的步骤

1、继承QWidget或者现有控件类
    大多数自定义控件都需要继承自QWidget类,或者继承一个已经实现的控件类(如 QPushButton、QLabel 等)。
    如果控件的行为较为复杂,还可以继承其他控件,如QFrame、QGroupBox等。
    
2、重载事件处理函数
    Qt提供了一些标准事件处理函数,可以通过重载它们来改变控件的行为。
    常用的事件处理函数包括:
        paintEvent(QPaintEvent *event):用于绘制控件。
        mousePressEvent(QMouseEvent *event):处理鼠标点击事件。
        mouseMoveEvent(QMouseEvent *event):处理鼠标移动事件。
        mouseReleaseEvent(QMouseEvent *event):处理鼠标释放事件。
        keyPressEvent(QKeyEvent *event):处理键盘事件。
        resizeEvent(QResizeEvent *event):处理控件大小改变的事件。
        
3、实现自定义控件的绘制逻辑
    在自定义控件中,最常见的事情之一是重写 paintEvent(),通过 QPainter 对象在控件上进行绘制。

3、绘制圆形按钮

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QDebug>
#include <QDragEnterEvent>
#include <QPushButton>
#include <QPainter>
#include <QWidget>
#include <QPoint>
#include <QMouseEvent>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
private:
    Ui::MainWindow *ui;
};
// ==================== 自定义按钮类 ====================
class my_btn : public QPushButton // 自定义按钮类,继承自 QPushButton
{
public:
    my_btn(const QString &text,QWidget * parent = nullptr)
        : QPushButton(text, parent)  // 调用父类构造函数,设置按钮文本和父对象
    {
        // 初始化圆心坐标(相对于按钮自身)
        x0 = width() / 2;    // 圆心的 X 坐标 = 按钮宽度的一半
        y0 = height() / 2;   // 圆心的 Y 坐标 = 按钮高度的一半
        qDebug() << "按钮文本:" << this->text();
    }
protected:
    // 重写了paintEvent,完全覆盖了父类的绘制逻辑,所以调用父类QPushButton的构造函数时文本效果未起作用
    // 重写绘制事件:将按钮绘制成圆形
    void paintEvent(QPaintEvent *event) override
    {
        // 创建 QPainter 对象,用于在按钮上绘制图形
        QPainter painter(this);
        // 开启抗锯齿(Antialiasing),使圆形边缘更平滑
        painter.setRenderHint(QPainter::Antialiasing);
        // 计算直径:取按钮宽度和高度的较小值(保证是正圆)
        int diameter = qMin(width(), height());
        // 计算半径 = 直径 / 2
        int radius = diameter / 2;
        // 计算圆心的坐标(按钮的中心点)
        int centerX = width() / 2;
        int centerY = height() / 2;
        qDebug()<<"圆心:("<<centerX<<","<<centerY<<") 半径:"<<radius;
        // 计算圆形绘制的矩形区域
        // 左上角 = (centerX - radius, centerY - radius)
        // 宽高 = diameter
        QRect rect(centerX - radius, centerY - radius, diameter, diameter);
        // 设置画刷颜色(填充颜色)
        // isDown() 返回 true 表示按钮被按下 → 深灰色
        // 否则(正常状态)→ 浅灰色
        painter.setBrush(isDown() ? Qt::darkGray : Qt::lightGray);  // 按下状态为深色
        // 绘制圆形(椭圆,但矩形是正方形,所以画出来是正圆)
        painter.drawEllipse(rect);
        // ===== 手动绘制文本 =====
        painter.setPen(Qt::black);  // 文本颜色
        painter.setFont(font());    // 使用按钮的字体
        painter.drawText(rect, Qt::AlignCenter, text());  // 在圆形中心绘制文本
    }
    // 重写鼠标按下事件
    void mousePressEvent(QMouseEvent *event) override
    {
        // 记录鼠标按下时的位置(相对于按钮自身)
        dragStartPos = event->pos();
        // 计算鼠标按下点与圆心的距离(两点间距离公式)
        // (x - x0)² + (y - y0)² < 50²
        // 即:鼠标点击位置必须在以 (x0, y0) 为圆心,50 像素为半径的圆内
        if((dragStartPos.x() - x0) * (dragStartPos.x() - x0) +
           (dragStartPos.y() - y0) * (dragStartPos.y() - y0) < 50*50)
        {
            // 调试输出圆心坐标
            qDebug()<<x0<<","<<y0;
            // 调用父类的鼠标按下事件处理(保留 QPushButton 的默认行为)
             QPushButton::mousePressEvent(event);
        }
        // 如果点击在圆形区域外,则不触发父类事件(按钮不会响应)
    }
    // 重写鼠标移动事件(实现拖拽功能)
    void mouseMoveEvent(QMouseEvent  *event) override
    {
        // 检查是否为左键拖动
        if (event->buttons() == Qt::LeftButton)
        {
            // 再次检查鼠标位置是否在圆形区域内
            if((dragStartPos.x() - x0) * (dragStartPos.x() - x0) +
               (dragStartPos.y() - y0) * (dragStartPos.y() - y0) < 50*50)
            {
                // 获取当前鼠标位置(相对于按钮自身)
                QPoint tmp_dragStartPos = event->pos();
                // 计算鼠标移动的偏移量(当前 - 按下时)
                int dx = tmp_dragStartPos.x() - dragStartPos.x();
                int dy = tmp_dragStartPos.y() - dragStartPos.y();
                // 更新按钮的位置(相对于父窗口)
                // x() 和 y() 是按钮当前在父窗口中的位置
                // move() 将按钮移动到新位置
                move(x() + dx, y() + dy);
            }
        }
        // 调用父类的鼠标移动事件处理
        QPushButton::mouseMoveEvent(event);
    }
    // 重写鼠标释放事件
    void mouseReleaseEvent(QMouseEvent *event) override
    {
        // 记录鼠标释放时的位置(用于后续判断)
        dragStartPos = event->pos();
        // 调用父类的鼠标释放事件处理
        QPushButton::mouseReleaseEvent(event);
    }
    QPoint dragStartPos; // 鼠标按下时的位置(相对于按钮自身)
    int x0; // 圆心的 X 坐标(相对于按钮自身)
    int y0; // 圆心的 Y 坐标(相对于按钮自身)
};
#endif // MAINWINDOW_H

main.cpp

#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    //自定义控件
    my_btn button("按钮",&w);
    w.show();
    return a.exec();
}

结果:

qt学习啊 /手写// .hprivate:// .cpp});});}); 阅读详情

相关推荐

QT学习(3)——对话框,模态非模态,系统对话框,界面布局,其他控件

QT学习(3)——对话框,模态非模态,系统对话框,界面布局,其他控件

Arya的博客,专注后端领域 845

QT小项目-雷达界面(三)绘制扫描效果

QT小项目-雷达界面(三)绘制扫描效果 去发现同类优质开源项目:https://gitcode.com/ 本项目为QT小项目系列的第三部分,主要展示了如何使用QT框架绘制雷达界面的扫描效果。以下为资源文件的详细介绍: 简介 本资源文件包含了绘制雷达界面扫描效果的完整代码和示例,旨在帮助开发者学习和掌握QT绘图相关的技术。 特点 基于QT框架,易于集成和扩展 实现了雷达界面扫描效果,视觉效果逼真 ...

gitblog_06704的博客 399

Mac上Office合法安装与激活全指南:2021/2024/M365区别解析

Office是微软办公套件的核心产品,其在macOS平台的部署逻辑与Windows截然不同——不依赖传统密钥激活,而是基于Microsoft账户与设备标识的云端绑定机制。理解这一原理,是解决‘无法验证开发者’‘打不开’‘功能受限’等常见问题的前提。Office 2021代表永久许可模型,Office 2024 LTSC面向企业离线场景,Microsoft 365则是持续订阅服务,三者在授权验证方式、更新策略与系统兼容性上存在本质差异。实际应用中,需结合macOS版本、芯片架构(Intel/Apple Sil

weixin_33491377的博客 1244

QT开发学习手册(三)-如何理解信号和槽

QT开发学习手册(三)-如何理解信号和槽 一、前言 二、过程 1、新建项目工程 然后一直选择默认设置,一直下一步 2、实现简单的信号和槽函数例程 1、头文件实现 #ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QPushButton> namespace Ui { c...

CH的博客 376

RM3100应用笔记驱动程序SPI接口

PNI磁传感器套件RM3100磁传感器套件由2个Sen-XY-f(pn13104)地磁传感器,1个Sen-Z-f(pn13101)地磁传感器和MagI2C(pn13156)控制芯片组成,能够实现三维空间的磁场大小测量。

AIoT技术栈的博客 4923

SystemC实战:用C++搞芯片建模的5个典型场景(含代码示例)

本文通过五个典型实战场景,详细介绍了如何使用SystemC这一基于C++的硬件建模库进行芯片设计与系统级建模。内容涵盖从基础并发模块构建、事务级总线建模、跨时钟域验证,到与ModelSim协同仿真及多核系统性能探索,并提供了完整的代码示例,帮助软件工程师利用熟悉的C++工具链高效参与硬件架构设计与验证。

weixin_29191761的博客 315

Nokia 论坛Qt开发者培训资料

qt_for_mobile_slides_day_1(Qt 偏底层知识,for windows/S60)qt_for_mobile_slides_day_2(Qt 偏上层知识,for windows/S60qt_for_mobile_slides_day_3(Maemo 开发)exercise_day_1demos_day_2

1069

【电弧故障检测算法全解析,电弧串扰问题分析和解决算法】

本文系统分析了电弧故障检测算法及串扰问题解决方案。电弧检测主要采用时频域分析和机器学习方法,通过提取高频噪声、波形畸变等特征实现故障识别。针对电弧串扰问题,提出了自适应滤波、盲源分离和时频联合分析等算法。研究给出了Python和C语言的算法实现示例,包括高频能量检测、过零率计算和陷波滤波器设计。最后指出算法优化方向:实时性提升可采用滑动窗口FFT和硬件加速;抗干扰增强需结合硬件滤波;机器学习扩展可引入随机森林等分类器。该研究为电弧故障检测系统开发提供了完整的技术路线。

syttt的专栏 891

基于QT的上位机串口助手设计

年前老师给我们安排了一个课程设计,是做智能电表,它可以采集电表的电流,电压,频率,以及功率。由于我当时为了找工作在自学QT编程,老师就让我做一个上位机用来读取下位机的数据,并且把采集到的数据以折线图形式打印出来。 我做的这个上位机通过QT自带的QSerialPort实现串口通信,绘图用的是第三方的库qcustomplot因为这个库相对来说比较简单可以实现的图表也很...

角落里的木头人的博客 2075

滤波器初步入门(非常全面)

主要关注的是-3dB这个点,-3dB就是截止频率所对应的点,我们把功率降至50%以下的信号定义为被衰减掉了(但要跟实际情况相结合,有些信号衰减-3db不够,需要衰减更多)-3dB这个点对应我们的电压来说是0.707。设计电路可以留一定的余量,如果你把4k设计为截止频率,那么4k时候衰减倍数为-3dB通常是不够的,你可以将截止频率设为2k,那么4k的衰减就可以达到15dB(假设),根据自己的需要去设计对应的截止频率。理想的滤波器是当输入的信号频率大于截止频率时,大于部分的频率对应的电压信号直接归0。

yybyybds的博客 5720

用WorkBuddy搭建漫剧AI自动化制作流水线全攻略

在内容创作领域,AI智能体正逐渐从单一工具辅助走向全流程自动化调度。其核心原理是将剧本、分镜、绘图、配音、剪辑等环节拆解为可独立执行的任务单元,由总控系统统一协调,从而大幅降低人力与时间成本。这种模式尤其适用于动态漫画(漫剧)这类环节多、专业度要求高的视频形态。传统制作流程中,角色一致性、配音周期和剪辑返工是公认的效率瓶颈,而借助AI智能体工作台,创作者只需输入故事创意,即可驱动多个数字分身协同完成内容生产。本文以WorkBuddy为例,详细展示如何配置模型、安装技能包并串联五段式流水线,将单集制作成本从万

weixin_28224217的博客 251

QT学习笔记(三)——系统标准对话框以及ui界面布局

QT学习笔记(三)——系统标准对话框以及ui界面布局

weixin_49513223的博客 1134

飞书文档API深度使用指南:如何用n8n社区节点绕过HTTP Request的复杂配置

本文详细解析了如何利用n8n社区节点简化飞书文档API的集成过程,绕过复杂的HTTP Request配置。通过n8n-feishu-lite社区节点,开发者可以轻松实现飞书文档的创建、编辑和查询操作,大幅提升自动化工作流的效率。文章还提供了高级应用场景和性能优化建议,帮助开发者更好地利用飞书开放平台的API功能。

weixin_29227585的博客 83

QT5.14入门教程GUI(三)第3个QT程序-单选按钮2

QT5.14入门教程GUI(三)第3个QT程序-单选按钮2 本章介绍如何使用单选按钮,使用槽链接,实现; 续接上一篇,QT5.14入门教程GUI(三)第3个QT程序-单选按钮1 1、打开头文件文件,双击; 2、新增函数声明; void on_Colour_clicked(); 3、主文件,打开; 4、在构造函数新增,链接; QObject::conn...

airanl的博客 1533

产品路线图的三种模型(RICE/MoSCoW/Kano),教你如何对需求进行优先级排序

RICE/MoSCoW/Kano三种模型,教你如何对需求进行优先级排序。 也许你会让业务提供一份ROI,记得前不久参加过一场立项会评审,一位很有意思的小产品在会上讲不清楚ROI,评审们要求会后重新梳理,小产品表达不要为难业务方干一些他们不擅长的事了。这个看似笑话的经历,背后隐藏着价值判断已经流于形式。 也许你会要求业务方直接给出需求优先级列表,把任务分为P0到P5,这样的划分除了按需求本质的优先级还同时考虑了开发资源、开发难度等问题。毫不夸张地说,我曾经拿到一张全是P0级别的需求清单,如果一切任务都是高

wenyusuran的专栏 5540

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

Qt实战一二三

简介 “我们来自Qt分享&&交流,我们来自Qt Quick分享&&交流”,不管你是笑了,还是笑了,反正我们是认真的。我们就是要找寻一种Hold不住的状态,来开始每一天的点滴分享,我们是一个有激情,有态度的部队,还在等什么,赶快加入吧! 但是我们还是我们,我们只是多了一份责任。古语有云:”不积跬步无...

weixin_34399060的博客 202

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

QT 新手小白USBCAN 学习

学习 USBCAN

m0_52467164的博客 5779

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

【AI时代速通QT】第五节:Qt Creator如何引入第三方库,以OpenCV为例

本文详细介绍了在Qt Creator中引入OpenCV第三方库的完整流程。首先阐述了准备工作,包括获取OpenCV库文件和建立合理的项目目录结构。接着重点讲解了两种配置.pro文件的方法:图形化向导和手动编辑(推荐),特别是如何使用相对路径和条件编译区分Debug/Release模式。然后通过修改main.cpp添加简单的OpenCV测试代码验证配置。最后针对运行时常见的DLL丢失问题,提供了三种解决方案:手动复制DLL、配置Qt运行环境以及编写构建后自动拷贝脚本(推荐)。文章强调了规范的项目结构和相对路径

攻城狮7号的博客 8018

QT跨平台应用程序开发框架(9)—— 容器类控件

QGridLayout 用来实现网格布局的效果,可以达到 M * N 的这种网格效果,主要属性和 QHBoxLayout 类似,但是设置 spacing 的时候是按照垂直水平两个方向来设置的。每个 Widget 只能设置一个布局管理器, 但是可以通过拖拽方式创建两个布局遍历器,但是这样创建的布局管理器仅仅只会将内部控件重新组合位置,并不会像上面一样随着窗口大小改变。而容器内控件包含的直接就是我们前面介绍的一堆的控件。解答:我们前面使用ui创建界面时,都是手动拖拽方式来布局的,其实这种方式不科学。

aaqq800520的博客 1153

Qt学习之Qt基础入门(上)

Qt语法 基础入门 槽函数 创建项目 文件

RongLin02的博客 1万+

QT跨平台应用程序开发框架(4)—— 常用控件QWidget

有时候 Qt 内置的光标可能满足不了我们的需求,所以 Qt 也允许我们通过自定义图片的方式来设置光标//设置图标//设置窗口的图标//当我们点击时,是图片左上角在进行点击//假设我在按钮的边缘位置进行点击,但由于光标图片的左上角到按钮外面去了导致点击不到//所以我们可以设置实际点击在图片光标里的位置,10,10表示点击实际生效的位置,左上角是0,0如果导入的图片太大,我们也而已通过下面的API对图片进行缩放:iconfont-阿里巴巴矢量图标库。

aaqq800520的博客 1567

Qt 使用第三方库

在 Qt 中经常会用到第三方库,例如:FFmpeg、OpenCV 等。第三方库的使用比较简单,只需要一些基本的配置就可以搞定,一起来看看吧!

青春不老,奋斗不止! 2万+

QT跨平台应用程序开发框架(8)—— 多元素控件

所以要想数据不被丢失,就得需要和“学生管理系统”一样,实现一个“保存数据到文件”和“从文件读取数据”的两个操作,每次运行程序时读取文件数据,每次关闭程序时,在析构函数里添加保存文件的操作。QTreeWidget 表示一个树形控件,里面的每个元素都是一个 QTreeWidgetItem,这个类可以包含多个文本和图标,每个文本/图标为一个列。上述几个控件相关的操作,数据都是在内存中保存的,重新运行程序后,数据都会重置。可以发现,说是6个控件,其实是3个,只是两两一组而已。

aaqq800520的博客 890

QT跨平台应用程序开发框架(1)—— 环境搭建

其实说是安装三个东西,其实只要安装一个Qt SDK,其它两个都有了。之后一路点击下一步即可,就是安装路径不要带中文,不要带特殊符号和空格。创建好项目后会预先生成一些代码,我们来讲解一下这些代码做了什么。Windows下还有哪些方案可以开发GUI?之后一路确认然后安装即可。

aaqq800520的博客 3885

Qt学习及使用_第1部分_认识Qt---学习目的及技术准备

学以致用,通过QT框架的学习,一边实践,一边探索编程的方方面面参考书:<Qt 6 C++开发指南>(以下称"本书")概念用粗体+倾斜.重点内容用(加粗黑体)---重点内容(红字)---重点内容(加粗红字),本书原话内容用深蓝色标识,比较重要的内容用加粗倾斜下划线深蓝色标识。

jllws1的博客 1271

QT学习笔记(一)——QT基础

qt学习笔记(一)

weixin_49513223的博客 5924
上一篇: QT的学习第二部分
下一篇: QT的windows程序打包
橙橙笔记
博客等级 码龄4年 13粉丝 42原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值