【QT】事件系統入門——QEvent 基礎與示例

一、事件介紹

事件是 應用程序內部或者外部產生的事情或者動作的統稱

  • 在 Qt 中使用一個對象來表示一個事件。所有的 Qt 事件均繼承于抽象類 QEvent。
  • 事件是由系統或者 Qt 平臺本身在不同的時刻發出的。
  • 當用戶按下鼠標、敲下鍵盤,或者是窗口需要重新繪制的時候,都會發出一個相應的事件。
  • 一些事件是在用戶操作時發出,如鍵盤事件、鼠標事件等,另一些事件則是由系統本身自動發出,如定時器事件。

事件本身是 操作系統提供的 機制,Qt 也同樣把操作系統事件機制進行了封裝拿到了 Qt 中,但由于 事件 對應的代碼編寫起來不方便,因此 Qt 對于事件機制 又進行了進一步的 封裝,就得到了 信號槽

常見的 QT 事件如下:

image-20250128131332619

不同場景下,要關注的點不一樣。這些事件的子類中就會包含一些對應的不同屬性。

常見事件描述:

從圖片中提取的文字信息如下表所示:

事件名稱描述
鼠標事件鼠標左鍵、鼠標右鍵、鼠標滾輪,鼠標的移動,鼠標按鍵的按下和松開
鍵盤事件按鍵類型、按鍵按下、按鍵松開
定時器事件定時時間到達
進入離開事件鼠標的進入和離開
滾輪事件鼠標滾輪滾動
繪屏事件重繪屏幕的某些部分
顯示隱藏事件窗口的顯示和隱藏
移動事件窗口位置的變化
窗口事件是否為當前窗口
大小改變事件窗口大小改變
焦點事件鍵盤焦點移動
拖拽事件用鼠標進行拖拽

二、事件的處理

事件處理一般常用的方法為:重寫相關的 Event 函數。

在 Qt 中,幾乎所有的 Event 函數都是虛函數,所以可以重新實現。

比如:在實現鼠標的進入和離開事件時,直接重新實現 enterEvent()leaveEvent() 即可。enterEvent()leaveEvent() 函數原型如下:
img

🐇標簽提升 & 演示

1)新建 Qt 項目

基類選擇 QWidget,同時勾選 UI 界面文件,并且設計 UI 文件,如下:

image-20250129160200592

  • 有了邊框,方便觀察當前鼠標是否進入和離開

這里我們還需要創建 QLabel 子類,來重寫 enterEventleaveEvent

2)在項目中新添加一個類

先選中項目名稱 QEvent,點擊鼠標右鍵,選擇 add new … ,彈出如下對話框:

img

3)定義類名并選擇基類

image-20250129160800887

4)此時項目中會新添加以下兩個文件

img

5)修改基類,重寫 enterEvent()leaveEvent

如果我們想了解這兩個函數,則可以在 幫助文檔 中查找對應的內容

  • 要想重寫父類的函數就需要確保寫的函數名字和函數的參數列表完全一致(形參名無所謂)。
  • 然后對這兩個函數進行重寫

label.hlabel.cpp 代碼如下:

image-20250129161706755

但是當前代碼還是有問題的,如下:

image-20250129163141755

  • 在 UI 文件中我們可以看到當前在界面上創建的這個 Label 并不是自己寫的 Label,而是 QLabel
  • 但是我們需要確保界面上的這個 Label 是自己定義的 Label 類實例才會被執行,因此需要 提升

6)在 UI 文件中選中 Label,右鍵 ——> 提升為…,點擊之后彈出如下:

image-20250129161405787

  • 這里需要確保這里填寫的類名以及頭文件 和 上述自定義的 類名頭文件 匹配

💡 通過 “提升為…” 這樣的方式就可以把 Qt Designer 中托上去的控件的類型轉換成自定義的控件類型,如下:

img

7)執行效果

當鼠標進入設計好的標簽之后,就會在應用程序輸出欄中打印:enterEvent;鼠標移出設計好的標簽之后,就會在應用程序輸出欄中打印:leaveEvent

