zoukankan      html  css  js  c++  java
  • Qt 自定义事件详细实例(继承QEvent,然后QCoreApplication::postEvent()、sendEvent())

    创建用户事件

    创建一个自定义类型的事件,首先需要有一个事件号,其值通常大于QEvent::User。
    为了传递事件信息,因此必须编写自定义的事件类,该事件类从QEvent继承。

        编写用户事件:
    编写用户事件类的方法是首先定义一个事件号。
    然后实现用户事件类,应用程序将把用户事件类于Qt的事件类同等处理。

    //用户事件类QOriCodeEvent头文件qoricodeevent.h 
    #include <QEvent>
    #define ORI_DIS_EVENT QEvent::User+12

    class QOriCodeEvent : public QEvent  
    {
    public:
        QOriCodeEvent();
    public:
        int m_len;
        char m_data[255];
    };

    //用户事件类QOriCodeEvent实现文件qoricodeevent.cpp
    #include "qoricodeevent.h"

    QOriCodeEvent::QOriCodeEvent()
        : QEvent( Type(ORI_DIS_EVENT) )
    {
        //实现比较简单,随机获得指定长度的源码
        m_len = rand()%150 + 50;
        //0xeb 0x90 表示起始头,其他数据随机产生的。
        m_data[0] = 235;
        m_data[1] = 144;
        for (int i = 2; i < m_len; i++)
            m_data[i] = rand()%255;
    }

    事件发送
    应用程序都要创建并发送自定义事件,因此先创建一个相应的事件类的对象,然后将事件发送。
    QCoreApplication::sendEvent()、QCoreApplication::postEvent()都能完成事件发送操作。
    senEvent()、postEvent()区别不用多说了吧~和Mfc中的SendMessage()、PostMessage()差不多。
    只是postEvent()是投寄事件到一个队列,以便迟缓分发。

        发送用户事件:
    这里为了简化实例,只在一个线程中定时发送,当然也可以在定时器事件中完成。
    但由于用户事件不一定时时触发,最好还是定义个全局的QWaitCondition对象,通过wait()、wakeOne()来触发事件在线程中的发送。
    QWaitCondition的相关内容留在以后写Qt线程中在讲解吧~

    //发送源码线程QOriThread头文件qorithread.h
    #include <QThread>
    class QOriThread : public QThread
    {
    public:
        QOriThread();
        virtual ~QOriThread();
        void run(); 
    private:
        bool m_sign;
    };

    //发送源码线程QOriThread实现部分qorithread.cpp
    #include "qoricodeevent.h"
    #include "orithread.h"
    #include <QApplication>
    #include <mainwindow.h>
    extern MainWindow *pMainwindow;

    OriThread::OriThread()
    {
    }

    OriThread::~OriThread()
    {
        m_sign = true;
        wait();
    }

    void OriThread::run()
    {
        m_sign = false;
     
        while(true)
        {
            if(m_sign)
                break;
            QOriCodeEvent *event = new QOriCodeEvent();
            //pMainwindow是主窗口类的指针
            qApp->postEvent( (QObject*)pMainwindow->textView, event);
            sleep(1);
        }
    }

    事件处理
    有5种不同的处理事件的方法,如下
    1、重载函数QCoreApplication::notify()可提供有效的事件控制,但仅能在派生于QCoreApplication、QApplication的类中重实现这个函数。
    2、在qApp(是QApplication的全局实例)中实现事件过滤,这样的一个事件过滤器能为所有的widget处理所有的事件,而且可以有超过一个全局应用程序的事件过滤器。如鼠标事件的全局事件过滤器设置了鼠标跟踪事件,则鼠标移动事件对于所有widget有效。
    3、重载QObject::event()(在QWidget类中)在任何widget特定的事件过滤器之前可看到所有事件。
       这个虚函数接收一个对象的事件,如果事件被识别并被处理,将返回true。这个函数能被用来重实现一个对象的行为。
    4、在对象上安装事件过滤器。
    5、重载Qt基类事件处理函数。
       当用户发现Qt基类的事件处理函数不能满足需要时,可以在用户类中重载这些函数。对于特定的Qt事件,可以重载特定的事件函数,如重载paintEvent()、mousePressEvent()等函数。

        处理用户事件:
    如果想处理多个Qt事件处理函数,可以通过重载QObject::event()来实现。
    但这个我们是要处理的是自定义用户事件,这个要重载的是QObject::customEvent()。

    //上面的textView就是QOriTextView类的对象。头文件qoritextview.h 
    #include "qoricodeevent.h"
    #include <QTextEdit>

    class QOriTextView : public QTextEdit  
    {
    public:
        QOriTextView(QWidget* parent = 0);
        void ClearBuf();
        QTextDocument *document;

    protected:
        void customEvent( QEvent *event );
     
    private:
        QVector<QString> m_oriTextList;
    };

    //QOriTextView类实现部分qoritextview.cpp
    #include "qoritextview.h"

    QOriTextView::QOriTextView(QWidget* parent)
        :QTextEdit(parent)
    {
        m_oriTextList.clear();
        document = new QTextDocument(this);
        //设置字体
        QFont font = document->defaultFont();
        font.setPointSize(11);
        document->setDefaultFont(font);
        document->setUseDesignMetrics(true);
        //设置背景色黑色
        setPalette(Qt::black);
        setDocument(document);
        //设置滚动条暗灰色
        verticalScrollBar()->setPalette(Qt::darkGray);
        //文本形式为只读
        setReadOnly(true);
        setUndoRedoEnabled(true);
    }

    void QOriTextView::ClearBuf()
    {
        clear();
        m_oriTextList.clear();
    }

    void QOriTextView::customEvent( QEvent *event )
    {
        int type = event->type();
        if ( type == ORI_DIS_EVENT ) 
        {  
            //将QOriCodeEvent发来的数据写到oriText中。
            QString oriText;
            for(int i=0; i<((QOriCodeEvent*)event)->m_len; i++)
            { 
                QString tempStr;
                tempStr.sprintf("%02X ", (unsigned char)(((QOriCodeEvent*)event)->m_data[i]));
                oriText += tempStr;
            }
            //设置文本字体颜色白色
            setTextColor(Qt::white);
            append(oriText);
            m_oriTextList.push_back(oriText);
            //当数据大于15条后,清除顶方数据
            if (m_oriTextList.count() > 15)
            {
                QTextCursor cursor(document);
                if (cursor.isNull())
                {
                    cursor.movePosition(QTextCursor::Start);
                    cursor.movePosition(QTextCursor::NextBlock, QTextCursor::KeepAnchor);
                    cursor.deleteChar();
                    m_oriTextList.pop_front();
                }
            }
            //滚动条始终在最下面
            QScrollBar *vScrollBar = verticalScrollBar();
            qreal high = vScrollBar->maximum() - vScrollBar->minimum() + vScrollBar->pageStep();
            vScrollBar->setSliderPosition(vScrollBar->maximum());
            event->accept();
        }
    }

    转自:http://cool.worm.blog.163.com/blog/static/6433900620084632410879/

    http://blog.csdn.net/leo115/article/details/7403033

  • 相关阅读:
    架构设计之NodeJS操作消息队列RabbitMQ
    如何搭建一个功能复杂的前端配置化框架(一)
    Web as a App(Web既APP)的概念可以提出吗?
    Bottle源码阅读笔记(二):路由
    Bottle源码阅读笔记(一):WSGI
    Python__slots__详解
    [译]如何在Web开发中使用Python
    C#中Internal关键字的总结
    [DataContract]引用
    分享一个与ABP配套使用的代码生成器源码
  • 原文地址:https://www.cnblogs.com/findumars/p/5696941.html
Copyright © 2011-2022 走看看