Qt学习笔记第61到70讲

news2025/1/31 11:10:50

第61讲 记事本实现当前行高亮功能

实现策略: 获取当前行的光标位置,使用的信号和获取行列值是一样的,即通过ExtraSelection 来配置相关属性。
关键API:
QList<QTextEdit::ExtraSelection> extraSelections;
void setExtraSelections(const QList<QTextEdit::ExtraSelection> &extraSelections)

ExtraSelection类内部有两个公有成员变量:

其中cursor可以存储获取的光标当前位置信息(比如行数),format用来存储文本样式属性。

综上所述,当前行高亮这个功能的实现还是需要在光标点击的响应槽函数onCursorPositionChanged内部。

第一步,声明了一个 QList 容器 extraSelections,用于存储 QTextEdit::ExtraSelection 类型的元素,并且明了一个 QTextEdit::ExtraSelection(结构体) 类型的变量 ext;

QList <QTextEdit::ExtraSelection> extraSelections;
QTextEdit::ExtraSelection ext;

第二步,利用textEdit内部的textCursor方法获取当前行信息;

 ext.cursor=ui->textEdit->textCursor();

第三步,开始配置颜色,创建了一个 QBrush 对象 qBrush,并使用 Qt::lightGray 颜色初始化它,然后通过 ext.format.setBackground(qBrush) 这行代码,将创建好的画刷所代表的颜色(浅灰色)设置为 ext 这个 ExtraSelection 实例对应的文本格式(ext.format)的背景颜色;

QBrush qBrush(Qt::lightGray);
ext.format.setBackground(qBrush);

第四步,利用setProperty方法配置段属性为整行显示

 ext.format.setProperty(QTextFormat::FullWidthSelection,true);

这行代码调用了 ext.formatQTextCharFormat 类型,用于设置文本的字符格式相关属性)的 setProperty 方法,将 QTextFormat::FullWidthSelection 属性设置为 trueQTextFormat::FullWidthSelection 这个属性表示文本选择区域按照整行的宽度来显示,确保不仅仅是当前光标所在处的文本有背景颜色等样式设置,而是整行文本都会应用之前配置的背景颜色(也就是浅灰色),实现整行高亮的效果。

第五步,进行整体配置

extraSelections.append(ext);
ui->textEdit->setExtraSelections(extraSelections);

第一行 extraSelections.append(ext) 将配置好的 ext(代表当前行的额外选择区域相关属性)添加到 extraSelections 列表中。最后一行 ui->textEdit->setExtraSelections(extraSelections) 则调用了 textEdit 部件的 setExtraSelections 方法,将包含了当前行额外选择区域配置信息的 extraSelections 列表传递进去,使得 textEdit 部件按照这个列表里定义的规则(这里就是当前行高亮的相关属性设置)来更新其显示效果,最终实现在文本编辑部件中当前行被高亮显示的功能。

最后整个槽函数:

void Widget::onCursorPositionChanged(void)
{
    QTextCursor cursor=ui->textEdit->textCursor();
    //qDebug()<<cursor.blockNumber()+1 <<cursor.columnNumber()+1;

    QString blockNum=QString::number(cursor.blockNumber()+1);
    QString columnNum=QString::number(cursor.columnNumber()+1);
    const QString labelMes="L:"+blockNum+" "+"C:"+columnNum;

    ui->labelPositon->setText(labelMes);

    /*设置当前行高亮*/
    //0.声明了一个 QList 容器 extraSelections
    QList <QTextEdit::ExtraSelection> extraSelections;
    //同时声明了ext这个结构体变量
    QTextEdit::ExtraSelection ext;

    //1.获取当前行的数值
    ext.cursor=ui->textEdit->textCursor();
    //2.配置颜色
    QBrush qBrush(Qt::lightGray);
    ext.format.setBackground(qBrush);
    //3.配置段属性,整行显示
    ext.format.setProperty(QTextFormat::FullWidthSelection,true);
    //4.整体配置
    extraSelections.append(ext);
    ui->textEdit->setExtraSelections(extraSelections);

}

运行效果:

第62讲 记事本优化保存文件的逻辑

代码目前存在这么一个问题,在当前页面编辑了一部分文本之后无法通过按键关闭清除。