image-20250129163712359

  • 這個時候就說明當前的 enterEventleaveEvent 這兩個事件就被我們給捕獲到了。

🐇 示例 – 當鼠標點擊時,獲取對應的坐標值

該示例主要基于上面代碼,實現:當鼠標點擊時,獲取對應的坐標值

void Label::mousePressEvent(QMouseEvent *event)
{if (event->button() == Qt::LeftButton) {qDebug() << "按下左鍵";} else if (event->button() == Qt::RightButton) {qDebug() << "按下右鍵";}// 當前 event 對象就包含了鼠標點擊位置的坐標.qDebug() << event->x() << ", " << event->y();// globalX 和 globalY 是以屏幕左上角為原點, 獲取的坐標.qDebug() << event->globalX() << ", " << event->globalY();
}

實現效果如下:

img

  • 我們這里就通過事件 獲取到 鼠標點擊 的位置
  • mouseEvent 這個函數 其實按左鍵、右鍵、滾輪都可以觸發的,甚至還有 前進 后退側鍵

三、鍵盤按鍵事件

  • Qt 中 QShortCut 是信號槽機制封裝過 獲取 鍵盤按鍵的 方式
  • 當然我們也可以從更底層角度,通過事件獲取到當前用戶鍵盤按下情況

Qt 中的按鍵事件是通過 QKeyEvent 類來實現的。當鍵盤上的按鍵被按下或者被釋放時,鍵盤事件便會觸發。

在幫助文檔中查找 QKeyEvent 類,然后查找按鍵事件中所有的按鍵類型:在幫助文檔中輸入:Qt::Key,如下圖:

img

1. 單個按鍵

示例:當某個按鍵被按下時,輸出:某個按鍵被按下了;

  1. 新建項目,在頭文件 “widget.h” 中聲明虛函數 keyPressEvent();
  2. 然后重寫 keyPressEvent() 虛函數,如下圖

image-20250129202354185

2. 組合按鍵

在 Qt 助手中搜索:Qt::KeyboardModifier,如下圖示:

img

Qt::KeyboardModifier 中定義了在處理鍵盤事件時對應的修改鍵。

在 Qt 中,鍵盤事件可以與修改鍵以起使用,以實現一些復雜的交互操作。

KeyboardModifier 中修改鍵的具體描述如下:

修飾鍵類型描述
Qt::NoModifier無修改鍵
Qt::ShiftModifierShift 鍵
Qt::ControlModifierCtrl 鍵
Qt::AltModifierAlt 鍵
Qt::MetaModifierMeta鍵(在Windows上指Windows鍵,在macOS上指Command鍵)
Qt::KeypadModifier使用鍵盤上的數字鍵盤進行輸入時,Num Lock鍵處于打開狀態
Qt::GroupSwitchModifier用于在輸入法組之間切換

這些修飾鍵常用于編程中處理鍵盤事件,特別是在使用Qt框架開發跨平臺應用程序時。

代碼如下:

void Widget::keyPressEvent(QKeyEvent *event)
{if(event->key() == Qt::Key_A){qDebug() << "A 按鍵被按下";}if(event->modifiers() == Qt::ControlModifier && event->key() == Qt::Key_A){qDebug() << "Ctrl + A 按鍵被按下";}
}

四、鼠標事件

在 Qt 中,鼠標事件是用 QMouseEvent 類來實現的。當在窗口中按下鼠標或者移動鼠標時,都會產生鼠標事件。

  • 利用 QMouseEvent 類可以獲取鼠標的哪個鍵被按下了以及鼠標的當前位置等信息。

在 Qt 幫助文檔中查找 QMouseEvent 類如下圖示:

img

鼠標單擊 | 釋放 | 雙擊 | 移動 事件

① 在 Qt 中,鼠標按下是通過虛函數 mousePressEvent() 來捕獲的。mousePressEvent() 函數原型如下:

  • [ virtual protected] void QWidget:: mousePressEvent (QMouseEvent * event )

