How to make some code run immediately before entering the event loop ? [Solved]



  • I would like some code to be executed systematically prior to entering the event loop, how can I achieve this ?


  • Moderators

    You can call the slot function directly prior to entering the event loop.



  • My question might well be not correctly worded.

    If I get the event loop doing something like
    @While(1){
    Do_Something;}@

    Then What I would like is to have :
    @While(1){
    My_Own_function();
    Do_Something;}@

    I have read some posts I think (but am not sure) related, suggesting to use a one shot timer.
    Is it the best practice ? How to achieve that practically ?


  • Moderators

    "slot description 2nd paragraph":http://qt-project.org/doc/qt-5.0/qtcore/signalsandslots.html#slots
    [quote]Since slots are normal member functions, they follow the normal C++ rules when called directly.[/quote]

    The standard template project looks like:

    MainWindow.h extended by a slot method:
    @
    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H

    #include <QMainWindow>

    namespace Ui {
    class MainWindow;
    }

    class MainWindow : public QMainWindow
    {
    Q_OBJECT

    public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

    public slots:
    void slt ();
    private:
    Ui::MainWindow *ui;
    };

    #endif // MAINWINDOW_H
    @

    MainWindow.cpp
    @
    #include "MainWindow.h"
    #include "ui_MainWindow.h"

    #include <QDebug>

    MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
    {
    ui->setupUi(this);
    }

    MainWindow::~MainWindow()
    {
    delete ui;
    }

    MainWindow::slt ()
    {
    int i = 10;
    qDebug() << i;
    }
    @

    main.cpp
    @
    #include "MainWindow.h"
    #include <QApplication>

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

    w.slt();
    
    return a.exec&#40;&#41;;
    

    }
    @


  • Moderators

    You should not change your post while someone is answering. Nothing matches anymore.

    If I understand you correctly, you like to call an additional slot function prior to the actual one, which is called?



  • [quote author="koahnig" date="1378404428"]You should not change your post while someone is answering. Nothing matches anymore. [/quote]
    I apologize.

    About everywhere in the code of the MainWindow.cpp, whatever is done, I fill a buffer.
    I get some code managing that buffer that I would like to run once per loop of the event loop before the system stops waiting for events.


  • Moderators

    Are you implementing your own event loop, or using Qt's one?



  • [quote author="JKSH" date="1378429807"]Are you implementing your own event loop, or using Qt's one?[/quote]
    I use the main QT's one.
    I only get in addition a custom event hanldler and an event filter.


  • Moderators

    [quote author="aCOSwt" date="1378409489"]I get some code managing that buffer that I would like to run once per loop of the event loop before the system stops waiting for events.[/quote]I think the usual way to do that is to use QTimer to periodically manage the buffer, not once every loop.

    @
    connect(timer, SIGNAL(timeout()),
    this, SLOT(myOwnFunction()));
    timer->start(20); // Run myOwnFunction() every 20 ms
    @



  • [quote author="JKSH" date="1378446981"]I think the usual way to do that is to use QTimer to periodically manage the buffer, not once every loop.[/quote]
    Thank you for helping JKSH.
    My initial idea was indeed to use a QTimer but with a timeout of 0 because I want the function to be ran once and only once per loop.
    The two problems I get with that is that :

    • The connected slot will be executed at the end of the event loop when I wanted it at the beginning

    • I read that zero millisecond QTimers would soon be deprecated, so this does not sound as a best practice for what I am looking after.


  • Moderators

    [quote author="aCOSwt" date="1378448525"]I want the function to be ran once and only once per loop.[/quote]Just out of curiosity, may I ask why you need this function to run exactly once per loop, and why it must be the very first function called each loop?

    [quote]- I read that zero millisecond QTimers would soon be deprecated[/quote]Where did you read that? I don't think that's true.

    [quote]- The connected slot will be executed at the end of the event loop when I wanted it at the beginning[/quote]A warning before I continue: This method is very fragile. I recommend looking for a different design, that doesn't require your function to be called at the start of every loop.

    But anyway, if you really truly MUST do things this way, here's a trick that could work (I've never tried it myself though):

    Make sure that the MainWindow is the first object that you create, after QApplication.

    @
    class MainWindow : public QMainWindow {
    Q_OBJECT

    public:
    explicit MainWindow(QWidget *parent = 0) {
    connect(this, SIGNAL(ready()),
    this, SLOT(manageBuffer()),
    Qt::QueuedConnection);
    emit ready();

        // Construct your MainWindow here
    }
    

    signals:
    void ready();

    private slots:
    void manageBuffer() {
    emit ready();

        // Manage your buffer here
    }
    

    };
    @

    Here's how it works:

    • When a signal is emitted, a Queued Connection will put the slot in the event queue, causing it it be run in the next iteration of the event loop. (Contrast this with a Direct Connection, where the slot is called immediately when the signal is emitted)
    • If MainWindow::ready() is the first signal emitted in a loop, then MainWindow::manageBuffer() will be the first slot called in the next loop.

    Here are the risks:

    • If you forget to specify Qt::QueuedConnection, your program will enter an infinite recursion and crash
    • For every iteration of the event loop, if another signal ever gets emitted before MainWindow::ready(), then MainWindow::manageBuffer() won't be the first function called in the next loop. This makes it a pain to grow your program, because you'll have to watch out for this at all times, for the lifetime of your project.


  • At first a BIG thank to you JKSH for your help + aplogizes for being so long to answer.
    [quote author="JKSH" date="1378513925"]Just out of curiosity, may I ask why you need this function to run exactly once per loop, and why it must be the very first function called each loop?[/quote]
    1/ Very first function called because the function needs to be run when the application starts even if there is no event to process.
    I was just too stupid when I translated this need into "first function in the loop".
    Of course-1, I just needed to call it once before a.exec and of course-2, I had not realized that when the application starts, there is a kyriad of events to process.
    => Problem solved : The function can now be run at the end of the loop.

    2/ Functionally, this function can run each time an event is processed, so, functionally, I could have included the call to the function as part of each event handler.
    But I did not want that because this function locks a mutex which can block processes of much higher priority than the qt interface.

    3/ So I realized that all I needed was to connect that function to some event and generate the event as part of each others event handlers.

    4/ But that was a bit suboptimal from a coding standpoint.
    So what I did was to :

    • create a singleshot 0 timer in the mainwindow creator,
    • start the timer in my eventfilter for all events except QEvent::Timer.

    That does the trick. Might be suboptimal but... it works.

    (Of course, the first time I tested... I had not made the timer singleshot and... [facepalm]...) lol!
    [quote author="JKSH" date="1378513925"][quote]- I read that zero millisecond QTimers would soon be deprecated[/quote]Where did you read that? I don't think that's true.[/quote]
    It could be possible that I read to far or misinterpreted but, here it is, quoted from the QTimer Class Reference:
    [quote]As a special case, a QTimer with a timeout of 0 will time out as soon as all the events in the window system's event queue have been processed. ... ... It should be written in such a way that it always returns quickly (typically after processing one data item) so that Qt can deliver events to widgets and stop the timer as soon as it has done all its work. ... ... multithreading is now becoming available on more and more platforms, and we expect that zero-millisecond QTimers will gradually be replaced by QThreads.[/quote]

    Thanks again for your detailed help and questions, at least it helped me much in the understanding of the event loop and in rethinking my analysis.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.