解决方法是按下关闭按键的时候,不进行文件是否打开的判断,直接使用clear函数清屏。

void Widget::on_btnClose_clicked()
{
   ui->textEdit->clear();

   if(file.isOpen())
   {
       file.close();    
       this->setWindowTitle("NotesBook");
   }

}

现在无论文件是否存在于文件中都需要弹出对话框进行询问,和我们的操作习惯不搭,我们更希望在原文件已经存在的时候,直接按保存就行。所以我们需要对btnSave槽函数做出修改:

void Widget::on_btnSave_clicked()
{
    //如果当前没有文件打开,就弹窗让用户选择新文件,创建新文件;
    //而不是原来那样,都弹出新的文件保存窗口
    if(!file.isOpen()){
        QString fileName = QFileDialog::getSaveFileName(this, tr("SaveFile"),
        "E:\\6_Qt Projects\\31_NotepadCodec\\files\\untitled file.txt",
        tr("Text (*.txt*.doc)"));

        file.setFileName(fileName);
        if(!file.open(QIODevice::WriteOnly | QIODevice::Text)){
           qDebug() << "file open error";
          }
       this->setWindowTitle(fileName + "- MyNoteBook");
    }else
    {
        // 如果文件已打开,先将文件指针移动到文件开头,准备覆盖原有内容
        file.seek(0);
        // 截断文件内容,清除原有内容
        file.resize(0);
    }

    //当保存被按下,不管是已有打开的文件还是上面if满足后用户选择新文件,
    //都要读取TextEdit内容并写入文件中
    QTextStream out(&file);
    out.setCodec(ui->comboBox->currentText().toStdString().c_str());
    QString context = ui->textEdit->toPlainText();
    out << context;
}

第63讲 记事本关闭按钮功能优化

对于QT框架下的陌生组件,推荐大家在帮助界面查看Detailed Description。

可以看到这里有着各种类型的API:

我们选用一个静态的warning函数和一个switch循环分支结构:

int ret = QMessageBox::warning(this, tr("My Application"),
                                tr("The document has been modified.\n"
                                   "Do you want to save your changes?"),
                                QMessageBox::Save | QMessageBox::Discard
                                | QMessageBox::Cancel,
                                QMessageBox::Save);

switch (ret) {
   case QMessageBox::Save:
       // Save was clicked
       break;
   case QMessageBox::Discard:
       // Don't Save was clicked
       break;
   case QMessageBox::Cancel:
       // Cancel was clicked
       break;
   default:
       // should never be reached
       break;
 }

为了警告对话框的出现更加符合我们的习惯,我在widget类添加了新的成员变量:

然后对widget.cpp文件做出如下修改:

#include "widget.h"
#include "ui_widget.h"

#include <QFileDialog>
#include <QDebug>
#include <QList>
#include <QColor>
#include <QMessageBox>

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

    connect(ui->comboBox,SIGNAL(currentIndexChanged(int)),
    this,SLOT(onCurrentIndexChanged(void)));

    connect(ui->textEdit,SIGNAL(cursorPositionChanged()),
    this,SLOT(onCursorPositionChanged()));
}

Widget::~Widget()
{
    delete ui;
}


void Widget::on_btnOpen_clicked()
{
    QString fileName=QFileDialog::getOpenFileName(this,tr("Open File"),
    "E:\\6_Qt Projects\\31_NotepadCodec\\files",tr("Text(*.txt *.doc)"));
    //QFileDialog限制程序可打开的文件形式为txt文件或者doc文本

    ui->textEdit->clear();
    //每次打开文件时清除控件区域“textEdit”

    file.setFileName(fileName);

    if(!file.open(QIODevice::ReadWrite|QIODevice::Text))
    {
        qDebug()<<"file open error";
    }

    this->setWindowTitle(fileName+"-NotesBook");

    QTextStream in(&file);

    QString str=ui->comboBox->currentText();
    const char* c_str=str.toStdString().c_str();

    in.setCodec(c_str);

    while(!in.atEnd())
    {
        QString context=in.readLine();
        //qDebug()<<qPrintable(context);

        ui->textEdit->append(context);
        //将读取到的每行内容通过 append 方法添加到界面的文本编辑框(ui->textEdit)中
    }

    // 将此时ui->textEdit中的文本内容保存到initialText变量中,作为初始文本
     initialText = ui->textEdit->toPlainText();
}