鼠標左右鍵及滾的表示如下:

  1. Qt::LeftButton 鼠標左鍵

  2. Qt::RightButton 鼠標右鍵

  3. Qt::MidButton 鼠標滾輪

void Label::mousePressEvent(QMouseEvent *event)
{if (event->button() == Qt::LeftButton) {qDebug() << "按下左鍵";} else if (event->button() == Qt::RightButton) {qDebug() << "按下右鍵";}
}

② 鼠標釋放事件是通過虛函數 mouseReleaseEvent() 來捕獲的。mouseReleaseEvent() 函數原型如下:

  • [ virtual protected] void QWidget:: mouseReleaseEvent (QMouseEvent * event )
void Label::mouseReleaseEvent(QMouseEvent *event)
{if (event->button() == Qt::LeftButton) {qDebug() << "釋放左鍵";} else if (event->button() == Qt::RightButton) {qDebug() << "釋放右鍵";}
}

③ 鼠標雙擊事件是通過虛函數:mouseDoubleClickEvent() 來實現的。mouseDoubleClickEvent() 函數原型如下:

  • [ virtual protected] void QWidget:: mouseDoubleClickEvent (QMouseEvent * event )
void Label::mouseDoubleClickEvent(QMouseEvent *event)
{if (event->button() == Qt::LeftButton) {qDebug() << "雙擊左鍵";} else if (event->button() == Qt::RightButton) {qDebug() << "雙擊右鍵";}
}

④ 鼠標移動事件是通過虛函數:mouseMoveEvent() 來實現的。同時為了實時捕獲鼠標位置信息,需要通過函數 setMouseTracking() 來追蹤鼠標的位置。mouseMoveEvent()函數原型如下:

  • [ virtual protected] void QWidget:: mouseMoveEvent (QMouseEvent * event )

setMouseTracking() 函數原型如下:

  • void setMouseTracking( bool enable )

說明:setMouseTracking() 函數默認是 false,需要設置為 true,才能實時捕獲鼠標位置信息。

否則只有當鼠標按下時才能捕獲其位置信息。
image-20250129172741229

  • 上面的操作其實和 二中說的標簽提升 那里一樣,可以仔細看看

最后演示結果如下:

image-20250129173003843

  • 這里演示的話,還是把實時捕捉關了,敏感太高不適合演示現象,我們這里坐標可以長按拖拽鼠標也可以顯示 鼠標位置信息
  • 我們這里重寫鼠標事件的操作都是放在 自定義的 Label 中完成的,此時只有鼠標在 Label 范圍內進行動作才能捕捉到
  • 當前也可以把其放到 Widget(Qwidget 子類) 來完成,此時鼠標在整個窗口都可以捕捉到

五、定時器

Qt 中在進行窗口程序的處理過程中,經常要周期性的執行某些操作,或者制作一些動畫效果,使用定時器就可以實現。

所謂 定時器就是在間隔一定時間后,去執行某一個任務

定時器在很多場景下都會使用到,如彈窗自動關閉之類的功能等。

Qt 中的定時器分為 QTimerEventQTimer 這 2 個類。

  • QTimerEvent 類用來描述一個定時器事件。
    • 在使用時需要通過 startTimer() 函數來開啟?個定時器,這個函數需要輸入一個以毫秒為單位的整數作為參數來表明設定的時間,它返回的整型值代表這個定時器。
    • 當定時器溢出時(即定時時間到達)就可以在 timerEvent() 函數中獲取該定時器的編號來進行相關操作。
  • QTimer 類來實現一個定時器,它提供了更高層次的編程接口,如:可以使用信號和槽,還可以設置只運行一次的定時器。

1. QTimerEvent 類

聯系前文:【QT】 控件 – 顯示類

在 UI 界面上放置一個 LCD Number 控件,讓其 10 秒數字不斷遞減到 0,相當于倒計時。

  1. 新建項目,在 UI 界面文件放置一個 LCD Number 控件,并且給定初始值為 10
  2. 在 “widget.h” 頭文件中聲明 timerEvent() 函數,并定義一個整型變量
  3. 在 “widget.cpp” 文件中重寫 timerEvent() 函數
