Search code examples
qtpyqtqeventqplaintextedit

Can I delay/bundle reactions to QPlainTextEditor.textChanged events?


I have a small IDE for a modeling language I wrote, implemented in PyQt/PySide, and am trying to implement a code navigator that let's you jump to different sections in the file being edited.

The current implementation is: (1) connect to QPlainTextEditor.textChanged, (2) any time a change is made, (sloppily) parse the file and update the navigator pane

It seems to work OK, but I'm worried this could cause major performance issues for large files on slower systems, in particular if more stuff is connected to textChanged in the future.

My question: Has anybody here implemented a delayed reaction to events, so that multiple events (i.e. keystrokes) within a short period only trigger a single update (say once per second)? And is there a proper QT way of doing this?

Thanks, Michael


Solution

  • You can try using timers if you want some "delay".

    There would be 2 ways to use them (with different results).


    One is only parse after no input has been done for a certain amount of time

    NOTE: I only know C++ Qt but I assume the same things are valid for pyqt so this is kind of "pseudocode" I hope you get the concept though.

    QTimer timer; //somewhere
    timer.setSingleShot(true); //only fire once
    connect(timer,QTimer::timeout(),OnTimerDone(...);
    
    OnTextChanged(...)
    {
        timer.start(500); //wait 500ms
    }
    
    OnTimerDone(...)
    {
        DoStuff(...);
    }
    

    This will restart the timer every input, so when you call that and the timer is not done the timeout signal is not emitted. When no input is done for an amount of time the timer timeouts and you parse the file.


    The second option would be to have a periodic timer running (singleShot(false)).

    Just start the timer for like each second. and timeout will be called once a second. You can combine that with a variable which you set to true when the input changes and to false when the file is parsed. So you avoid parsing when nothing has changed.

    In C++Qt you won't have to worry about multi-threading because the slot gets called in the GUI thread. I assume it is the same for python but you should probably check this.