Qt-Focus事件处理,重写qpushbutton实现背景切换鼠标样式及eventFilter的用法
方法一:
描述:一開(kāi)始我要實(shí)現(xiàn)的目的就是,在一個(gè)窗體上有多個(gè)可編輯控件(比如QLineEdit、QTextEdit等),當(dāng)哪個(gè)控件獲得焦點(diǎn),哪個(gè)控件的背景就高亮用來(lái)起提示作用,查了下文檔應(yīng)該用focusInEvent()和focusOutEvent(), 在實(shí)際過(guò)程中,我犯了十分嚴(yán)重的錯(cuò)誤,最開(kāi)始的時(shí)候我是這樣做的:我重寫(xiě)了窗體QWidget的這兩個(gè)函數(shù),然后再在函數(shù)體中把QFocusEvent事件傳遞給窗體上的QLineEdit控件:
void Widget::focusInEvent(QFocusEvent *event) {QLineEdit::focusInEvent(event);..... }編譯的時(shí)候報(bào)錯(cuò),說(shuō)是沒(méi)有調(diào)用對(duì)象什么的,后來(lái)問(wèn)了下朋友才得到了完美的答案:
既然是要控件得到焦點(diǎn)改變動(dòng)作,則應(yīng)該重寫(xiě)該控件的focusInEvent()和focusOutEvent(),即重寫(xiě)QLineEdit類(lèi),再重新定義這兩個(gè)處理函數(shù),然后再在主程序中,include 我們自己重寫(xiě)的QLineEdit頭文件,具體代碼如下:
// MYLINEEDIT_H #ifndef MYLINEEDIT_H #define MYLINEEDIT_H #include <QLineEdit> class MyLineEdit : public QLineEdit {Q_OBJECTpublic:MyLineEdit(QWidget *parent=0);~MyLineEdit();protected:virtual void focusInEvent(QFocusEvent *e);virtual void focusOutEvent(QFocusEvent *e); }; #endif // MYLINEEDIT_H `//myLineEdit.cpp #include "myLineEdit.h"MyLineEdit::MyLineEdit(QWidget *parent):QLineEdit(parent) {}MyLineEdit::~MyLineEdit() {}void MyLineEdit::focusInEvent(QFocusEvent *e) {QPalette p=QPalette();p.setColor(QPalette::Base,Qt::green); //QPalette::Base 對(duì)可編輯輸入框有效,還有其他類(lèi)型,具體的查看文檔setPalette(p); }void MyLineEdit::focusOutEvent(QFocusEvent *e) {QPalette p1=QPalette();p1.setColor(QPalette::Base,Qt::white);setPalette(p1); }//widget.cpp #include "widget.h" #include "ui_widget.h" #include "MyLineEdit.h" #include <QGridLayout> #include <QMessageBox> Widget::Widget(QWidget *parent) :QWidget(parent),ui(new Ui::Widget) {ui->setupUi(this);init(); } Widget::~Widget() {delete ui; } void Widget::init() {lineEdit1=new MyLineEdit(this);lineEdit2=new MyLineEdit(this);gridLayout=new QGridLayout;gridLayout->addWidget(lineEdit1,0,0);gridLayout->addWidget(lineEdit2,1,0);setLayout(gridLayout); }方法二:
前面實(shí)現(xiàn)了QLineEdit獲得焦點(diǎn)高亮顯示與失去焦點(diǎn)恢復(fù)原樣的操作,是通過(guò)重新繼承該類(lèi),再重構(gòu)該事件函數(shù)的方式。這里要實(shí)現(xiàn)的功能也是一樣的,而是通過(guò)另外不同的方式——事件過(guò)濾器(eventFilter)。
Qt的事件模型中提供的事件過(guò)濾功能使得一個(gè)QObject對(duì)象可以監(jiān)視另一個(gè)QObject對(duì)象中的事件,通過(guò)在一個(gè)QObject對(duì)象中安裝事件過(guò)濾器可以在事件到達(dá)該對(duì)象前捕獲事件,從而起到監(jiān)視該對(duì)象事件的效果。
實(shí)現(xiàn)類(lèi)似功能的另一種方式是通過(guò)分別繼承不同的控件類(lèi),并重構(gòu)各控件的事件響應(yīng)函數(shù),但若窗體中包含大量不同的控件時(shí),每一個(gè)控件都必須重新繼承,然后分別重構(gòu)不同的事件函數(shù),實(shí)現(xiàn)比較復(fù)雜。事件過(guò)濾器可以實(shí)現(xiàn)在窗體中監(jiān)視全部控件的不同事件,方便實(shí)現(xiàn)功能擴(kuò)展。
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> namespace Ui { class Widget; } class Widget : public QWidget {Q_OBJECTpublic:explicit Widget(QWidget *parent = 0);~Widget();public slots:bool eventFilter(QObject *,QEvent *); //注意這里private:Ui::Widget *ui; }; #endif // WIDGET_H `#include "widget.h" #include "ui_widget.h" #include <QPalette> Widget::Widget(QWidget *parent) :QWidget(parent),ui(new Ui::Widget) {ui->setupUi(this);ui->lineEdit1->installEventFilter(this); //在窗體上為lineEdit1安裝過(guò)濾器ui->lineEdit2->installEventFilter(this); //在窗體上為lineEdit2安裝過(guò)濾器 }Widget::~Widget() {delete ui; }bool Widget::eventFilter(QObject *watched, QEvent *event) {if (watched==ui->lineEdit1) //首先判斷控件(這里指 lineEdit1){if (event->type()==QEvent::FocusIn) //然后再判斷控件的具體事件 (這里指獲得焦點(diǎn)事件){QPalette p=QPalette();p.setColor(QPalette::Base,Qt::green);ui->lineEdit1->setPalette(p);}else if (event->type()==QEvent::FocusOut) // 這里指 lineEdit1 控件的失去焦點(diǎn)事件{QPalette p=QPalette();p.setColor(QPalette::Base,Qt::white);ui->lineEdit1->setPalette(p);}}if (watched==ui->lineEdit2) //這里來(lái)處理 lineEdit2 , 和處理lineEdit1 是一樣的{if (event->type()==QEvent::FocusIn){QPalette p=QPalette();p.setColor(QPalette::Base,Qt::green);ui->lineEdit2->setPalette(p);}else if (event->type()==QEvent::FocusOut){QPalette p=QPalette();p.setColor(QPalette::Base,Qt::white);ui->lineEdit2->setPalette(p);}}return QWidget::eventFilter(watched,event); // 最后將事件交給上層對(duì)話(huà)框 }另外,我在一本書(shū)上看到作者有一個(gè)例子是關(guān)于動(dòng)態(tài)按鈕的:鼠標(biāo)未按下時(shí)沒(méi)有任何反應(yīng),當(dāng)鼠標(biāo)左鍵按下時(shí)圖片變大,松開(kāi)鼠標(biāo)后又恢復(fù)原來(lái)的狀態(tài)。其實(shí)這個(gè)效果和我這個(gè)例子是一個(gè)道理,也就是監(jiān)聽(tīng)按鈕的按下事件(QEvent::MouseButtonPress)和釋放事件(QEvent::MouseButtonRelease)
bool EventFilter::eventFilter(QObject *watched,QEvent *event) {if (watched==Label1){if (event->type()==QEvent::MouseButtonPress){QMouseEvent *mouseEvent=static_cast<QMouseEvent *>event;if (mouseEvent->buttons() && Qt::LeftButton){ // 更換一張大一點(diǎn)的圖片 ..........}if (event->type()==QEvent::MouseButtonRelease){ // 重新?lián)Q回最初那張圖片 ...........}return QWidget::eventFilter(watched,event); }/**********************重寫(xiě)QPushbutton
設(shè)置鼠標(biāo)樣式不起作用的可能原因
一般在QT開(kāi)發(fā)中,使用setCursor()給控件設(shè)置鼠標(biāo)的樣式效果(一般是手型和箭頭的切換),一般情況下,這個(gè)函數(shù)也是起作用的,但是一旦調(diào)用了全局QApplication::setOverrideCursor()設(shè)置鼠標(biāo)效果后,在使用setCursor給控件設(shè)置鼠標(biāo)樣式就不起效果了,這是QT的機(jī)制
解決思路
目前能想到的一種解決思路就是重寫(xiě)控件,并重寫(xiě)控件鼠標(biāo)的相關(guān)事件,下面以重寫(xiě)QPushButton為例,當(dāng)然代碼是從網(wǎng)上找的,Qt自定義按鈕及不同狀態(tài)下圖片的切換,我參考該博客是為了實(shí)現(xiàn)按鈕背景圖片的切換,發(fā)現(xiàn)使用該博客,在我的電腦上會(huì)出現(xiàn)有的按鈕進(jìn)入時(shí),會(huì)同時(shí)觸發(fā)進(jìn)入事件和離開(kāi)事件,目前還不知道原因,所以就沒(méi)使用該博客繪制按鈕的圖片,還是老老實(shí)實(shí)的使用setStyleSheet來(lái)設(shè)置按鈕的背景圖片的樣式,以下是修改后的代碼(注釋的相關(guān)代碼是設(shè)置背景圖片的,我沒(méi)有****用),這里還是感謝該博主提供的思路
頭文件
#ifndef QTXPUSHBUTTON_H
#define QTXPUSHBUTTON_H
#include <QPushButton>
//有的按鈕進(jìn)入按鈕時(shí),會(huì)同時(shí)觸發(fā)進(jìn)入事件和離開(kāi)事件,暫時(shí)不知道啥原因(BUG),圖片樣式使用樣式表設(shè)置
//不在各個(gè)事件里設(shè)置圖片,目前只用于設(shè)置鼠標(biāo)樣式
class QtXPushButton : public QPushButton
{
? ? Q_OBJECT
public:
? ? enum XBUTTONSTATE
? ? {
? ? ? ? NORMAL = 0X01,//正常狀態(tài)
? ? ? ? HOVER = 0X02,//鼠標(biāo)滑過(guò)狀態(tài)
? ? ? ? SELECTED = 0X04,//選中狀態(tài)
? ? ? ? DISABLE = 0X08//禁止點(diǎn)擊狀態(tài)
? ? };
? ? QtXPushButton(QString strImagePath="", QWidget *parent = nullptr);
? ? ~QtXPushButton();
? ? //設(shè)置正常圖標(biāo)
? ? void SetNormalPixmap(QString strImagePath);
? ? //設(shè)置鼠標(biāo)滑動(dòng)圖片
? ? void SetHoverPixmap(QString strImagePath);
? ? //設(shè)置選中狀態(tài)圖片
? ? void SetSelectedPixmap(QString strImagePath);
? ? //設(shè)置禁止點(diǎn)擊圖標(biāo)
? ? void SetDisablePixmap(QString strImagePath);
? ? //設(shè)置按鈕當(dāng)前狀態(tài)
? ? void SetBtnState(XBUTTONSTATE state);
? ? //設(shè)置圖片大小
? ? void SetSize(QSize sz);
protected:
? ? virtual void paintEvent(QPaintEvent *event);
? ? virtual void enterEvent(QEvent *event);
? ? virtual void mouseReleaseEvent(QMouseEvent *event);
? ? virtual void mousePressEvent(QMouseEvent *event);
? ? virtual void leaveEvent(QEvent *event);
private:
? ? QtXPushButton(const QtXPushButton& btn);
? ? QtXPushButton& operator=(const QtXPushButton& btn);
private:
? ? QPixmap m_NormalPix;//正常圖標(biāo)
? ? QPixmap m_HoverPix;//鼠標(biāo)滑動(dòng)圖標(biāo)
? ? QPixmap m_SelectedPix;//選中狀態(tài)圖標(biāo)
? ? QPixmap m_DisablePix;//禁止點(diǎn)擊圖標(biāo)
? ? //包含1則啟動(dòng)正常圖標(biāo),包含2啟用滑動(dòng)圖標(biāo),
? ? //包含4啟用選中狀態(tài)圖標(biāo),包含8啟用禁止點(diǎn)擊圖標(biāo),默認(rèn)標(biāo)為1.
? ? int m_iMask;
? ? XBUTTONSTATE m_curState;//當(dāng)前狀態(tài)
? ? XBUTTONSTATE m_lastState;//上一次狀態(tài)
};
#endif // QTXPUSHBUTTON_H
cpp
#include <QBitmap>
#include <QPainter>
#include <QDebug>
#include <QStyleOption>
#include <QApplication>
#include "qtxpushbutton.h"
QtXPushButton::QtXPushButton(QString strImagePath, QWidget *parent)
? ? :QPushButton(parent)
{
? ? // ? ?m_NormalPix.load(strImagePath);
? ? // ? ?setFixedSize(m_NormalPix.size());
? ? // ? ?setMask(QBitmap(m_NormalPix.mask()));
? ? // ? ?m_iMask = XBUTTONSTATE::NORMAL;
? ? // ? ?m_curState = XBUTTONSTATE::NORMAL;
? ? // ? ?m_lastState = XBUTTONSTATE::NORMAL;
}
QtXPushButton::~QtXPushButton()
{
}
void QtXPushButton::SetNormalPixmap(QString strImagePath)
{
? ? m_NormalPix.load(strImagePath);
? ? m_iMask |= XBUTTONSTATE::NORMAL;
}
void QtXPushButton::SetHoverPixmap(QString strImagePath)
{
? ? m_HoverPix.load(strImagePath);
? ? m_iMask |= XBUTTONSTATE::HOVER;
}
void QtXPushButton::SetSelectedPixmap(QString strImagePath)
{
? ? m_SelectedPix.load(strImagePath);
? ? m_iMask |= XBUTTONSTATE::SELECTED;
}
void QtXPushButton::SetDisablePixmap(QString strImagePath)
{
? ? m_DisablePix.load(strImagePath);
? ? m_iMask |= XBUTTONSTATE::DISABLE;
}
void QtXPushButton::SetBtnState(QtXPushButton::XBUTTONSTATE state)
{
? ? m_lastState = m_curState;
? ? m_curState = state;
}
void QtXPushButton::SetSize(QSize sz)
{
? ? m_NormalPix = m_NormalPix.scaled(sz);
? ? int iValue = m_iMask&XBUTTONSTATE::HOVER;
? ? if (iValue != 0)
? ? {
? ? ? ? m_HoverPix = m_HoverPix.scaled(sz);
? ? }
? ? iValue = m_iMask&XBUTTONSTATE::SELECTED;
? ? if (iValue != 0)
? ? {
? ? ? ? m_SelectedPix = m_SelectedPix.scaled(sz);
? ? }
? ? iValue = m_iMask&XBUTTONSTATE::DISABLE;
? ? if (iValue != 0)
? ? {
? ? ? ? m_DisablePix = m_DisablePix.scaled(sz);
? ? }
}
void QtXPushButton::paintEvent(QPaintEvent *event)
{
? ? //需要在paintEvent添加以下代碼,否則設(shè)置按鈕的樣式表不起效果
? ? QStyleOption o;
? ? o.initFrom(this);
? ? QPainter p(this);
? ? style()->drawPrimitive(QStyle::PE_Widget, &o, &p, this);
? ? // ? ?QPixmap drawPix;
? ? // ? ?if (m_curState == XBUTTONSTATE::NORMAL)
? ? // ? ?{
? ? // ? ? ? ?drawPix = m_NormalPix;
? ? // ? ?}
? ? // ? ?else if (m_curState == XBUTTONSTATE::HOVER)
? ? // ? ?{
? ? // ? ? ? ?int iValue = m_iMask&XBUTTONSTATE::HOVER;
? ? // ? ? ? ?drawPix = (0 == iValue) ? m_NormalPix : m_HoverPix;
? ? // ? ?}
? ? // ? ?else if (m_curState == XBUTTONSTATE::SELECTED)
? ? // ? ?{
? ? // ? ? ? ?int iValue = m_iMask&XBUTTONSTATE::SELECTED;
? ? // ? ? ? ?drawPix = (0 == iValue) ? m_NormalPix : m_SelectedPix;
? ? // ? ?}
? ? // ? ?else if (m_curState == XBUTTONSTATE::DISABLE)
? ? // ? ?{
? ? // ? ? ? ?int iValue = m_iMask&XBUTTONSTATE::DISABLE;
? ? // ? ? ? ?drawPix = (0 == iValue) ? m_NormalPix : m_DisablePix;
? ? // ? ?}
? ? // ? ?QPainter painter(this);
? ? // ? ?painter.drawPixmap(0, 0, drawPix);
}
void QtXPushButton::enterEvent(QEvent *event)
{
? ? QApplication::setOverrideCursor(Qt::PointingHandCursor);
? ? // ? ?SetBtnState(XBUTTONSTATE::HOVER);
? ? QPushButton::enterEvent(event);
? ? // ? ?update();
}
void QtXPushButton::mouseReleaseEvent(QMouseEvent *event)
{
? ? QApplication::setOverrideCursor(Qt::ArrowCursor);
? ? // ? ?m_curState =XBUTTONSTATE::NORMAL;
? ? QPushButton::mouseReleaseEvent(event);
? ? // ? ?update();
}
void QtXPushButton::mousePressEvent(QMouseEvent *event)
{
? ? QApplication::setOverrideCursor(Qt::PointingHandCursor);
? ? // ? SetBtnState(XBUTTONSTATE::SELECTED);
? ? QPushButton::mousePressEvent(event);
? ? // ? update();
}
void QtXPushButton::leaveEvent(QEvent *event)
{
? ? QApplication::setOverrideCursor(Qt::ArrowCursor);
? ? // ? ?m_curState =XBUTTONSTATE::NORMAL;
? ? QPushButton::leaveEvent(event);
? ? // ? ?update();
}
QtXPushButton &QtXPushButton::operator=(const QtXPushButton &btn)
{
? ? return *this;
}
?
總結(jié)
以上是生活随笔為你收集整理的Qt-Focus事件处理,重写qpushbutton实现背景切换鼠标样式及eventFilter的用法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: @JsonFormat Date类型时间
- 下一篇: Qt-qwidget项目入门实例