Qt - 解决插槽上的两个连续调用并仅执行一次操作

Qt - resolve two sequential calls on a slot and perform action only once

我有一个 CodeEditor class 继承自 QPlainTextEdit。 class 必须在 textCursor() 的位置或选择发生变化时发出请求。问题是,当同时发出 cursorPositionChangedselectionChanged 时,我不想两次调用 assembleIntellisenseRequestpickListSortRequest 信号。我通过将 bool update_ 成员添加到 CodeEditor 来解决这个问题,它在构造函数中设置为 true。 500 毫秒延迟只是为了清楚起见。

void CodeEditor::makeConnections()
{
    auto updateRequest = [this]()
    {
        if(update_ && !textCursor().hasSelection())
        {
            update_ = false;
            QTimer::singleShot(500, [this]() { update_ = true; });

            emit assembleIntellisenseRequest(textCursor().blockNumber());
            emit pickListSortRequest(textCursor().positionInBlock());
        }
    };

    connect(this, &CodeEditor::cursorPositionChanged, updateRequest);
    connect(this, &CodeEditor::selectionChanged, updateRequest);
}

有没有更好的方法来完成这个?另外,为什么在这种情况下,当 lambda 通过引用捕获时 this1: 打印输出不等于 this:?沉默了,我才知道,update_还是false

auto updateRequest = [this]()
{
    cout << "this: " << this << endl;

    if(update_ && !textCursor().hasSelection())
    {
        update_ = false;
        QTimer::singleShot(500, [&]()
        {
            cout << "this1: " << this << endl;
            update_ = true;
        });

        emit assembleIntellisenseRequest(textCursor().blockNumber());
        emit pickListSortRequest(textCursor().positionInBlock());
    }
};

提前谢谢你。

您可以将下一个模式应用于您的代码:

class MyClass : public QObject
{
private slots:
  void updateRequest();  

private:
  QTimer *_timer;
  CodeEditor *_editor;
};


MyClass::MyClass()
{
  // Init members
  // ...
  _timer->setSingleShot( true );
  _timer->setInterval( 0 );

  connect( _editor, &CodeEditor:: cursorPositionChanged, _timer, &QTimer::start);
  connect( _editor, &CodeEditor:: selectionChanged, _timer, &QTimer::start);
  connect( _timer, &QTimer::timeout, this, &MyClass::updateRequest );
}

在此解决方案中,定时器是 "proxy for signals"。每次发出信号时,计时器都会立即启动(当流 return 进入事件循环时)。每次发出信号都会调用 QTimer::start 插槽。但是 start 的所有调用只会将 timeout 信号的一个调用放置到事件队列中。因此,当控制流 return 进入事件循环时,即使发出了很多信号,您的 updateRequest 插槽也只会被调用一次。

QTimer 是一个 "Qt way" 来替换您的 update_ 变量,没有任何超时。