void Widget::on_btnSave_clicked()
{
    //如果当前没有文件打开,就弹窗让用户选择新文件,创建新文件;
    //而不是原来那样,都弹出新的文件保存窗口
    if(!file.isOpen()){
        QString fileName = QFileDialog::getSaveFileName(this, tr("SaveFile"),
        "E:\\6_Qt Projects\\31_NotepadCodec\\files\\untitled file.txt",tr("Text (*.txt*.doc)"));

        file.setFileName(fileName);
        if(!file.open(QIODevice::WriteOnly | QIODevice::Text)){
           qDebug() << "file open error";
          }
       this->setWindowTitle(fileName + "- MyNoteBook");
    }else
    {
        // 如果文件已打开,先将文件指针移动到文件开头,准备覆盖原有内容
        file.seek(0);
        // 截断文件内容,清除原有内容
        file.resize(0);
    }

    //当保存被按下,不管是已有打开的文件还是上面if满足后用户选择新文件,
    //都要读取TextEdit内容并写入文件中
    QTextStream out(&file);
    out.setCodec(ui->comboBox->currentText().toStdString().c_str());
    QString context = ui->textEdit->toPlainText();
    out << context;
    //按下保存按钮会修改初始文本
    initialText=ui->textEdit->toPlainText();
}

void Widget::on_btnClose_clicked()
{
    QString currentText = ui->textEdit->toPlainText();
    if(currentText!= initialText){
        int ret = QMessageBox::warning(this, tr("NotesBook Notice"),
                                       tr("The document has been modified.\n"
                                          "Do you want to save your changes?"),
                                       QMessageBox::Save | QMessageBox::Discard
                                       | QMessageBox::Cancel, QMessageBox::Save);

        switch (ret) {
        case QMessageBox::Save:
            // Save was clicked
            on_btnSave_clicked();
            ui->textEdit->clear();
            break;

        case QMessageBox::Discard:
            // Don't Save was clicked
            ui->textEdit->clear();
            if (file.isOpen()) {
                file.close();
                this->setWindowTitle("NotesBook");
            }
            break;

        case QMessageBox::Cancel:
            // Cancel was clicked
            break;

        default:
            // should never be reached
            break;
        }
    } else {
        ui->textEdit->clear();
        if (file.isOpen()) {
            file.close();
            this->setWindowTitle("NotesBook");
        }
    }
}

void Widget::onCurrentIndexChanged(void)
{
    ui->textEdit->clear();
    if(file.isOpen())
    {
        QTextStream in(&file);
        in.setCodec(ui->comboBox->currentText().toStdString().c_str());
        //链式调用访问成员变量
        file.seek(0);//将光标移动回起始点
        while(!in.atEnd())
        {
            QString context=in.readLine();
            ui->textEdit->append(context);
        }
    }
}

void Widget::onCursorPositionChanged(void)
{
    QTextCursor cursor=ui->textEdit->textCursor();
    //qDebug()<<cursor.blockNumber()+1 <<cursor.columnNumber()+1;

    QString blockNum=QString::number(cursor.blockNumber()+1);
    QString columnNum=QString::number(cursor.columnNumber()+1);
    const QString labelMes="L:"+blockNum+" "+"C:"+columnNum;

    ui->labelPositon->setText(labelMes);

    /*设置当前行高亮*/
    //0.声明了一个 QList 容器 extraSelections
    QList <QTextEdit::ExtraSelection> extraSelections;
      //同时声明了ext这个结构体变量
    QTextEdit::ExtraSelection ext;

    //1.获取当前行的数值
    ext.cursor=ui->textEdit->textCursor();
    //2.配置颜色
    QBrush qBrush(Qt::lightGray);
    ext.format.setBackground(qBrush);
    //3.配置段属性,整行显示
    ext.format.setProperty(QTextFormat::FullWidthSelection,true);
    //4.整体配置
    extraSelections.append(ext);
    ui->textEdit->setExtraSelections(extraSelections);

}