#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);// 開啟定時器事件// 此處 timerId 是一個定時器的身份標識(類似于 Linux 中的文件描述符)timerId = this->startTimer(1000); // 這里 timerId 設為成員變量
}void Widget::timerEvent(QTimerEvent *event)
{// 如果一個程序中存在多個定時器 (startTimer 創建的定時器), 此時每個定時器都會觸發 timerEvent 函數.// 先判定一下這次觸發是否是想要的定時器觸發的.if (event->timerId() != this->timerId) {// 如果不是我們的定時器觸發的, 就直接忽略.// 當前程序中只有這一個定時器.return;}int value = ui->lcdNumber->intValue();if (value <= 0) {// 停止定時器this->killTimer(this->timerId);return;}value -= 1;ui->lcdNumber->display(value);
}
  • 此時運行程序就可以獲得我們想要的倒計時結果了

但是相比于 QTimer ,使用 timerEvent 還是要更加復雜一點,因為需要手動管理 timerId,需要區分整個函數調用是由哪個 timer 引起

2. QTimer 類

純代碼實現,無調用 ui

  • 實現基本的計時功能
  • 還實現了**【獲取系統日期及實時時間】**,如下:
#include "widget.h"
#include "ui_widget.h"#include <QVBoxLayout>
#include <QLabel>
#include <QTimer>
#include <QPushButton>
#include <QDateTime>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);QVBoxLayout *layout = new QVBoxLayout(this);// 創建控件QLabel *label = new QLabel("0");label->setStyleSheet("font-size: 50px; color: red;");QLabel *label_date = new QLabel("0");label_date->setStyleSheet("font-size: 50px; color: blue;");QPushButton *startBtn = new QPushButton("開始");QPushButton *stopBtn = new QPushButton("停止");// 按鈕布局QHBoxLayout *btnLayout = new QHBoxLayout;btnLayout->addWidget(startBtn);btnLayout->addWidget(stopBtn);// 主布局layout->addWidget(label, 0, Qt::AlignCenter);layout->addWidget(label_date, 0, Qt::AlignCenter);layout->addLayout(btnLayout);// 創建定時器和計數器QTimer *timer = new QTimer(this);// 連接信號與槽connect(timer, &QTimer::timeout, [=](){static int num=1;label->setText(QString::number(num++));});connect(timer, &QTimer::timeout, [=](){QString str=QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");label_date->setText(str);});connect(startBtn, &QPushButton::clicked, [=](){timer->start(1000);});connect(stopBtn, &QPushButton::clicked, [=]{timer->stop();});
}

結果如下:

image-20250129220136849

六、事件分發器

1. 概述

在 Qt 中,事件分發器(Event Dispatcher)是一個核心概念,用于處理 GUI 應用程序中的事件。

事件分發器負責 將事件從一個對象傳遞到另一個對象,直到事件被處理或被取消。

每個繼承自 QObject 類QObject 類 本身都可以在本類中 重寫 bool event(QEvent *e) 函數,來實現相關事件的捕獲和攔截。

2. 事件分發器工作原理

在 Qt 中,我們發送的事件是傳給了 QObject 對象的 event() 函數。

  • 所有的事件都會進入到這個函數里面,那么我們處理事件就要重寫這個 event() 函數。
  • event() 函數本身不會去處理事件,而是根據 事件類型(type值)調用不同的事件處理函數。事件分發器就是工作在應用程序向下分發事件的過程中,如下圖:

如上圖,事件分發器用于分發事件。在此過程中,事件分發器也可以做 攔截操作

  • 事件分發器主要是通過 bool event(QEvent *e) 函數來實現。其返回值為布爾類型,若為 true,代表攔截,不向下分發。
  • Qt 中的事件是封裝在 QEvent類 中,在 Qt 助手中輸入 QEvent 可以查看其所包括的事件類型,如下圖示:

image-20250128133052036

演示代碼如下:

