Creating a custom message/event with Qt

笑着哭i 提交于 2019-12-05 15:27:45

In Qt 3, the usual way to communicate with the GUI thread from a non-GUI thread was by posting a custom event to a QObject in the GUI thread. In Qt 4, this still works and can be generalized to the case where one thread needs to communicate with any other thread that has an event loop.

To ease programming, Qt 4 also allows you to establish signal--slot connections across threads. Behind the scenes, these connections are implemented using an event. If the signal has any parameters, these are also stored in the event. Like previously, if the sender and receiver live in the same thread, Qt makes a direct function call.

-- http://doc.qt.nokia.com/qq/qq14-threading.html#signalslotconnectionsacrossthreads

Using custom events generally involves creating your own QEvent subclass, overriding customEvent() in the QObject class that will receive the event (often the main window class) and some code that "posts" the event from your thread to the receiver.

I like to implement the event posting code as a method of the receiver class. That way, the caller only has to know about the recevier object and not any of the "Qt" specifics. The caller will invoke this method which will then essentially post a message to itself. Hopefully the code below will make it clearer.

// MainWindow.h
...
// Define your custom event identifier
const QEvent::Type MY_CUSTOM_EVENT = static_cast<QEvent::Type>(QEvent::User + 1);

// Define your custom event subclass
class MyCustomEvent : public QEvent
{
    public:
        MyCustomEvent(const int customData1, const int customData2):
            QEvent(MY_CUSTOM_EVENT),
            m_customData1(customData1),
            m_customData2(customData2)
        {
        }

        int getCustomData1() const
        {
            return m_customData1;
        }

        int getCustomData2() const
        {
            return m_customData2;
        }

    private:
        int m_customData1;
        int m_customData2;
};

public:
void postMyCustomEvent(const int customData1, const int customData2);
....
protected:
void customEvent(QEvent *event); // This overrides QObject::customEvent()
...
private:
void handleMyCustomEvent(const MyCustomEvent *event);

The customData1 and customData2 are there to demonstrate how you might pass some data along in your event. They don't have to be ints.

// MainWindow.cpp
...
void MainWindow::postMyCustomEvent(const int customData1, const int customData2)
{   
    // This method (postMyCustomEvent) can be called from any thread

    QApplication::postEvent(this, new MyCustomEvent(customData1, customData2));   
}

void MainWindow::customEvent(QEvent * event)
{
    // When we get here, we've crossed the thread boundary and are now
    // executing in the Qt object's thread

    if(event->type() == MY_CUSTOM_EVENT)
    {
        handleMyCustomEvent(static_cast<MyCustomEvent *>(event));
    }

    // use more else ifs to handle other custom events
}

void MainWindow::handleMyCustomEvent(const MyCustomEvent *event)
{
    // Now you can safely do something with your Qt objects.
    // Access your custom data using event->getCustomData1() etc.
}

I hope I didn't leave anything out. With this in place, code in some other thread just needs to get a pointer to a MainWindow object (let's call it mainWindow) and call

mainWindow->postMyCustomEvent(1,2);

where, just for our example, 1 and 2 can be any integer data.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!