17.QT-event processing analysis, event filters, drag and drop events

Introduction to Qt Event Handling

  • The Qt platform converts system-generated messages into Qt events
  • A Qt event is a QEvent object
  • Qt events are used to describe actions that occur inside or outside the program
  • Any QObject object has the ability to handle events

The common event inheritance diagram of Qt is as follows:

 

 

  • QInputEvent: user input event
  • QDropEvent: User drag and drop event
  • QPaintEvent: events that describe the GUI drawing action of the operating system
  • QCloseEvent: user closes the window event
  • QTimerEvent: timer event

 

order of events

1. The Qt event is dispatched to the QWidget object immediately after it is generated

2. Event (QEvent*) in QWidget for event processing

3.event() calls different event handlers according to the event type

4. Send a predefined signal in Qt in the event handler

5. Call the slot function associated with the signal

 

Take button click as an example, as shown in the following figure:

 

 

QPushButton event handling summary

1. When the button is clicked, the mouse event will be triggered

2. Call the event(QEvent*) member function

3. Call the mouseReleaseEvent(QMouseEvent*) member function

4. Call the click() member function

5. Trigger signal SIGNAL(clicked()) ;

 

Similarly, when the user clicks the close button of the window, the closeEvent() event function will also be triggered, which needs to be rewritten to achieve

