Qt(4.8.2)GUI - 拥有主循环而不是QApplication :: exec()

时间:2021-12-04 21:01:04

I would like to ask, if it is possible to use a custom main loop instead of running a.exec():

我想问一下,如果可以使用自定义主循环而不是运行a.exec():

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Window r;
    r.showFullScreen();
    return a.exec(); 
}

something like:

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Window r;
    r.showFullScreen();

    while(a.processOneEvent()) {
        read_event_from_legacy_system
    }

    return 0; 
}

In GTK I could use gtk_main_iteration_do() so I thought there is maybe something similar in Qt?

在GTK中我可以使用gtk_main_iteration_do()所以我认为在Qt中可能有类似的东西?

Or is there any other correct way to read custom events from a specific legacy system?

或者是否有其他正确的方法来从特定的遗留系统中读取自定义事件?

EDIT: The events which a read from the FIFOs are not system events (such as X11) they are just a struct which is sent via a FIFO to realize ipc.

编辑:从FIFO读取的事件不是系统事件(例如X11),它们只是一个通过FIFO发送以实现ipc的结构。

3 个解决方案

#1


So you want to react on a FIFO -or pipe- file descriptor (on Linux) using Qt

因此,您希望使用Qt对FIFO -or管道文件描述符(在Linux上)做出反应

With Qt5 you would probably use QAbstractSocket or QIoDevice and its readyRead signal

使用Qt5,您可能会使用QAbstractSocket或QIoDevice及其readyRead信号

With Qt4 you should use QSocketNotifier and its activated signal (so call your read_event_from_legacy_system from a Qt slot connected to that signal). It can poll any file descriptor, including a fifo(7)

使用Qt4,您应该使用QSocketNotifier及其激活的信号(因此从连接到该信号的Qt插槽调用read_event_from_legacy_system)。它可以轮询任何文件描述符,包括fifo(7)

There is no need to change the application's event loop (even if in theory you might subclass QApplication but I don't recommend doing that). Once you set up correctly your thing, Qt event loop will poll the additional file descriptor, and your code should read it.

无需更改应用程序的事件循环(即使理论上您可能是子类QApplication但我不建议这样做)。一旦你正确设置了你的东西,Qt事件循环将轮询其他文件描述符,你的代码应该读取它。

#2


Although this might not be the best solution for your problem, you can write your own main loop like this:

虽然这可能不是您问题的最佳解决方案,但您可以编写自己的主循环,如下所示:

QApplication app(argc, argv);
QMainWindow wnd;

wnd.show();

while(wnd.isVisible())
{
    app.processEvents();

    // perform your own actions here
}

Instead of wnd.isVisible() you can of course use your own breaking condition.

你可以使用自己的破坏条件代替wnd.isVisible()。

#3


I have come up with following solution:

我想出了以下解决方案:

PipeReader.hpp

#ifndef PIPEREADER_HPP
#define PIPEREADER_HPP

#include <QObject>
#include <QSocketNotifier>

class PipeReader : public QObject
{
    Q_OBJECT
public:
    PipeReader(int fd, QObject *parent = 0);
    ~PipeReader();
private:
    QSocketNotifier *notifier;
    int m_fd;
signals:
    void dataReceived();
private slots:
    void readFromFd();
};

#endif  /* PIPEREADER_HPP */

PipeReader.cpp

#include <PipeReader.hpp>
#include <QObject>

PipeReader::PipeReader(int fd, QObject *parent)
: QObject(parent), notifier(NULL), m_fd(fd)
{
    notifier = new QSocketNotifier(m_fd, QSocketNotifier::Read, this);
    QObject::connect(notifier, SIGNAL(activated(int)), this, SLOT(readFromFd()));
}

PipeReader::~PipeReader()
{

}

void PipeReader::readFromFd()
{
    qDebug("readFromFd");
    int ret_val = read(m_fd, &event, sizeof(Event), 10);

    emit dataReceived();
}