第64讲 记事本添加快捷键功能

我们通常使用QShortcut类来实现快捷键的功能,就像下图中的手册内容节选:

最简单的应用方法如下:

/*The simplest way to create a shortcut for a particular widget is to 
construct the shortcut with a key sequence. For example:*/
QShortcut *shortcut = new QShortcut(QKeySequence(tr("Ctrl+O", "File|Open")),parent);

注意new创建的对象返回类型均为指针。

此时我们已经梳理出了事件“按下快捷键Ctrl+O”,槽函数可以为“on_btnOpen_clicked()”,还需要找到事件触发的信号。

查阅手册得知,QShortcut类继承QObject类的两个静态信号。

最后Widget的构造函数被修改为:


Widget::Widget(QWidget *parent) : QWidget(parent) , ui(new Ui::Widget)
{
    ui->setupUi(this);

    QShortcut *shortcutOpen = new QShortcut(QKeySequence(tr("Ctrl+O", "File|Open")),
                                        this);
    QShortcut *shortcutSave = new QShortcut(QKeySequence(tr("Ctrl+S", "File|Save")),
                                        this);

    connect(shortcutOpen,&QShortcut::activated,[=](){on_btnOpen_clicked();});
    connect(shortcutSave,&QShortcut::activated,[=](){on_btnSave_clicked();});

    this->setLayout(ui->verticalLayout);
    ui->widgetBottom->setLayout(ui->horizontalLayout);

    connect(ui->comboBox,SIGNAL(currentIndexChanged(int)),
    this,SLOT(onCurrentIndexChanged(void)));

    connect(ui->textEdit,SIGNAL(cursorPositionChanged()),
    this,SLOT(onCursorPositionChanged()));
}

第64讲 记事本快捷键放大缩小字体

QWidget类内部的setFont方法可以动态改变UI显示的字体大小,我们跳转查看一下函数定义:

void setFont(const QFont &);

注意该方法需要传入一个QFont类型的引用,同时QFont内部有pointSize方法获取当前字体大小。

综上所述,我们可以和上一章先使用QShortcut类创建按键事件,再使用connect函数将信号与槽关联起来。其中除了槽函数在Widget构造函数外部实现之外,其余均在内部修改。

Widget构造函数:

Widget::Widget(QWidget *parent) : QWidget(parent) , ui(new Ui::Widget)
{
    ui->setupUi(this);

    QShortcut *shortcutOpen = new QShortcut(QKeySequence(tr("Ctrl+O", "File|Open")),
                                        this);
    QShortcut *shortcutSave = new QShortcut(QKeySequence(tr("Ctrl+S", "File|Save")),
                                        this);
    QShortcut *shortcutEnlarge = new QShortcut(QKeySequence(tr("Ctrl+Shift+=", "File|Enlarge")),
                                        this);
    QShortcut *shortcutReduce = new QShortcut(QKeySequence(tr("Ctrl+Shift+-", "File|Reduce")),
                                          this);

    connect(shortcutOpen,&QShortcut::activated,[=](){on_btnOpen_clicked();});
    connect(shortcutSave,&QShortcut::activated,[=](){on_btnSave_clicked();});
    connect(shortcutEnlarge,&QShortcut::activated,[=](){textEditEnlarge();});
    connect(shortcutReduce, &QShortcut::activated,[=](){textEditReduce();});

    this->setLayout(ui->verticalLayout);
    ui->widgetBottom->setLayout(ui->horizontalLayout);

    connect(ui->comboBox,SIGNAL(currentIndexChanged(int)),
    this,SLOT(onCurrentIndexChanged(void)));

    connect(ui->textEdit,SIGNAL(cursorPositionChanged()),
    this,SLOT(onCursorPositionChanged()));
}

使得字体增大\减小的槽函数:

void Widget::textEditEnlarge()
{
    //获取当前TextEdit内的字体信息
    QFont font=ui->textEdit->font();
    //获取当前字体的大小
    int fontSize=font.pointSize();
    if(fontSize==-1) return;

    //改变大小,并设置字体大小
    int newFontSize=fontSize+1;
    font.setPointSize(newFontSize);
    ui->textEdit->setFont(font);
}

