2014-02-21 1 views
1

Я работаю над приложением Point of Sale, у меня есть функция, которая берет текст из QLineEdit (штрих-код продукта) и запускает запрос, который ищет продукт отображается. Проблема в том, что я выполняю запрос каждый раз, когда текст изменяется, то есть каждый раз, когда набирается новый символ. Есть ли способ дождаться, когда пользователь перестанет печатать, а затем запустит запрос? Я буду использовать карманный сканер, чтобы он был как 100 мс между каждым набираемым символом.Дождитесь последнего символа, введенного в QLineEdit :: onTextChanged

Я думаю, что мне нужно что-то вроде этого:

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

Я пытался использовать таймер и также темы (я новичок в Qt 5), но не увенчались успехом до сих пор.

ответ

3

Вам понадобится таймер. Узнайте больше о 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 
} 
+0

Работает как очарование! это именно то, что мне нужно. Спасибо – user3338859

+0

Простой и элегантный! Я добавлю это (с надлежащей атрибуцией) на соответствующую страницу в вики Qt, чтобы получить дополнительную видимость: https://wiki.qt.io/Delay_action_to_wait_for_user_interaction – waldyrious

0

Есть два подхода:

  1. Запрос 100 мс после последнего изменения. Для этого вы (повторно) запускаете таймер 100 мс при нажатии клавиши. По истечении этого срока выполняется запрос.

  2. Вопрос каждые 100 мс, пока пользователь вносит изменения. Начните 100 мс при нажатии клавиши, но только если он еще не запущен. По истечении этого срока выполняется запрос.

Если вы реализуете процессор запроса в отдельном QObject, вы можете тривиальным переместить его в отдельный поток - но убедитесь, что вы создали соединение с базой данных в этой теме тоже. Единственным средством связи между объектом пользовательского интерфейса и процессором запросов должно быть через сигналы/слоты - это обеспечивает синхронизацию обмена данными между потоками.

Вы можете удалить звонок moveToThread: он все равно будет работать. Затем вы запускаете исполнитель запросов в потоке графического интерфейса пользователя, поэтому для него может быть хуже, поскольку драйверы базы данных обычно блокируются во время обработки запроса.

#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" 
Смежные вопросы