QTimer()の()内は何か入れないといけませんか?
なにも入れなくてよいです。
これは処理を止めない限り処理Xと処理Yが0.1秒ごとに繰り返されますか?
今のコードはそうなっていません。
QTimer() は名前の通り、ストップウォッチです。
start() に指定したミリ秒分経過すると、timeout()
シグナルが呼ばれます。
timeout()
シグナルをスロットに繋いである場合は、タイムアウトしたときにその関数が呼ばれます。
本来どのようなことが行いたかったのかコメントいただければアドバイスできるかもしれません。
追記
今のコードでは、「処理Xが実行された0.1秒後に処理Xは止まり、処理Yが実行される」という解釈でよろしかったでしょうか?
今のコードは X() を呼び出すと、なにも起こらずにただちに終了します。
本来やりたい意図は置いておいて、問題点がいくつかあるのでコメント形式で書きました。
python
1def X(self):
2 self.Y # 関数呼び出しになっていない self.Y() では?
3 timer=QTimer()
4 timer.timeout.comect(self.Y) # comect() は connect() のスペルミスでは?
5 time.start(100) # start() という関数はタイマーをスタートさせるだけでここで処理はブロックされない。このあと、すぐに関数を抜けて、timer 変数が破棄されてしまうので、ローカル変数ではなく、self.timer のように属性として持っておかないとまずい
サンプルコード
QTimer の使い方の例を以下に記載します。
「タイマースタート」をクリックすると、2秒ごとに on_timeout()
が呼ばれます。
python
1import sys
2from PyQt5.QtWidgets import *
3from PyQt5.QtCore import *
4
5
6class MainWindow(QMainWindow):
7 def __init__(self):
8 super().__init__()
9 self.initUI()
10
11 def initUI(self):
12 widget = QWidget()
13 self.setCentralWidget(widget)
14
15 layout = QVBoxLayout()
16 widget.setLayout(layout)
17
18 # ボタンを配置する。
19 self.button = QPushButton("タイマースタート")
20 self.button.clicked.connect(self.startTimer)
21 layout.addWidget(self.button)
22
23 def startTimer(self):
24 self.timer = QTimer()
25 self.timer.timeout.connect(self.on_timeout) # QTimer が timeout した場合に呼び出す関数を登録
26 self.timer.start(2000) # タイマーをスタートさせる
27
28 def on_timeout(self):
29 """start() で設定したミリ秒ごとにこの処理が呼ばれます
30 """
31 print("timeout")
32
33
34if __name__ == '__main__':
35 app = QApplication(sys.argv)
36 windows = MainWindow()
37 windows.show()
38 app.exec_()
39 sys.exit(0)
Whileは処理が重くなるため使ってはいけないのかと感じています。
GUI アプリケーションは、イベントが発生していないかチェックするイベントループというものがメインスレッドで動いています。
while やすぐに終了しない重たい処理を行ってしまうと、そのイベントループが止まってしまうので、GUI がフリーズしたようになります。
なので、while や重たい処理を行いたい場合は別にスレッドを作って行う必要があります。
追記
「物体を検知してドアを開閉する」処理と「ドアの開閉状態をテキストボックスに入力する」処理をマルチスレッド(threading)で並列処理する『処理Z』をつくればよろしいのでしょうか?
ドアの開閉を行う処理を別スレッドで行う必要があると思います。
図にすると以下のようになります。
ドアが開閉されたら、シグナルを発呼し、メインスレッド側のスロットで受信し、テキストボックスに開閉状態を表示すればよいと思います。
python
1import sys
2from datetime import datetime
3from PyQt5.QtWidgets import *
4from PyQt5.QtCore import *
5
6### ここは別スレッドで行う ###
7class Worker(QObject):
8 doorOpened = pyqtSignal()
9
10 def __init__(self, parent=None):
11 QObject.__init__(self, parent=parent)
12
13 def process(self):
14 while True:
15 QThread.sleep(3)
16 # 実際はドアを開閉する処理などを書く
17
18 # ドアの開閉を通知
19 self.doorOpened.emit()
20
21class MainWindow(QMainWindow):
22 stop_signal = pyqtSignal()
23
24 def __init__(self):
25 super().__init__()
26 self.initUI()
27
28 def initUI(self):
29 widget = QWidget()
30 self.setFixedSize(640, 480)
31 self.setCentralWidget(widget)
32
33 layout = QVBoxLayout()
34 widget.setLayout(layout)
35
36 # LineEdit を配置する。
37 self.lineEdit = QLineEdit("処理開始")
38 layout.addWidget(self.lineEdit)
39
40 # スレッドを作成する。
41 self.thread = QThread()
42
43 # worker を作成し、メインスレッドから先程作成したスレッドに移す。
44 self.worker = Worker()
45 self.worker.moveToThread(self.thread)
46
47 # signal slot の設定
48 self.thread.started.connect(self.worker.process) # スレッド開始後に process() 開始
49 self.worker.doorOpened.connect(self.func) # doorOpened() が発呼されたら、func() を呼ぶ
50
51 # スレッドを開始
52 self.thread.start()
53
54 def func(self):
55 # ドアの開閉が通知されたら、テキストボックスに表示する
56 now = datetime.now()
57 self.lineEdit.setText(f"Door opened! {now}")
58
59### メインスレッド ###
60if __name__ == '__main__':
61 app = QApplication(sys.argv)
62 windows = MainWindow()
63 windows.show()
64 app.exec_()
65 sys.exit(0)
ここで詳解するのは、スペース的に厳しいので、概要と検索キーワードを示しておきます。
- スレッド間のやり取り: Qt のシグナルスロットを使う
→ 検索キーワード「Qt シグナルスロット」
→ 検索キーワード「QThread」
蛇足
ロボットのシステム開発だと、いくつかの処理を並列で実行しつつ、各処理間でデータをやり取りする必要があるので、システムが複雑になってくると、マルチスレッドのプログラムを書くのは大変になってきます。
なので、ROS というロボット用のフレームワーク (ライブラリ) がよく使われます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/05/21 09:52
2020/05/21 10:58 編集
2020/05/21 12:03
2020/05/22 12:32
2020/05/22 12:40
2021/01/26 14:35