45007


# 実現したいこと

PyQT5を使って簡単なGUIを作っています。  
その際、ソケット通信を行いサーバから受け取ったデータをGUI上に表示しようと思っています。

そこで、socketモジュールのsocket.recv()を使ってデータを受けとるようにしましたが、  
socket.recv()の待機時間が10秒ほどあり、その間、プログレスバーで時間経過を表示したいです。

# 実装したコード

以下のようにコードを実装してみましたが、  
socket.recv()の待機時間中はプログレスバーが止まってしまいます。  
具体的な改善点などして頂けると助かります。

[code]

    import socket
    import sys
    from PyQt5.QtWidgets import (QWidget, QLabel, QLineEdit,
        QTextEdit, QGridLayout, QApplication, QPushButton, QProgressBar, QSizePolicy)
    from PyQt5.QtCore import QBasicTimer
    import threading
    
    class Example(QWidget)
    
      def __init__(self):
        self.button = QPushButton("Run!")
        self.button.clicked.connect(self.threading_wrapper)
        self.pbar = QProgressBar(self)         #18/06/22 追記
        self.pbar.setGeometry(30, 40, 200, 25) #18/06/22 追記
        self.step = 0                          #18/06/22 追記
        self.timer = QBasicTimer()             #18/06/22 追記
    
      def threading_wrapper(self):
        thread = threading.Thread(target=self.send_socket)
        thread.daemon = True
        thread.start()
    
      def send_socket(self):
        ...
        self.timer.start(100, self)                           # 18/06/22 追記
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 18/06/22 追記
        s.connect((TCP_IP, TCP_PORT))                         # 18/06/22 追記
        s.send(msg.encode('utf-8'))                           # 18/06/22 追記
        r = socket.recv()
        self.timer.stop()                                     # 18/06/22 追記
        ...
    
      def timeEvent(self, e):
        self.step = self.step + 1     # 18/06/22 追記
        self.pbar.setValue(self.step) # 18/06/22 追記
        if self.step > 100:           # 18/06/22 追記
          self.timer.stop()           # 18/06/22 追記
    
[/code]


CC BY-SA 4.0
2018-06-21T06:24:03.527
44946
2018-06-23T08:34:41.997
2018-06-22T00:16:27.137
28333
28333
question
python pyqt socket
socket.recv()の待機時間中に、PyQt5のプログレスバーを進めたい


`QBasicTimer.start`を別スレッド(`threading.Thread`のスレッド)で呼んでいるので、タイマーの起動に失敗しているか(`QApplication`の)イベントディスパッチャで処理されていないためと予想します。  
「`self.timer.start(100,
self)`」を`threading_wrapper`メソッド側で呼び出すとタイマーが動作し、`Example.timerEvent()`が呼び出されるようになると思います。

* * *

なお、PyQt(Qt)の機能をスレッドで利用するのであれば、`threading.Thread`ではなく、`QtCore.QThread`でスレッド生成して処理する方が、相性がよいと思います。(`QThread`は  
イベントディスパッチャ機能を持っているため)

＃`QThread`を使った修正例は省略しますが、`socket_send`メソッドの内容を`QThread`の拡張クラスの`run()`メソッドとして実装する、等の方法で実現可能です。


CC BY-SA 4.0
2018-06-23T08:34:41.997
45007
2018-06-23T08:34:41.997
20098
44946
answer