Reference example:

 void MainWindow::closeEvent(QCloseEvent *event)
{
     if (maybeSave())                         // If there is still data to save 
{ writeSettings(); event->accept(); }
else // Cancel closing the window { event->ignore(); } }

Similar to keyEvent() to get keyboard event function, keyReleaseEvent() to keyboard press event function, enterEvent cursor to enter component event function, leaveEvent cursor to leave component event function and so on.

 

Among them, QCloseEvent inherits from QEvent, and the commonly used member functions in QEvent are

void   accept ();     // The receiver handles the current event

void   ignore ();     // The receiver ignores the current event, after ignoring, the event may be passed to the parent component

bool isAccepted();   // Determine whether the current event has been processed

 

When using ignore() to handle an event, the event may be passed to its parent component object to continue processing

Proceed as follows:

  • Write two classes: QMyWidget, QMyLineEdit (QMyLineEdit is a class member of QMyWidget)
  • Rewrite LineEdit's keyReleaseEvent() keyboard press event function through QMyLineEdit
  • Rewrite QWidget's keyReleaseEvent() keyboard press event function through QMyWidget
  • Then handle the keyReleaseEvent() event function of QMyLineEdit through ignore()
  • Determine whether the keyReleaseEvent() event function of the parent component of QMyWidget will continue to be executed

QLineEdit.h looks like this:

#ifndef QMYLINEEDIT_H
#define QMYLINEEDIT_H

#include <QLineEdit>
#include <QtGui>

class QMyLineEdit : public QLineEdit
{
    Q_OBJECT

public:
    explicit QMyLineEdit(QWidget *parent = 0);

    void  keyReleaseEvent( QKeyEvent * event );
};
#endif // QMYLINEEDIT_H

 

QLineEdit.cpp如下所示:

#include "QMyLineEdit.h"

QMyLineEdit::QMyLineEdit(QWidget *parent) :
    QLineEdit(parent)
{
}
void QMyLineEdit::keyReleaseEvent( QKeyEvent * event ) { qDebug()<<"QMyLineEdit::keyReleaseEvent"; qDebug()<<"key value:"<< event->key(); event->ignore(); //忽略当前事件 }

 

QMyWidget.h如下所示:

#ifndef QMYWIDGET_H
#define QMYWIDGET_H

#include "QMyLineEdit.h"
#include <QWidget>

class QMyWidget : public QWidget
{
    Q_OBJECT
    QMyLineEdit line;

public:
    explicit QMyWidget(QWidget *parent = 0);
    void   keyReleaseEvent( QKeyEvent * event );

};

#endif // QMYWIDGET_H

 

QMyWidget.cpp如下所示:

#include "QMyWidget.h"

QMyWidget::QMyWidget(QWidget *parent) :
    QWidget(parent),
    line(this)
{
}

void  QMyWidget::keyReleaseEvent( QKeyEvent * event )
{
    qDebug()<<"QMyWidget::keyReleaseEvent";
    qDebug()<<"key value:"<< event->key();

    QWidget::keyPressEvent(event);
}

 

main()函数如下所示:

int main(int argc, char *argv[])
{
        QApplication a(argc, argv);

        QMyWidget w;

        w.show();

        return a.exec();
}

效果如下:

 

可以看到成员调用了event->ignore()函数忽略事件后,同样也会继续进入QMyWidget类处理事件 

 

Qt中的事件过滤器

  • 事件过滤器可以对需要的组件接收到的事件进行过滤,以及监控
  • 任意的QObject对象都可以作为事件过滤器使用
  • 事件过滤器的实现,需要重写eventFilter()函数
  • 组件要想被监控,则需要通过installEventFilter()安装事件过滤器
  • 事件过滤器能够决定是否将事件转发给组件对象,如下图所示:

 

eventFilter函数体如下所示:

bool QObject::eventFilter ( QObject * watched, QEvent * event );
       // watched:代表被监控的组件  event:代表要转发的事件
       //返回true,表示该事件也被过滤掉(处理),无需再转发了
       //返回false,则正常转发给watched

 

参考示例-实现文本框只允许输入数字:

class MainWindow : public QMainWindow
 {
 public:
     MainWindow();

 protected:
     bool eventFilter(QObject *obj, QEvent *ev);

 private:
     QTextEdit *textEdit;
 };

MainWindow::MainWindow() { textEdit
= new QTextEdit; setCentralWidget(textEdit); textEdit->setAttribute(Qt::WA_InputMethodEnabled, false); //禁止中文输入法 textEdit->installEventFilter(this); } bool MainWindow::eventFilter(QObject *obj, QEvent *event) { if (obj == textEdit) { if (event->type() == QEvent::KeyPress) { QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event); qDebug() << "Ate key press" << keyEvent->key(); switch(keyEvent->key()) //只接受0~9数字 { case Qt::Key_0: case Qt::Key_1: case Qt::Key_2: case Qt::Key_3: case Qt::Key_4: case Qt::Key_5: case Qt::Key_6: case Qt::Key_7: case Qt::Key_8: case Qt::Key_9: return false; default: return true; } } else { return false; } } else { return QMainWindow::eventFilter(obj, event); } }

 

用户拖放事件

每个QWidget对象都能处理拖放事件

常用的拖放事件相关函数有:

void  dragEnterEvent ( QDragEnterEvent * event );  //拖事件处理函数
void dropEvent ( QDropEvent * event ) ;           //放事件处理函数 

 

拖放事件所处理的数据是QMimeData类

MIME类型常用处理函数如下所示:

 

拖放事件的步骤如下:

1.在构造函数里通过setAcceptDrops(true)函数,让该组件能接受拖放事件

2.重写dragEnterEvent(QDragEnterEvent* event)函数并判断MIME类型

  如果是期待的类型,则调用event ->acceptProposedAction();

  否则调用 : event ->ignore();

3.重写dropEvent()函数并判断MIME类型

  如果是期待的类型,则获取MIME数据并处理.

  否则调用 : event ->ignore();

 

示例:

 class MainWindow : public QMainWindow
 {
private:
    QTextEdit *textEdit;
    void dragEnterEvent(QDragEnterEvent *event);
    void dropEvent(QDropEvent *event);

public:
    MainWindow();
 };

 MainWindow::MainWindow()
 {
     textEdit = new QTextEdit;
     setCentralWidget(textEdit);
     textEdit->setAttribute(Qt::WA_InputMethodEnabled, false) ;
     textEdit->installEventFilter(this);
     this->setAcceptDrops(true);
 }

void MainWindow::dragEnterEvent(QDragEnterEvent *event)
{
      if(event->mimeData()->hasUrls())      //判断拖的类型
      {
            event->acceptProposedAction();
      }
      else
      {
            event->ignore();
      }
}

void MainWindow::dropEvent(QDropEvent *event)
{
    if(event->mimeData()->hasUrls())        //判断放的类型
    {
        textEdit->clear();
        QList<QUrl> List = event->mimeData()->urls();

        for(int i=0;i<List.length();i++)
        {
            textEdit->insertPlainText(List[i].toLocalFile()+"\n");
        }
    }
    else
    {
          event->ignore();
    }
}

效果:

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325354920&siteId=291194637