void Widget::mousePressEvent(QMouseEvent *event)
{if(event->button() == Qt::LeftButton){qDebug() << "鼠標左鍵按下";}
}bool Widget::event(QEvent *ev)
{if(ev->type() == QEvent::MouseButtonPress){qDebug() << "Event 中鼠標被按下";return true; // 表示不向下分發}// 其他事件交給父類處理(默認)return QWidget::event(ev);
}

結果如下:

image-20250129220805361

當我們 return false 時,就會出現一下結果

image-20250129221037788

  • 單機鼠標右鍵,鼠標被按下
  • 單擊鼠標左鍵, event 函數和 mousePressEvent 函數交替觸發

七、事件過濾器

在 Qt 中,一個對象可能經常要查看或攔截另外一個對象的事件,如對話框想要攔截按鍵事件,不讓別的組件接收到,或者修改按鍵的默認值等。

  • 通過上面的學習,我們已經知道,Qt 創建了 QEvent 事件對象之后,會調用 QObjectevent() 函數 處理事件的分發。
  • 顯然,我們可以在 event() 函數中實現攔截的操作。由于 event() 函數是 protected 的,因此,需要繼承已有類。
  • 如果組件很多,就需要重寫很多個 event() 函數。這當然相當?煩,更不用說重寫 event() 函數還得小心一堆問題。好在 Qt 提供了另外一種機制來達到這一目的:事件過濾器

事件過濾器是在 應用程序 分發到 event 事件分發器 之前,再做一次更高級的攔截

img

事件過濾器的?般使用步驟:

  1. 安裝事件過濾器;
  2. 重寫事件過濾器函數:eventfilter()

【示例】:基于文章上面演示的 標簽提升 那的操作,在 "Label.cpp" 中代碼如下:

#include "label.h"
#include <QDebug>
#include <QMouseEvent>Label::Label(QWidget* parent): QLabel(parent)
{}void Label::mousePressEvent(QMouseEvent *event)
{QString str = QString("鼠標按下: x = %1, y = %2").arg(event->x()).arg(event->y());qDebug() << str.toUtf8().data();
}bool Label::event(QEvent *e)
{//如果是鼠標按下,在event事件分發時做攔截操作if (e->type() == QEvent::MouseButtonPress){QMouseEvent *event = static_cast<QMouseEvent *>(e);QString str = QString("Event函數中鼠標按下: x = %1, y = %2").arg(event->x()).arg(event->y());qDebug() << str.toUtf8().data();return true; //返回true,代表用戶自己處理,不向下分發}//其他事件交給父類處理return QLabel::event(e);
}

Widget.cpp 代碼如下:

#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
#include <QEvent>
#include <QMouseEvent>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);// 給 label 裝上事件過濾器 this;當前窗口安裝事件過濾器ui->label->installEventFilter(this);
}bool Widget::eventFilter(QObject *obj, QEvent *e)
{if(obj == ui->label) // 判斷控件{if(e->type() == QEvent::MouseButtonPress){QMouseEvent *event = static_cast<QMouseEvent *>(e);QString str = QString("事件過濾器中鼠標按下: x = %1, y = %2").arg(event->x()).arg(event->y());qDebug() << str.toUtf8().data();return true; // 返回true,代表用戶自己處理,不向下分發}}return QWidget::eventFilter(obj, e);
}
  • 注意書寫函數實現時,記得先聲明函數名

結果如下:

img

八、其他

  • moveEvent:窗口移動時觸發的事件
  • resizeEvent:窗口大小改變時觸發的事件

image-20250130163923426

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/72121.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/72121.shtml
英文地址,請注明出處:http://en.pswp.cn/web/72121.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

自然語言處理初學者指南

文章目錄 一、說明二、自然語言處理發展史2.1 最早的自然語言處理簡介2.2 歷史2.3 NLP 的早期工作 三、NLP的現代方法3.1 單詞編碼3.2 循環神經網絡3.3 強化學習3.4 深度學習 四、更進一步的方法 一、說明 對于初學者來說&#xff0c;自然語言處理的發展歷史非常有必要了解&am…

unittest vs pytest區別

