快捷鍵
我們電腦中的記事本中還支持快捷鍵,如
“CTRL+O”打開文件、“CTRL+S”保存文件
在Qt中使用QShortcut這個類創建快捷鍵
在.cpp文件的構造函數中創建QShortcut對象,綁定打開文件和保存文件的槽函數
放大縮小字體
還是在.cpp的構造函數中編寫代碼
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);this->setLayout(ui->verticalLayout);ui->widget_2->setLayout(ui->horizontalLayout_2);connect(ui->comboBox,SIGNAL(currentIndexChanged(int)),this,SLOT(oncurrentIndex(int)));connect(ui->textEdit,SIGNAL(cursorPositionChanged()),this,SLOT(oncursorPosition()));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_Bopen_clicked();}); //綁定信號與槽(指針)connect(shortcutSave,&QShortcut::activated,[=](){on_Bsave_clicked();});QShortcut *shortcutZoomBig=new QShortcut(QKeySequence(tr("Ctrl+Shift+=","File|Save")),this); //ctrl、shift、+號同時按下(+與=在同一個位置)QShortcut *shortcutZoomSmall=new QShortcut(QKeySequence(tr("Ctrl+Shift+-","File|Save")),this); connect(shortcutZoomBig,&QShortcut::activated,[=](){QFont font = ui->textEdit->font(); //獲取當前字體信息int fontSize = font.pointSize(); //獲取當前字體大小if(fontSize==-1) return;int newfontSize=fontSize+1; //改變字體大小font.setPointSize(newfontSize); //設置新字體大小ui->textEdit->setFont(font);}); connect(shortcutZoomSmall,&QShortcut::activated,[=](){QFont font = ui->textEdit->font(); //獲取當前字體信息int fontSize = font.pointSize(); //獲取當前字體大小if(fontSize==-1) return;int newfontSize=fontSize-1; //改變字體大小font.setPointSize(newfontSize); //設置新字體大小ui->textEdit->setFont(font);});
}
事件處理
事件是 Qt 程序與用戶(或操作系統)交互的基本單元:用戶按下鼠標、鍵盤輸入、窗口被遮擋或暴露、定時器到期……都會產生一個 QEvent 對象。
過去我們常用“信號-槽”機制來處理用戶動作,但信號-槽只能覆蓋 Qt 已定義好的“高層語義”,遇到“關閉窗口時詢問是否保存”“拖拽窗口時限制范圍”這類底層或組合行為,就必須介入真正的事件處理流程。
在 Qt 中,事件處理分為四個連貫的步驟:
事件派發(dispatch):
QApplication::notify()
把事件發給目標對象;事件過濾(filter):沿途的所有
QObject::eventFilter()
都有機會截斷或修改事件;事件分發(delivery):目標對象內部的
QWidget::event()
根據事件類型再細分;事件處理(handle):具體虛函數如
mousePressEvent()
、closeEvent()
最終被執行。
在Qwidget中的保護成員中,還有如下這些事件處理函數,如closeEvent()可以關閉窗口,我們重寫事件處理函數也可以在一定程度上處理事件。
事件重寫
我們再來添加一個關閉窗口時的彈窗詢問
打開.h文件,聲明重寫closeEvent()事件處理函數(widget繼承于Qwidget)
同時按下“ALT+ENTER”,在.cpp文件中添加實現
void Widget::closeEvent(QCloseEvent *event) //記得添加頭文件
{int ret=QMessageBox::warning(this,tr("My Application"),tr("close the window.\n""Do you want to close the window?"),QMessageBox::Yes|QMessageBox::No); //彈窗switch (ret) {case QMessageBox::Yes:event->accept(); //QCloseEvent繼承于QEvent,accept接受事件,ignore忽略 break;case QMessageBox::No:event->ignore();break;}}
自定義按鍵
按鍵個性化設置
新建一個項目(同前),然后自定義一個按鈕
右鍵項目,點擊“Add New”
點擊“C++ Class”,點擊“choose”
繼承于QWidget,點擊“下一步”,點擊“完成”
需要在.h文件中聲明的成員如下
再次右鍵項目名稱,點擊“Add New”,添加一個Qt的資源文件
點擊“Add Files”,選擇3張圖片樣式添加(在項目文件下添加),“CTRL+S”保存
在.cpp文件中實現重寫邏輯
右鍵復制圖片文件地址
#include "mybutton.h"#include <QPainter>MyButton::MyButton(QWidget *parent) : QWidget(parent)
{pic.load(":/p1.png"); //加載圖片(初始圖片)setFixedSize(pic.size()); //設置按鍵大小為圖片大小update(); //刷新,觸發paintEvent()
}void MyButton::mousePressEvent(QMouseEvent *event)
{pic.load(":/p3.png");update();
}void MyButton::leaveEvent(QEvent *event)
{pic.load(":/p1.png");update();
}void MyButton::enterEvent(QEvent *event)
{pic.load(":/p2.png");update();
}void MyButton::paintEvent(QPaintEvent *event)
{QPainter painter(this); //繪畫師painter.drawPixmap(rect(),pic); //繪制圖像(矩形,位圖)}
打開.ui文件,托入一個widget控件,右鍵,點擊“提升為”
輸入新按鈕的類的名稱,點擊“添加”
點擊運行文件,按鈕圖標能正常轉換
這樣自定義后按鍵的形狀就能隨自己設計,更好看一些(可以用圖片等)
自定義按鍵的信號與槽
在"button.h"文件中聲明點擊信號
在widget.cpp中引入button的頭文件
connect綁定信號與槽
并在button.cpp文件,在鼠標信號點擊處,發送點擊信號
點擊“打開”按鈕后,能正常發射信號
事件重寫實現滾輪放大縮小字體
標準的QTextEdit控件并不支持“CTAL+鼠標滾輪”,所以我們要自定義一個MyTextEdit出來,再將notebook原來的textEdit提升為我們自定義的textEdit類(原代碼.c文件不用修改,都是繼承于QtextEdit實現)
右鍵項目名稱,新建一個類文件
標注父控件
在我們的MyTextEdit構造時還需標注父控件,使MyTextEdit與ui中的TextEdit聯系起來(ui中所有控件都有QWidget這個父親)
“ALT+ENTER”添加構造函數的實現(把原來的刪掉)
MyTextEdit::MyTextEdit(QWidget *parent):QTextEdit(parent) //調用QtextEdit的構造函數實現
{}
再在.h文件中聲明要實現的功能
#ifndef MYTEXTEDIT_H
#define MYTEXTEDIT_H#include <QTextEdit>class MyTextEdit : public QTextEdit
{
public:MyTextEdit(QWidget *parent);protected:void wheelEvent(QWheelEvent *e) override; //鼠標滾輪事件void keyPressEvent(QKeyEvent *e) override; //按鍵按下事件void keyReleaseEvent(QKeyEvent *e) override; //按鍵松開事件
};#endif // MYTEXTEDIT_H
提升TextEdit
在ui中右鍵TextEdit,“提升為”
然后右邊可以看到已經提升過來了
代碼實現
放大和縮小字體的代碼與之前快捷鍵實現重復了,所以直接把之前那段代碼用函數封裝調用就好了
widget.h添加聲明
widget.cpp添加實現
使用事件函數基本的使用,我們已經能寫出大致框架,但我們要實現的應該是“CTRL+滾輪”實現,但滾輪能夠上下滑動
我們只要添加一個bool型的變量,使同時操作時再調用函數就可以了
以及除了同時按下,正常操作的反應要繼承下來
#include "mytextedit.h"#include <QCloseEvent>MyTextEdit::MyTextEdit(QWidget *parent):QTextEdit(parent) //調用QtextEdit的構造函數實現
{}void MyTextEdit::wheelEvent(QWheelEvent *e)
{if(ctrlKeyPressed==1){if(e->angleDelta().y()>0){ //上滑縮小zoomIn();}else if(e->angleDelta().y()<0){zoomOut();}e->accept(); //處理完畢}else{QTextEdit::wheelEvent(e); //正常執行QTextEdit的滾輪事件}
}void MyTextEdit::keyPressEvent(QKeyEvent *e)
{if(e->key()==Qt::Key_Control){ //Ctrl按下ctrlKeyPressed=1;}QTextEdit::keyPressEvent(e); //按鍵按下執行
}void MyTextEdit::keyReleaseEvent(QKeyEvent *e)
{if(e->key()==Qt::Key_Control){ //Ctrl釋放ctrlKeyPressed=0;}QTextEdit::keyReleaseEvent(e);
}
事件過濾器
對于Qt事件,我們主要把中重點放在事件處理和事件過濾
事件過濾器適用于:當你不想在修改子代碼的情況下改變事件的行為(如上面的情況不添加新的類)。可在事件到達目標對象之前進行攔截和處理
先在.h文件添加聲明
安裝事件過濾器
在事件過濾器中,我們既要檢測滾輪,又要檢測“Ctrl”是否被按下。若單使用QEvent事件,檢測滾輪會調用一次,檢測ctrl按下又會調用一次。則兩個事件不能同時被檢測,所以我們換種方式檢測滾輪。
bool Widget::eventFilter(QObject *watched, QEvent *event)
{if(event->type()==QEvent::Wheel){ //事件是滾輪事件if(QGuiApplication::keyboardModifiers()==Qt::ControlModifier){ //ctrl被按下QWheelEvent *weelEvent=dynamic_cast<QWheelEvent*>(event); //轉換類型if(weelEvent->angleDelta().y()>0){zoomIn();}else{zoomOut();}return true; //事件已執行}return false; //若ctrl沒被按下,事件繼續傳遞給目標對象}
}
至此,我們的記事本項目簡單完成!
下圖為up主老陳的總結
?