void Widget::textEditReduce()
{
    //获取当前TextEdit内的字体信息
    QFont font=ui->textEdit->font();
    //获取当前字体的大小
    int fontSize=font.pointSize();
    if(fontSize==-1) return;

    //改变大小,并设置字体大小
    int newFontSize=fontSize-1;
    font.setPointSize(newFontSize);
    ui->textEdit->setFont(font);
}

建议在Widget.h文件内部添加上两个槽函数的声明:

第65讲 QT事件的引入

人机交互最早的时候是用命令行,比如查看我们PC机上的网络信息(以Win11为例),可以按下Win+R->输入cmd->输入ipconfig:

本节课我们要实现的滚轮缩放文本字体本质上也是一种人机交互事件。众所周知Qt是一个基于C++的框架,主要用来开发带窗口的应用程序(不带窗口的也行,但不是主流)。 我们使用的基于窗口的应用程序都是基于事件,其目的主要是用来实现回调(因为只有这样程序的效率才是最高的)。所以在Qt框架内部为我们提供了一些列的事件处理机制,当窗口事件产生之后,事件会经过: “事件派发 -> 事件过滤->事件分发->事件处理” 几个阶段。Qt窗口中对于产生的一系列事件都有默认的处理动作,如果我们有特殊需求就需要在合适的阶段重写事件的处理动作,比如信号与槽就是一种事件(event)是由系统或者 Qt 本身在不同的场景下发出的。当用户按下/移动鼠标、敲下键盘,或者是窗口关闭/大小发生变化/隐藏或显示都会发出一个相应的事件。一些事件在对用户操作做出响应时发出,如鼠标/键盘事件等;另一些事件则是由系统自动发出,如计时器事件。

每一个Qt应用程序都对应一个唯一的 QApplication 应用程序对象,然后调用这个对象的 exec() 函 数,这样Qt框架内部的事件检测就开始了( 程序将进入事件循环来监听应用程序的事件 )。

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow* w = new MainWindow;
    w.show();
    return a.exec();
}
事件在 Qt 中产生之后,的分发过程是这样的:
1. 当事件产生之后, Qt 使用用应用程序对象调用 notify() 函数将事件发送到指定的窗口:
[override virtual] bool QApplication::notify(QObject *receiver, QEvent *e);
2. 事件在发送过程中可以通过事件过滤器进行过滤,默认不对任何产生的事件进行过滤。
// 需要先给窗口安装过滤器, 该事件才会触发
[virtual] bool QObject::eventFilter(QObject *watched, QEvent *event)
3. 当事件发送到指定窗口之后,窗口的事件分发器会对收到的事件进行分类 :
[override virtual protected] bool QWidget::event(QEvent *event);
4. 事件分发器会将分类之后的事件(鼠标事件、键盘事件、绘图事件等等)分发给对应的事件处理器函数进行处理,每个事件处理器函数都有默认的处理动作(我们也可以重写这些事件处理器函
数),比如:鼠标事件:
// 鼠标按下
[virtual protected] void QWidget::mousePressEvent(QMouseEvent *event);
// 鼠标释放
[virtual protected] void QWidget::mouseReleaseEvent(QMouseEvent *event);
// 鼠标移动
[virtual protected] void QWidget::mouseMoveEvent(QMouseEvent *event);

第66讲 重写窗口各类默认事件

创建了五个例子,分别是鼠标进入窗口的事件、鼠标离开窗口的事件、滚轮上下滚动的事件、店家关闭按钮的事件以及拖动窗口大小的事件。

代码示例如下:

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
#include <QMessageBox>
#include <QWheelEvent>

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

Widget::~Widget()
{
    delete ui;
}

void Widget::enterEvent(QEvent *event)
{
    qDebug()<<"mouse enter";
}

void Widget::leaveEvent(QEvent *event)
{
    qDebug()<<"mouse leave";
}


void Widget::wheelEvent(QWheelEvent *event)
{
    qDebug()<<event->angleDelta();
}

