2017-08-28 8 views
0

キーイベントを作成します。キー "A"を押すと、関数A()が実行されます.A()のプロセスは2秒間続きます。 4times/2sのようにすばやくキーを押すと、すべてのプロセスが終了するまで待つことにします。私はテストして、キーを4回/ 2秒間押すと、後でキーを押すイベントでプロセスを実行することがわかりました。すべてのプロセスがキーイベントで終了するまで待つことはできますか?スレッドとミューテックスを使用する必要があります。しかし、何か間違っている。 mutexを使うのは初めてのことです。この問題の解決方法はわかりません。Qtのすべてのプロセスがkeyeventsで終了するまで、どうすればいいですか?

int g = 0; 
void MainWindow::keyPressEvent(QKeyEvent *event) 
{ 
int keyCode = event->key(); 
if(keyCode == Qt::Key_A) { 
    qDebug() << "da"; 
    a->start(); 
} 
} 


void MyThread::run()// i try to block the second time process while press the key so quickly 
{ 

    mutex->lock(); 
    ...//process:last for 2s 
    g++; 
    mutex->unlock(); 
} 
+1

あなたのスレッドは何をすべきですか?なぜ私はあなたのためにスレッドが必要になるか分かりません。開始されたプロセスのカウンタを維持するだけです。プロセスが終了したら、['QProcess :: finished'](http://doc.qt.io/qt-5/qprocess.html#finished)シグナルを通知してください。そのような信号を受信したときにカウンタを減らしてください。カウンタが0になると、すべてのプロセスが終了したことがわかります。私はこのすべてのポイントが何であるかはわかりませんが。あなたのプログラムを少し説明してくれれば助かります。 – thuga

+0

私はコードを更新しました。例えば、Aの2秒後にgの値を更新したいです()。しかし、私がキーをすばやく押すと、gを更新せずに新しいキーイベントを受け取り、最初の行からA()を再度実行します。だから私は新しいイベントが来るのを防ぐためにミューテックスを設定し、A()とupdate gを通過できることを確認したい。 –

+0

プロセスを開始してから2秒後に 'g 'を更新したいのはなぜですか?なぜ即座に更新できないのですか?あなたは達成しようとしていることをより詳細に説明しなければなりません、なぜなら今は意味をなさないからです。プロセスが実行されている間にキーイベントをブロックしたい場合は、キープロセスで[プロセスの状態をチェック](http://doc.qt.io/qt-5/qprocess.html#state)してください。 – thuga

答えて

0

私が正しく理解していれば、ボタンAを押すとアクションA()が実行されます。ただし、GUIスレッドをブロックしてUIをフリーズしたくないため、別のスレッドでアクションA()を実行します。

ボタンを「スキップ」したくない場合は、解決策は単純であるプッシュ:

  1. contextと呼ばれるいくつかのダミーQObjectを作成します。
    QObject* context = new QObject;
  2. QThreadthreadを稼働させて実行してください。
    QThread* thread = new QThread{ this }; thread->start(); ...
  3. その後 object->moveToThread(thread)threadcontextを移動します。
  4. MainWindowクラスの信号を作成します(例:runA())。
  5. A()アクションでこの信号を接続し:
    connect(this, &MainWindow::runA, context, []() { A(); });
  6. たびボタン「」ちょうどこの信号を発する押される:emit runA();

信号が発せられるたびに、アクションA(のイベント)実行されるスレッドは `threads events loop 'にポストされます。すべてのイベントは、の順番で処理されます。どんなにあなたがボタン "A" を押してどのように迅速


#pragma once 

#include <QThread> 
#include <QDebug> 
#include <QWidget> 
#include <QKeyEvent> 

class MainWindow : public QWidget 
{ 
    Q_OBJECT 
private: 
    QThread* thread; 
    QObject* context; 

public: 
    MainWindow() 
     : thread{ new QThread }, 
      context{ new QObject } 
    { 
     context->moveToThread(thread); 
     connect(this, &MainWindow::doAction, context, [this]() { 
      Action(); 
     }); 
     thread->start(); 
    } 
    ~MainWindow() { 
     context->deleteLater(); 
     thread->deleteLater(); 
    } 

signals: 
    void doAction(); 

public: 
    void keyPressEvent(QKeyEvent* event) 
    { 
     int keyCode = event->key(); 
     if(keyCode == Qt::Key_A) { 
      emit doAction(); 
     } 
    } 

    void Action() { 
     qDebug() << "Action is being executed."; 
     QThread::currentThread()->sleep(2); // imitate some long calculation 
    } 
}; 

。 "アクションが実行されています。"ちょうど2秒の間隔と正確にボタンが押された回数で印刷されます。

+0

ありがとうございました。しかし、私の場合は、すべてのキーイベントをキューに保存し、2秒ごとに1つずつ実行したい(プロセスが終了するまで待つ)。たとえば、キーを2回押すと1つのプロセスが2秒間続きます。 2秒でキーを4回押しました。そして、私はこの4つのイベントをキューに保存し、2秒ごとに1つずつ実行したいと考えています。 –

+0

このシグナルをA()アクションで接続します:connect(this、&MainWindow :: runA、context、[](){A();});仕事ができません –

+0

@MotoJack、Ok、私は最初の部分はあなたのためのオプションではないことがわかります。しかし、なぜ "A()'アクションでこのシグナルを接続することができないのですか? – WindyFields

-1

これは必須です何明確ではありません。

  • あなたはA()
  • 内部の任意のミューテックスなく、各キープレス使用QtConcurrent::run(A);ためのスレッドを起動したい場合は、押されたキーごとA()を実行する場合同時にではありません A()内のミューテックスを使用します(あなたのように)
+0

私はコードを更新しました。例えば、Aの2秒後にgの値を更新したい)。しかし、私がキーをすばやく押すと、gを更新せずに新しいキーイベントを受け取り、最初の行からA()を再度実行します。だから私は新しいイベントが来るのを防ぐためにミューテックスを設定し、A()とgを更新できることを確認したい。コードは機能しない –

+0

これは質問への回答を提供しない。 [類似の質問を検索する](// stackoverflow.com/search)、またはページの右側にある関連するリンクされた質問を参照して回答を見つけることができます。関連しているが異なる質問がある場合は、[新しい質問をする](// stackoverflow.com/questions/ask)、コンテキストの提供に役立つこのリンクを追加してください。参照:[質問をする、回答を得る、混乱を招く](//stackoverflow.com/tour) –

0

簡単な解決策の1つは、スレッドプール内にただ1つのスレッドを持つQtConcurrent::runを使用することです。これにより、スレッドの寿命、高価なリソース(リソースプールなど)を管理する必要がなくなります。それはリソースを解放するためにしばらく使用されていない場合に処分されます。

// https://github.com/KubaO/stackoverflown/tree/master/questions/single-job-lambda-45913311 
#include <QtWidgets> 
#include <QtConcurrent> 

class LogWindow : public QPlainTextEdit { 
    Q_OBJECT 
    QThreadPool m_pool; 
    int g = {}; // can be accessed from the worker thread only 
    void keyReleaseEvent(QKeyEvent * event) override { 
     if (event->key() == Qt::Key_A) 
     QtConcurrent::run(&m_pool, this, &LogWindow::method); 
     QPlainTextEdit::keyReleaseEvent(event); 
    } 
    /// This method must be thread-safe. It is never reentered. 
    void method() { 
     QThread::sleep(2); // block for two seconds 
     g++; 
     emit done(g); 
    } 
    Q_SIGNAL void done(int); 
public: 
    LogWindow(QWidget * parent = {}) : QPlainTextEdit{parent} { 
     appendPlainText("Press and release 'a' a few times.\n"); 
     m_pool.setMaxThreadCount(1); 
     connect(this, &LogWindow::done, this, [this](int val){ 
     appendPlainText(QString::number(val)); 
     }); 
    } 
}; 

int main(int argc, char ** argv) { 
    QApplication app{argc, argv}; 
    LogWindow w; 
    w.show(); 
    return app.exec(); 
} 

#include "main.moc" 
関連する問題