4.1、event()函数用法:捕获鼠标点击事件
boolevent(QEvent*event); // 重载 |
boolMyWidget::event(QEvent*event) { if(event->type()==QEvent::MouseButtonPress) { qDebug()<<"mousepress"; } returnQWidget::event(event); } |
event是总的消息处理,他会将消息分门别类抛出,如果重载之后不调用原有的处理方式,消息将被截断。event可以用来进行消息截断,而不是用来做具体工作。
event消息截断:
boolMyWidget::event(QEvent*event) { if(event->type()==QEvent::MouseButtonPress) { returntrue; } returnQWidget::event(event); } |
消息的种类有很多,都在event中处理会很麻烦,而每个消息都有自己的子类,我们只要重载它的子类事件就可以了。
消息处理流程:
QApplication先得到 à 具体的处理的处理窗口::event() à event()函数根据消息类型调用具体的虚函数
我们可以做:
1、 可以重载具体的虚函数来实现对消息的响应。
2、 可以重载event()函数用来处理或者截断消息。
4.2、鼠标事件:QMouseEvevt
4.2.1鼠标按下事件:mousePressEvent
voidmousePressEvent(QMouseEvent*); |
voidMyWidget::mousePressEvent(QMouseEvent*ev) { QPointpt=ev->pos(); qDebug()<<pt; //鼠标左键 if(ev->button()==Qt::LeftButton) { qDebug()<<"leftbutton"; } //shift键按下 if(ev->modifiers()==Qt::ShiftModifier) { qDebug()<<"shiftpress"; } //shift键按下Control键按下 if(ev->modifiers()==Qt::ControlModifier) { qDebug()<<"handl1"; return; } qDebug()<<"handl2"; } |
4.2.2鼠标释放事件:mouseReleaseEvent
voidmouseReleaseEvent(QMouseEvent*); |
voidMyWidget::mouseReleaseEvent(QMouseEvent*ev) { QPointpt=ev->pos(); qDebug()<<"mouseReleaseEvent"<<pt; } |
4.2.3鼠标移动事件:mouseMoveEvent
voidmouseMoveEvent(QMouseEvent*); |
voidMyWidget::mouseMoveEvent(QMouseEvent*ev) { QPointpt=ev->pos(); qDebug()<<"mouseMoveEvent"<<pt; } |
正常情况下鼠标移动事件只要在鼠标按下拖动的时候才会触发,要想在鼠标不按下的情况就触发鼠标的移动事件,则要在窗口的构造函数中增加下面的设置:
this->setMouseTracking(true); |
4.3键盘事件:QKeyEvent
4.3.1键盘按下事件:keyPressEvent
voidkeyPressEvent(QKeyEvent*); |
voidMyWidget::keyPressEvent(QKeyEvent*ev) { ev->modifiers(); qDebug()<<ev->key()<<(char)ev->key(); } |
4.3.2键盘释放事件:
voidkeyReleaseEvent(QKeyEvent*); |
voidMyWidget::keyPressEvent(QKeyEvent*ev) { ev->modifiers(); qDebug()<<ev->key()<<(char)ev->key(); } |
4.4鼠标与键盘的焦点问题
4.4.1鼠标的消息处理
同一时刻只有一个窗口处理鼠标事件,在构造函数中定义一个按钮,查看鼠标移动时坐标的变化。
鼠标停在谁上面就是谁处理。
4.4.2键盘的消息处理
4.4.2.1按钮的键盘焦点获取
哪个控件得到焦点,就由哪个控件来处理键盘消息。
按钮本身不接收键盘消息,所以如下设置是不通过的:
m_button->setFocus(); |
按钮获取键盘的焦点设置:
m_button->setDefault(true); |
通过在构造函数中增加按钮来并处理按钮点击事件来查看:
m_layout=newQVBoxLayout(this);
m_button=newQPushButton("OK",this); m_button1=newQPushButton("Quit",this); m_button->setDefault(true);
m_layout->addWidget(m_button); m_layout->addWidget(m_button1);
connect(m_button,SIGNAL(clicked()),this,SLOT(buttonclicked())); connect(m_button1,SIGNAL(clicked()),this,SLOT(buttonclicked())); |
voidMyWidget::buttonclicked() { QPushButton*button=(QPushButton*)sender(); qDebug()<<button->text(); } |
在槽函数中可以通过sender()函数来获取消息的发送者。按空格键过着Enter键触发按钮的点击事件。
4.4.2.2文本输入框的Enter消息处理
QLineEdit本身不处理Enter键盘消息,交由其父窗口处理。父窗口默认不会处理这个消息,可以自定义槽函数捕获Enter消息并处理。
m_lineEdit=newQLineEdit(this); connect(m_lineEdit,SIGNAL(returnPressed()),this,SLOT(lineEnter())); |
这种方式主窗体和控件都处理了这个Enter消息。
4.5两个控件同时处理一个消息
boolMyWidget::event(QEvent*event) { event->accept(); returnQWidget::event(event); } |
QEvent中有一个accept()函数,如下:
inlinevoidaccept(){m_accept=true;} |
消息在传递过程中,从一个对象传递到另一个对象,然后又接着往下传递,在传递的过程中消息带的参数都是QEvent *, 里面的m_accept表明消息是否有被处理。
通过调用父类的同名函数,我们可以把 Qt 的事件传递看成链状:如果子类没有处理这个事件,就会继续向其父类传递。Qt 的事件对象有两个函数:accept()和ignore()。正如它们的名字一样,前者用来告诉 Qt,这个类的事件处理函数想要处理这个事件;后者则告诉 Qt,这个类的事件处理函数不想要处理这个事件。在事件处理函数中,可以使用isAccepted()来查询这个事件是不是已经被接收了。具体来说:如果一个事件处理函数调用了一个事件对象的accept()函数,这个事件就不会被继续传播给其父组件;如果它调用了事件的ignore()函数,Qt 会从其父组件中寻找另外的接受者。
4.6常用窗体消息
4.6.1窗口关闭:closeEvent
voidcloseEvent(QCloseEvent*); |
voidMyWidget::closeEvent(QCloseEvent*ev) { qDebug()<<"close"; } |
4.6.2窗口显示:showEvent
voidshowEvent(QShowEvent*); |
voidMyWidget::showEvent(QShowEvent*ev) { qDebug()<<"show"; } |
4.6.3窗口隐藏:hideEvent
voidhideEvent(QHideEvent*); |
voidMyWidget::hideEvent(QHideEvent*ev) { qDebug()<<"hide"; } |
4.6.4窗口重回:paintEvent
voidpaintEvent(QPaintEvent*); |
voidMyWidget::paintEvent(QPaintEvent*ev) { QPainterp(this); p.drawLine(QPoint(0,0),QPoint(100,100)); } |
窗口在重绘结束后,会调用paintEvent事件,我们可以添加一些额外的东西在窗口上。