void Widget::closeEvent(QCloseEvent *event)
{
    int ret = QMessageBox::warning(this, tr("My Application"),
                                   tr("close the window\n"
                                      "Do you really want to leave?"),
                                   QMessageBox::Ok | QMessageBox::No);

    switch(ret)
    {
       case QMessageBox::Ok:
           event->accept();
        break;

       case QMessageBox::No:
           event->ignore();
        break;

    }

}

void Widget::resizeEvent(QResizeEvent *event)
{
    qDebug()<<"oldSize"<<event->oldSize();
    qDebug()<<"newSize"<<event->size(); 
}

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

    /*personel EventGroup begin*/
    void enterEvent(QEvent *event) override;
    void leaveEvent(QEvent *event) override;
    void wheelEvent(QWheelEvent *event) override;
    void closeEvent(QCloseEvent *event) override;
    void resizeEvent(QResizeEvent *event)override;

    /*personel EventGroup end*/

private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

第67讲 用事件自定义出一个按钮

补充知识

①explicit关键字的作用?

抑制隐式转换;在 C++ 中,explicit关键字主要用于修饰构造函数。当一个构造函数被声明为explicit时,它不能用于隐式转换。例如:

class MyClass {
public:
    int value;
    explicit MyClass(int val) : value(val) {}
};

②在头文件内声明函数过后按下alt+enter可以快速在cpp文件中添加定义:

③在工程文件中新建一个res文件

(1)右键工程图标,新建

(2)选择Qt框架下的Qt Resource File

(3)清除前缀,添加文件

编程设计

首先在Widget.h头文件内部实例化一个QPixmap类的对象pic,以及三个鼠标事件(点击、离开、进入)和一个绘图事件。

#ifndef MYBUTTON_H
#define MYBUTTON_H

#include <QWidget>

class MyButton : public QWidget
{
    Q_OBJECT
public:
    explicit MyButton(QWidget *parent = nullptr);

/*personel components begin*/
private:
    QPixmap pic;

protected:
    void mousePressEvent(QMouseEvent *event) override;
    void leaveEvent(QEvent *event) override;
    void enterEvent(QEvent *event) override;
    void paintEvent(QPaintEvent *event) override;



/*personel components end*/

signals:

};

#endif // MYBUTTON_H

其次在MyButton.cpp文件内对这些函数予以实现:

#include "mybutton.h"

#include <QPainter>

MyButton::MyButton(QWidget *parent) : QWidget(parent)
{
    pic.load(":/icon/blackOpen.png");
    setFixedSize(pic.size());

    update();
}

void MyButton::mousePressEvent(QMouseEvent *event)
{
    pic.load(":/icon/redOpen.png");
    update();
}

void MyButton::leaveEvent(QEvent *event)
{
    pic.load(":/icon/blackOpen.png");
    update();
}

void MyButton::enterEvent(QEvent *event)
{
    pic.load(":/icon/yellowOpen.png");
    update();
}

void MyButton::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.drawPixmap(rect(),pic);
}

总结,注意掌握QPixmap类与QPainter类的使用,讲解可以求助AI老师,如下:

①构造函数部分

②绘制事件处理部分

设计UI

①拖动一个Widget组件到UI画面

②然后提升类型为MyButton

第68讲 使用自定义按键的信号与槽

①在按键类内部新增信号clciked

#ifndef MYBUTTON_H
#define MYBUTTON_H

#include <QWidget>

class MyButton : public QWidget
{
    Q_OBJECT
public:
    explicit MyButton(QWidget *parent = nullptr);

/*personel components begin*/
private:
    QPixmap pic;

protected:
    void mousePressEvent(QMouseEvent *event) override;
    void leaveEvent(QEvent *event) override;
    void enterEvent(QEvent *event) override;
    void paintEvent(QPaintEvent *event) override;





signals:
   void clicked();

 /*personel components end*/
};

#endif // MYBUTTON_H

②在鼠标点击事件中发射信号(mybutton.cpp内修改)

void MyButton::mousePressEvent(QMouseEvent *event)
{
    pic.load(":/icon/redOpen.png");
    update();
    emit clicked();
}

③在widget类内部关联信号与槽(widget.cpp内修改)

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    connect(ui->mybtn,&MyButton::clicked,[=](){
        qDebug()<<"myButton is clicked!";
    });
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2261841.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Axure高保真数据可视化大屏图表组件库

