等待在QLineEdit :: onTextChanged中输入的最后一个字符

时间:2014-02-21 20:59:18

标签: c++ qt qt5

我正在开发销售点应用程序,我有一个函数从QLineEdit(产品的条形码)获取文本并运行查询以查找要显示的产品。问题是我每次文本更改时都会运行查询,也就是说,每次输入新字符时都会运行查询。有没有办法等待用户停止输入然后运行查询?我将使用手持式扫描仪,因此在输入的每个字符之间会有100毫秒。

我想我需要这样的事情:

void PoS::on_lineEdit_textEdited()
{
    //check for keys still being pressed
    //if 100ms have passed without any key press, run query
}

我曾尝试使用计时器和线程(我对Qt 5很新)但到目前为止都失败了。

3 个答案:

答案 0 :(得分:6)

你需要一个计时器。在此处详细了解QTimerhttp://qt-project.org/doc/qt-5.1/qtcore/qtimer.html

添加QTimer *mTimer作为私有成员变量。创建一个名为do_query的插槽,您可以在其中执行查询。把它放在构造函数中的某个地方:

mTimer = new QTimer(this); // make a QTimer
mTimer->setSingleShot(true); // it will fire once after it was started
connect(mTimer, &QTimer::timeout, this, &PoS::do_query); // connect it to your slot

现在你的功能:

void PoS::on_lineEdit_textEdited()
{
    mTimer->start(100); // This will fire do_query after 100msec. 
    // If user would enter something before it fires, the timer restarts
}

并进行查询:

void PoS::do_query()
{
    // your code goes here
}

答案 1 :(得分:1)

有两种方法:

  1. 上次更改后100ms查询。为此,您(重新)按下按键启动100ms计时器。当它过期时,您运行查询。

  2. 在用户进行更改时,每隔 100ms查询。按键启动时间为100毫秒,但前提是它尚未运行。当它过期时,您运行查询。

  3. 如果在单独的QObject中实现查询处理器,则可以将其简单地移动到单独的线程 - 但请确保您也在该线程中创建了数据库连接。 UI对象和查询处理器之间唯一的通信方式应该是通过信号/插槽 - 这需要处理线程之间的同步数据交换。

    你可以删除moveToThread电话:它仍然可以使用。然后在GUI线程中运行查询执行器,因此用户体验可能会更糟,因为数据库驱动程序通常会在查询处理时阻塞。

    #include <QApplication>
    #include <QTextEdit>
    #include <QBasicTimer>
    #include <QSqlDatabase>
    #include <QThread>
    
    class ProductData {
    };
    Q_DECLARE_METATYPE(ProductData)
    
    class PoS : public QWidget {
       Q_OBJECT
       enum QueryBehavior { FinalQuery, MultipleQuery };
       QBasicTimer m_queryTimer;
       QueryBehavior m_queryBehavior;
       Q_SLOT void on_lineEdit_textEdited() {
          if (m_queryBehavior == FinalQuery || !m_queryTimer.isActive())
             m_queryTimer.start(100, this);
       }
       void timerEvent(QTimerEvent * ev) {
          if (ev->timerId() != m_queryTimer.timerId()) return;
          m_queryTimer.stop();
          emit queryRequest();
       }
    public:
       Q_SIGNAL void queryRequest();
       Q_SLOT void queryResponse(const ProductData &) { /* ... */ }
       // ...
    };
    
    class QueryExecutor : public QObject {
       Q_OBJECT
       QSqlDatabase m_dbConnection;
    public:
       Q_SLOT void queryRequest() {
          if (!m_dbConnection.isOpen()) {
             // Open the database connection here, NOT in the constructor.
             // The constructor executes in the wrong thread.
             // ...
          }
          ProductData pdata;
          // ...
          emit queryResponse(pdata);
       }
       Q_SIGNAL void queryResponse(const ProductData &);
    };
    
    //! A thread that's always safe to destruct.
    class Thread : public QThread {
    private:
       using QThread::run; // This is a final class.
    public:
       Thread(QObject * parent = 0) : QThread(parent) {}
       ~Thread() { quit(); wait(); }
    };
    
    int main(int argc, char ** argv) {
       QApplication app(argc, argv);
       qRegisterMetaType<ProductData>();
       PoS pos;
       QueryExecutor executor;
       Thread thread; // must come after the executor!
       thread.start();
       executor.moveToThread(&thread);
       executor.connect(&pos, SIGNAL(queryRequest()), SLOT(queryRequest()));
       pos.connect(&executor, SIGNAL(queryResponse(ProductData)), SLOT(queryResponse(ProductData)));
       pos.show();
       return app.exec();
    }
    
    #include "main.moc"
    

答案 2 :(得分:0)

理解这不是为pyqt标记的,我为将来可能会发现它的任何人提供了Python 3 / PqQt5示例。每次文本更改(每个字符)时,都会重新启动计时器。用户停止输入1秒钟后,它将执行SQL或其他功能。

class MyClass(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.txt_edit = QtWidgets.QPlainTextEdit()
        self.typing_timer = QtCore.QTimer()
        self.typing_timer.setSingleShot(True)
        self.typing_timer.timeout.connect(self.make_changes)
        self.txt_edit.textChanged.connect(self.start_typing_timer)

    def start_typing_timer(self):
        """Wait until there are no changes for 1 second before making changes."""
        self.typing_timer.start(1000)

    def make_changes(self):
        txt = self.txt_edit.toPlainText()
        # RUN SQL OR DO SOMETHING ELSE WITH THE TEXT HERE #