unittest vs pytest 對比 ?unittest 像“手動擋汽車”&#xff1a;操作步驟多&#xff0c;規則嚴格&#xff0c;適合老司機。?pytest 像“自動擋汽車”&#xff1a;開起來輕松&#xff0c;功能強大&#xff0c;適合新手和高效開發。 區別點?unittest?&#xff08;你學過的&…

CT117E-M4 CubeMX與Keil5 MDK-ARM基礎配置

目錄 1.CubeMX構建項目 2.芯片時鐘配置 2.1 芯片引腳配置 2.2 時鐘樹配置 3.調試接口配置 4.項目管理器Project Manager配置 4.1 project 4.2 Code Generator 5. 生成代碼 6.MDK_ARM配置 6.1 編譯器選擇 ?6.2 調試器配置 7. 創建本地代碼文件夾 8. #include 路徑…

MySQL中有哪幾種鎖?

大家好&#xff0c;我是鋒哥。今天分享關于【MySQL中有哪幾種鎖&#xff1f;】面試題。希望對大家有幫助&#xff1b; MySQL中有哪幾種鎖&#xff1f; 1000道 互聯網大廠Java工程師 精選面試題-Java資源分享網 在MySQL中&#xff0c;鎖是用來控制并發訪問的機制&#xff0c;確…

MongoDB 和 Elasticsearch的區別、優缺點對比,以及選型建議

MongoDB 和 Elasticsearch 在存儲和搜索方面各有特點&#xff0c;適用于不同的場景。以下是它們的區別、優缺點對比&#xff0c;以及選型建議。 1. 概述 MongoDB&#xff1a;分布式 NoSQL 文檔數據庫&#xff0c;基于 BSON&#xff08;類似 JSON&#xff09;的文檔存儲&#x…

55.HarmonyOS NEXT 登錄模塊開發教程(九):部署與發布

溫馨提示&#xff1a;本篇博客的詳細代碼已發布到 git : https://gitcode.com/nutpi/HarmonyosNext 可以下載運行哦&#xff01; HarmonyOS NEXT 登錄模塊開發教程&#xff08;九&#xff09;&#xff1a;部署與發布 效果預覽 1. 引言 在前八篇教程中&#xff0c;我們介紹了H…

vue3實現跨頁面緩存

避免頻繁向后端發送請求,vue3中,可以用緩存機制,為了實現跨頁面緩存,可以把緩存放到localsotrage里面 關鍵代碼: const globalCache JSON.parse(localStorage.getItem(globalCache)) || {}; 然后加一個forceRefresh關鍵字, const fetchData async (forceRefresh false) …

c++類和對象(下篇)上

今天又重新回到c的學習中~在前兩篇博客中,我簡單的學習了類的定義,實例化,以及類中的默認成員函數.下篇是類和對象的收尾篇,在這篇中我將補充一下中篇所講的構造函數以及介紹一些類和對象的新知識.下面讓我們開始學習吧. 再談構造函數 在之前我們實現構造函數時,初始化成員變量…

深度學習 bert流程

Token IDs 在自然語言處理任務中&#xff0c;特別是使用預訓練模型如BERT時&#xff0c;文本首先通過一個分詞器&#xff08;例如 BertTokenizer&#xff09;轉換為一系列的token IDs。這些ID是每個詞或子詞單元在詞匯表&#xff08;包含漢字、英文單詞、標點符號&#xff09;…

PPT內視頻播放無法播放的原因及解決辦法

PPT內視頻無法播放&#xff0c;通常是視頻編解碼的問題。目前我遇到的常見的視頻編碼格式有H.264&#xff0c;H.265&#xff0c;VP9&#xff0c;AV1這4種。H.264編解碼的視頻&#xff0c;Windows原生系統可以直接播放&#xff0c;其他的視頻編碼格式需要安裝對應的視頻編解碼插…

星越L_行李艙空間拓展講解

目錄 1.儲物槽 2.底板蓋儲物空間 3.掛鉤 3.左側照明燈 4.第二排座椅放倒 1.儲物槽 使用鑰匙或者后備箱按鈕打開電動后備箱,左側儲物槽可儲藏物品。 2.底板蓋儲物空間 打開地板蓋,下方有儲物空間。并放置了隨車工具。 3.掛鉤 后備箱左右兩測各有一個掛鉤。

