我正在开发销售点应用程序,我有一个函数从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很新)但到目前为止都失败了。
答案 0 :(得分:6)
你需要一个计时器。在此处详细了解QTimer
:http://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)
有两种方法:
上次更改后100ms查询。为此,您(重新)按下按键启动100ms计时器。当它过期时,您运行查询。
在用户进行更改时,每隔 100ms查询。按键启动时间为100毫秒,但前提是它尚未运行。当它过期时,您运行查询。
如果在单独的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 #