推出了一款高保真数据可视化大屏图表组件库&#xff0c;旨在为用户提供丰富的图表类型&#xff0c;使数据呈现更加直观、生动。本文将详细介绍该组件库中的各类图表元件&#xff0c;包括面积图、折线图、柱状图、条形图、圆环图、雷达图、仪表图以及综合类图表&#xff0c;以满…

【机器学习】在向量的流光中,揽数理星河为衣,以线性代数为钥,轻启机器学习黎明的瑰丽诗章

文章目录 线性代数入门&#xff1a;机器学习零基础小白指南前言一、向量&#xff1a;数据的基本单元1.1 什么是向量&#xff1f;1.1.1 举个例子&#xff1a; 1.2 向量的表示与维度1.2.1 向量的维度1.2.2 向量的表示方法 1.3 向量的基本运算1.3.1 向量加法1.3.2 向量的数乘1.3.3…

【鸿睿创智开发板试用】RK3568 NPU的人工智能推理测试

目录 引言 驱动移植 例程编译 修改build.sh 执行编译 运行测试 部署libc的库文件 执行测试程序 结语 引言 鸿睿创智的H01开发板是基于RK3568芯片的&#xff0c;瑞芯微芯片的一大特色就是提供了NPU推理的支持。本文将对其NPU推理进行测试。 驱动移植 H01的开发板已经…

3D相框案例讲解(详细)

前言 通过现阶段的学习&#xff0c;我们已经掌握了HTML&#xff0c;CSS和JS部分的相关知识点&#xff0c;现在让我们通过一篇案例&#xff0c;来巩固我们近期所学的知识点。 详细视频讲解戳这里 任务一 了解目标案例样式 1.1了解案例 3D相框 1.2 分析案例 首先我们看到一个…

【试听开放中】新中地2408期GIS特训营同步,学习路线图+职业规划

很多地信相关专业的同学都知道 学习开发很重要&#xff1f;项目实战经验很重要 但是在面对学什么语言&#xff1f;掌握什么技术的时候 同学又就开始犯嘀咕&#xff0c;这么多&#xff0c;到底学什么&#xff1f; 基础入门 1.掌握GIS基础的理论知识 2.HTML5标签搭建页面结构…

Ubuntu 18.04无有线图表且无法设置有线网络

问题背景&#xff1a; 今天在登陆自己的虚拟机Ubuntu系统的时候突然出现 有线连接无法连接的问题&#xff0c;有线连接的图标变为没有了&#xff0c;无法点击网络菜单的Setting模块选项。我的虚拟机有线网络连接方式是NAT方式。 没有如下有线连接图标 解决方法&#xff1a; …

设计规规范:【App 配色】

文章目录 引言I App 配色组成色彩象征 & 联想II 知识扩展设计流程图UI设计交互设计UI交互设计引言 设计规范,保持设计一致性,提高设计效率。宏观上对内统一,管理与合作变得容易。 按类型管理颜色、文本样式、图标、组件(symbol)。 蓝湖设计规范云 https://lanhuapp.co…

[maven]使用spring

为了更好理解springboot&#xff0c;我们先通过学习spring了解其底层。 这里讲一下简单的maven使用spring框架入门使用。因为这一块的东西很多都需要联合起来后才好去细讲&#xff0c;本篇通过spring-context大致地介绍相关内容。 注意&#xff1a;spring只是一个框架&#xff…

Unity性能优化---使用SpriteAtlas创建图集进行批次优化

在日常游戏开发中&#xff0c;UI是不可缺少的模块&#xff0c;而在UI中又使用着大量的图片&#xff0c;特别是2D游戏还有很多精灵图片存在&#xff0c;如果不加以处理&#xff0c;会导致很高的Batches&#xff0c;影响性能。 比如如下的例子&#xff1a; Batches是9&#xff0…

transformer学习笔记-位置编码

在transformer学习笔记-自注意力机制&#xff08;1&#xff09;学习原理的时候&#xff0c;我们提到: 将句子从“苹果梨”&#xff0c;改成“梨苹果”&#xff0c;最终的到的新苹果和新梨&#xff0c;竟然是一样的&#xff0c;因为苹果和梨两个向量调换顺序后&#xff0c;对应计…

