Qt-Focus事件处理,重写qpushbutton实现背景切换⿏标样式
及eventFil。。。
⽅法⼀:
描述:⼀开始我要实现的⽬的就是,在⼀个窗体上有多个可编辑控件(⽐如QLineEdit、QTextEdit等),当哪个控件获得焦点,哪个控件的背景就⾼亮⽤来起提⽰作⽤,查了下⽂档应该⽤focusInEvent()和focusOutEvent(), 在实际过程中,我犯了⼗分严重的错误,最开始的时候我是这样做的:我重写了窗体QWidget的这两个函数,然后再在函数体中把QFocusEvent事件传递给窗体上的QLineEdit控件:
void Widget::focusInEvent(QFocusEvent *event)
{
QLineEdit::focusInEvent(event);
.....
}
编译的时候报错,说是没有调⽤对象什么的,后来问了下朋友才得到了完美的答案:
既然是要控件得到焦点改变动作,则应该重写该控件的focusInEvent()和focusOutEvent(),即重写QLineEdit类,再重新定义这两个处理函数,然后再在主程序中,include 我们⾃⼰重写的QLineEdit头⽂件,具体代码如下:
// MYLINEEDIT_H
#ifndef MYLINEEDIT_H
#define MYLINEEDIT_H
#include <QLineEdit>
class MyLineEdit : public QLineEdit
{
Q_OBJECT
public:
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 对可编辑输⼊框有效,还有其他类型,具体的查看⽂档
setPalette(p);
}
void MyLineEdit::focusOutEvent(QFocusEvent *e)
{
QPalette p1=QPalette();
p1.setColor(QPalette::Base,Qt::white);
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);
}
⽅法⼆:
前⾯实现了QLineEdit获得焦点⾼亮显⽰与失去焦点恢复原样的操作,是通过重新继承该类,再重构该事件函数的⽅式。这⾥要实现的功能也是⼀样的,⽽是通过另外不同的⽅式——事件过滤器(eventFilter)。
Qt的事件模型中提供的事件过滤功能使得⼀个QObject对象可以监视另⼀个QObject对象中的事件,通过在⼀个QObject对象中安装事件过滤器可以在事件到达该对象前捕获事件,从⽽起到监视该对象事件的效果。
实现类似功能的另⼀种⽅式是通过分别继承不同的控件类,并重构各控件的事件响应函数,但若窗体中包含⼤量不同的控件时,每⼀个控件都必须重新继承,然后分别重构不同的事件函数,实现⽐较复杂。事件过滤器可以实现在窗体中监视全部控件的不同事件,⽅便实现功能扩展。
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
namespace Ui {
class Widget;
}
htmlradio添加切换事件class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
public slots:
bool eventFilter(QObject *,QEvent *); //注意这⾥
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
#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安装过滤器
ui->lineEdit2->installEventFilter(this); //在窗体上为lineEdit2安装过滤器
}
Widget::~Widget()
{
delete ui;
}
bool Widget::eventFilter(QObject *watched, QEvent *event)
{
if (watched==ui->lineEdit1) //⾸先判断控件(这⾥指 lineEdit1)
{
if (event->type()==QEvent::FocusIn) //然后再判断控件的具体事件 (这⾥指获得焦点事件)
{
QPalette p=QPalette();
p.setColor(QPalette::Base,Qt::green);
ui->lineEdit1->setPalette(p);
}
else if (event->type()==QEvent::FocusOut) // 这⾥指 lineEdit1 控件的失去焦点事件
{
QPalette p=QPalette();
p.setColor(QPalette::Base,Qt::white);
ui->lineEdit1->setPalette(p);
}
}
if (watched==ui->lineEdit2) //这⾥来处理 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); // 最后将事件交给上层对话框
}
另外,我在⼀本书上看到作者有⼀个例⼦是关于动态按钮的:⿏标未按下时没有任何反应,当⿏标左键按下时图⽚变⼤,松开⿏标后⼜恢复原来的状态。其实这个效果和我这个例⼦是⼀个道理,也就是监听按钮的按下事件(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)
{ // 更换⼀张⼤⼀点的图⽚ ..........
}
if (event->type()==QEvent::MouseButtonRelease)
{ // 重新换回最初那张图⽚ ...........
}
return QWidget::eventFilter(watched,event);
}
/**********************重写QPushbutton
设置⿏标样式不起作⽤的可能原因
⼀般在QT开发中,使⽤setCursor()给控件设置⿏标的样式效果(⼀般是⼿型和箭头的切换),⼀般情况下,这个函数也是起作⽤的,但是⼀旦调⽤了全局QApplication::setOverrideCursor()设置⿏标效果后,在使⽤setCursor给控件设置⿏标样式就不起效果了,这是QT的机制
解决思路
⽬前能想到的⼀种解决思路就是重写控件,并重写控件⿏标的相关事件,下⾯以重写QPushButton为例,当然代码是从⽹上的,Qt⾃定义按钮及不同状态下图⽚的切换,我参考该博客是为了实现按钮背景图⽚的切换,发现使⽤该博客,在我的电脑上会出现有的按钮进⼊时,会同时触发进⼊事件和离开事件,⽬前还不知道原因,所以就没使⽤该博客绘制按钮的图⽚,还是⽼⽼实实的使⽤setStyleSheet来设置按钮的背景图⽚的样式,以下是修改后的代码(注释的相关代码是设置背景图⽚的,我没有****⽤),这⾥还是感谢该博主提供的思路
头⽂件
#ifndef QTXPUSHBUTTON_H
#define QTXPUSHBUTTON_H
#include <QPushButton>
//有的按钮进⼊按钮时,会同时触发进⼊事件和离开事件,暂时不知道啥原因(BUG),图⽚样式使⽤样式表设置
//不在各个事件⾥设置图⽚,⽬前只⽤于设置⿏标样式
class QtXPushButton : public QPushButton
{
Q_OBJECT
public:
enum XBUTTONSTATE
{
NORMAL = 0X01,//正常状态
HOVER = 0X02,//⿏标滑过状态
SELECTED = 0X04,//选中状态
DISABLE = 0X08//禁⽌点击状态
};
QtXPushButton(QString strImagePath="", QWidget *parent = nullptr); ~QtXPushButton();
/
/设置正常图标
void SetNormalPixmap(QString strImagePath);
//设置⿏标滑动图⽚
void SetHoverPixmap(QString strImagePath);
//设置选中状态图⽚
void SetSelectedPixmap(QString strImagePath);
//设置禁⽌点击图标
void SetDisablePixmap(QString strImagePath);
//设置按钮当前状态
void SetBtnState(XBUTTONSTATE state);
//设置图⽚⼤⼩
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;//正常图标
QPixmap m_HoverPix;//⿏标滑动图标
QPixmap m_SelectedPix;//选中状态图标
QPixmap m_DisablePix;//禁⽌点击图标
//包含1则启动正常图标,包含2启⽤滑动图标,
//包含4启⽤选中状态图标,包含8启⽤禁⽌点击图标,默认标为1.
int m_iMask;
XBUTTONSTATE m_curState;//当前状态
XBUTTONSTATE m_lastState;//上⼀次状态
};
#endif // QTXPUSHBUTTON_H
cpp
#include <QBitmap>
#include <QPainter>
#include <QDebug>
#include <QStyleOption>
#include <QApplication>
#include "qtxpushbutton.h"
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论