深度學習與大模型-矩陣

矩陣其實在我們的生活中也有很多應用&#xff0c;只是我們沒注意罷了。 1. 矩陣是什么&#xff1f; 簡單來說&#xff0c;矩陣就是一個長方形的數字表格。比如你有一個2行3列的矩陣&#xff0c;可以寫成這樣&#xff1a; 這個矩陣有2行3列&#xff0c;每個數字都有一個位置&a…

LuaJIT 學習(2)—— 使用 FFI 庫的幾個例子

文章目錄 介紹Motivating Example: Calling External C Functions例子&#xff1a;Lua 中調用 C 函數 Motivating Example: Using C Data StructuresAccessing Standard System FunctionsAccessing the zlib Compression LibraryDefining Metamethods for a C Type例子&#xf…

基于 FastText、dlib 和 CppJieba 的中文語義相似度計算實踐

在自然語言處理(NLP)領域,語義相似度計算是許多任務的核心,例如問答系統、文本檢索和推薦系統。然而,中文因缺乏顯式分詞和復雜的語義結構,實現高效的語義對比具有一定挑戰性。 本文將介紹如何結合 CppJieba(高效中文分詞工具)、FastText(詞向量模型)和 dlib(機器學…

HCIA-11.以太網鏈路聚合與交換機堆疊、集群

鏈路聚合背景 拓撲組網時為了高可用&#xff0c;需要網絡的冗余備份。但增加冗余容易后會出現環路&#xff0c;所以我們部署了STP協議來破除環路。 但是&#xff0c;根據實際業務的需要&#xff0c;為網絡不停的增加冗余是現實需要的一部分。 那么&#xff0c;為了讓網絡冗余…

Unity基于C#+UGUI解決方案,制作每日簽到系統(本地存儲簽到數據)

一、需求介紹:基于本地存儲系統制作一個每日簽到系統界面,相關簽到界面如下圖所示,點擊“簽到有禮”按鈕后就會跳轉到“每日登錄禮”這個界面,點擊“立即簽到”按鈕之后,按鈕就會置灰,而且按鈕的文字會變成“等待明日”。 二、制作界面顯示相關功能,需要在Unity中新建一…

AI本地部署

文檔加載&#xff08;Document Loading&#xff09;&#xff1a;從多種不同來源加載文檔。LangChain提供了100多種不同的文檔加載器&#xff0c;包括PDF在內的非結構化的數據、SQL在內的結構化的數據&#xff0c;以及Python、Java之類的代碼等? ?文本分割&#xff08;Splitti…

精準車型識別:視覺分析技術的力量

隨著智慧城市和智能交通系統的快速發展&#xff0c;車型識別檢測成為交通管理、安全監控和數據分析的關鍵技術之一。利用視覺分析的方式&#xff0c;我們可以高效、準確地檢測監控下的車輛類型、車牌信息及車流量&#xff0c;為城市交通管理提供有力支持。本文將從背景、技術實…

上下文微調(Contextual Fine-Tuning, CFT)提高大型語言模型(LLMs)在特定領域的學習和推理能力

大型語言模型(LLMs)在開放領域任務中表現出色,但在快速演變的專業領域(如醫學、金融)中面臨挑戰: 知識更新難題:傳統指令微調(Instruction Fine-Tuning, IFT)依賴顯式指令,難以適應動態知識。災難性遺忘:持續預訓練(Continued Pretraining, CPT)可能導致模型遺忘已…

在 LaTeX 中強制表格位于頁面頂部

在 LaTeX 中強制表格位于頁面頂部&#xff0c;可以通過以下 多種方法結合使用&#xff0c;按優先級推薦&#xff1a; 方法 1&#xff1a;使用 [!t] 位置限定符 原理&#xff1a;通過 [!t] 強制 LaTeX 優先將表格放置在頁面頂部&#xff08;Top&#xff09;&#xff0c;! 表示忽…