【Unity3D】实现UGUI高亮引导点击

Unity版本2019.4.0f1 Personal <DX11> using UnityEngine; using UnityEngine.UI;public class GuideMask : MonoBehaviour, ICanvasRaycastFilter {public Canvas canvas;public Transform guideTargetTrans;public Image image;private Vector3 guideTargetWorldPos;pr…

Springboot3.x配置类(Configuration)和单元测试

配置类在Spring Boot框架中扮演着关键角色&#xff0c;它使开发者能够利用Java代码定义Bean、设定属性及调整其他Spring相关设置&#xff0c;取代了早期版本中依赖的XML配置文件。 集中化管理&#xff1a;借助Configuration注解&#xff0c;Spring Boot让用户能在一个或几个配…

SpringBoot增删改查导入导出操作【模板】

SpringBoot增删改查导入导出操作【模板】 文章目录 SpringBoot增删改查导入导出操作【模板】前期数据库操作IDEA上进行操作1. 创建 Spring Boot 项目2. 项目结构3. pom.xml文件4. 配置数据库连接并进行测试5. 创建实体类6. 创建 MyBatis Mapper7. 创建服务层8. 创建控制器9. 启…

mfc140.dll是什么东西?mfc140.dll缺失的几种具体解决方法

mfc140.dll是Microsoft Foundation Classes&#xff08;MFC&#xff09;库中的一个动态链接库&#xff08;DLL&#xff09;文件&#xff0c;它是微软基础类库的一部分&#xff0c;为Windows应用程序的开发提供了丰富的类库和接口。MFC库旨在简化Windows应用程序的开发过程&…

探索Starship:一款用Rust打造的高性能终端

在终端的世界里&#xff0c;效率和美观往往并行不悖。今天&#xff0c;我们要介绍的是一款名为Starship的终端工具&#xff0c;它以其轻量级、高颜值和强大的自定义功能&#xff0c;赢得了众多开发者的青睐。 安装 任选一种方式进行安装 Windows &#x1fa9f; # scoop scoo…

2024年NSSCTF秋季招新赛-WEB

The Beginning F12看源码&#xff0c;有flag http标头 黑吗喽 题目说要在发售时的0点0分&#xff0c;所以添加标头data Date: Tue, 20 Aug 2024 00:00:00 GMT然后改浏览器头 User-Agent: BlackMonkey曲奇就是Cookie cookieBlackMonkey这个一般就是Referer Referer:wukon…

TQ15EG开发板教程:使用SSH登录petalinux

本例程在上一章“创建运行petalinux2019.1”基础上进行&#xff0c;本例程将实现使用SSH登录petalinux。 将上一章生成的BOOT.BIN与imag.ub文件放入到SD卡中启动。给开发板插入电源与串口&#xff0c;注意串口插入后会识别出两个串口号&#xff0c;都需要打开&#xff0c;查看串…

windos系统安装-mysql 5.7 zip压缩包教程

一, 安装包下载 在mysql官网上下载mysql5.7版本的压缩包 官方网址: https://dev.mysql.com/downloads/mysql/5.7.html#downloads选择历史版本 选择系统和数据库版本下载 下载完成后解压到安装的目录 二, 新增数据目录,配置文件, 配置环境变量 新建data文件夹用于存放数据库…

js 获取屏幕高度和宽度的几种方式

1、document.documentElement.clientHeight 屏幕可视区域高度&#xff0c;文档的根元素&#xff08;通常是 <html> 元素&#xff09;的高度&#xff0c;但会受到CSS样式的影响。 实际应用&#xff1a;对于H5的移动端&#xff0c;希望video元素在全屏状态下占满整个手机屏…

Tree-of-Counterfactual Prompting for Zero-Shot Stance Detection

论文地址&#xff1a;Tree-of-Counterfactual Prompting for Zero-Shot Stance Detection - ACL Anthologyhttps://aclanthology.org/2024.acl-long.49/ 1. 概述 立场检测被定义为对文本中立场态度的自动推断。根据 Biber 和 Finegan (1988) 的定义&#xff0c;立场包含两个主…