main.cpp

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

    if ((fd = open(SPECIAL_FD, O_RDONLY | O_SYNC)) < 0) {
        exit(0);
    }

    PipeReader reader(fd);

    w.showFullScreen();
    return a.exec();
}

I get all events read from a specific file descriptor. If you want to use the events in MyWindow just connect the signal dataReceived() with a public slot of MyWindow.

我从特定的文件描述符中读取所有事件。如果要在MyWindow中使用事件,只需将信号dataReceived()与MyWindow的公共插槽连接即可。

#1


So you want to react on a FIFO -or pipe- file descriptor (on Linux) using Qt

因此,您希望使用Qt对FIFO -or管道文件描述符(在Linux上)做出反应

With Qt5 you would probably use QAbstractSocket or QIoDevice and its readyRead signal

使用Qt5,您可能会使用QAbstractSocket或QIoDevice及其readyRead信号

With Qt4 you should use QSocketNotifier and its activated signal (so call your read_event_from_legacy_system from a Qt slot connected to that signal). It can poll any file descriptor, including a fifo(7)

使用Qt4,您应该使用QSocketNotifier及其激活的信号(因此从连接到该信号的Qt插槽调用read_event_from_legacy_system)。它可以轮询任何文件描述符,包括fifo(7)

There is no need to change the application's event loop (even if in theory you might subclass QApplication but I don't recommend doing that). Once you set up correctly your thing, Qt event loop will poll the additional file descriptor, and your code should read it.

无需更改应用程序的事件循环(即使理论上您可能是子类QApplication但我不建议这样做)。一旦你正确设置了你的东西,Qt事件循环将轮询其他文件描述符,你的代码应该读取它。

#2


Although this might not be the best solution for your problem, you can write your own main loop like this:

虽然这可能不是您问题的最佳解决方案,但您可以编写自己的主循环,如下所示:

QApplication app(argc, argv);
QMainWindow wnd;

wnd.show();

while(wnd.isVisible())
{
    app.processEvents();

    // perform your own actions here
}

Instead of wnd.isVisible() you can of course use your own breaking condition.

你可以使用自己的破坏条件代替wnd.isVisible()。

#3


I have come up with following solution:

我想出了以下解决方案:

PipeReader.hpp

#ifndef PIPEREADER_HPP
#define PIPEREADER_HPP

#include <QObject>
#include <QSocketNotifier>

class PipeReader : public QObject
{
    Q_OBJECT
public:
    PipeReader(int fd, QObject *parent = 0);
    ~PipeReader();
private:
    QSocketNotifier *notifier;
    int m_fd;
signals:
    void dataReceived();
private slots:
    void readFromFd();
};

#endif  /* PIPEREADER_HPP */

PipeReader.cpp

#include <PipeReader.hpp>
#include <QObject>

PipeReader::PipeReader(int fd, QObject *parent)
: QObject(parent), notifier(NULL), m_fd(fd)
{
    notifier = new QSocketNotifier(m_fd, QSocketNotifier::Read, this);
    QObject::connect(notifier, SIGNAL(activated(int)), this, SLOT(readFromFd()));
}

PipeReader::~PipeReader()
{

}

void PipeReader::readFromFd()
{
    qDebug("readFromFd");
    int ret_val = read(m_fd, &event, sizeof(Event), 10);

    emit dataReceived();
}

main.cpp

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

    if ((fd = open(SPECIAL_FD, O_RDONLY | O_SYNC)) < 0) {
        exit(0);
    }

    PipeReader reader(fd);

    w.showFullScreen();
    return a.exec();
}

I get all events read from a specific file descriptor. If you want to use the events in MyWindow just connect the signal dataReceived() with a public slot of MyWindow.

我从特定的文件描述符中读取所有事件。如果要在MyWindow中使用事件,只需将信号dataReceived()与MyWindow的公共插槽连接即可。