52260


pyqt5で計算中は別のウィンドウを表示するように作ってみたいです。下は試しに書いてみたコードです。

[code]

    import sys
    from PyQt5 import*
    from PyQt5.QtWidgets import *
    from PyQt5.QtGui import *
    from PyQt5.QtCore import *
    from PyQt5 import QtGui,QtCore, QtWidgets
    import time
    from time import sleep
    
    
    class Second(QtWidgets.QWidget):
        def __init__(self, parent=None):
            super(Second, self).__init__(parent)
            #Setting a title, locating and sizing the window
            self.title = 'My Second Window'
            self.left = 200
            self.top = 200
            self.width = 500
            self.height = 500
            self.setWindowTitle(self.title)
            self.setGeometry(self.left, self.top, self.width, self.height)
            lbl = QtWidgets.QLabel("計算中")
    
            layout1=QHBoxLayout()
            layout1.addWidget(lbl)
            self.setLayout(layout1)
    
    
    class First(QtWidgets.QWidget):
        def __init__(self, parent=None):
            super(First, self).__init__(parent)
            self.title = 'My First Window'
            self.left = 100
            self.top = 100
            self.width = 500
            self.height = 500
            self.setWindowTitle(self.title)
            self.setGeometry(self.left, self.top, self.width, self.height)
            self.pushButton = QtWidgets.QPushButton("Open Me", self)
            self.pushButton2 = QtWidgets.QPushButton("close", self)
            self.pushButton.clicked.connect(self.on_pushButton_clicked)
            self.pushButton2.clicked.connect(self.on_pushButton2_clicked)
            self.newWindow = Second()
            #self.timer = QBasicTimer()
            #self.step=0
            #self.calctime=1000
    
            layout1=QHBoxLayout()
            layout1.addWidget(self.pushButton)
            layout1.addWidget(self.pushButton2)
    
            self.setLayout(layout1)
    
    
        def on_pushButton_clicked(self):
            self.newWindow.show()
            self.calc()
            self.newWindow.close()
    
        def calc(self):
            sleep(3)
    
    
        def on_pushButton2_clicked(self):
            self.newWindow.close()
    
    if __name__ == '__main__':
        app = QtWidgets.QApplication(sys.argv)
        main = First()
        main.show()
        sys.exit(app.exec_())
    
[/code]

これを実行することで、次のようなGUIが作成されます。  
[![画像](https://i.stack.imgur.com/wiIPd.png)](https://i.stack.imgur.com/wiIPd.png)  
ここで、計算に3秒かかるとして、「Open
Me」のボタンを押すとcalc関数を実行している間、「計算中」と書かれた別ウィンドウが表示されるように書いたつもりです。しかし、実際に実行すると計算の3秒間、真っ白な別ウィンドが表示されただけでした。どのように直せば計算中にSecondクラスで書いたウィンドウが表示されるのでしょうか。


CC BY-SA 4.0
2019-01-22T23:21:52.877
52221
2019-01-24T00:51:37.990
2019-01-23T01:37:08.060
19110
26529
question
python python3 pyqt5
pyqt5で計算中に別のウィンドウを表示したい


**コメント後**

`sleep(3)`を外せばいいかなと思ったのですが、適当な`for`文を`calc()`関数に入れて実行したら同じ現象が発生しました。恐らく私と同じように、`for`文かwhileループを実行し、PyQt5本来のイベントが取られているのだろうと思います。こういう時、`Qt`では別の計算を別のプロセスに任せて行う事ができる便利な方法が用意されています。

以下のコードをご覧ください。  
キーポイントは、`QtWidgets.QApplication.processEvents()`です。  
本来プログラムは一つのプロセスで全てを行うため、計算をするためにループに入ると、  
その間はユーザーは処理が終わるのを待たなくてはいけません。しかし、このコードを使えば、  
その計算処理だけを別プロセスで実行することが出来、しかも本来のプロセスで行うよりも  
圧倒的な速さで並行処理することが出来ます。巨大なデータをファイルから吸い出したい  
時なんかにも重宝します。ある場合とない場合で、処理の違いを確認してみてください。  
結果としてはこれでできるのですが、書き方のルールは2つないといけないんじゃなかった  
かな。他にも`QThread`とか、マルチスレッド処理なんかも、こういう時のためのものだと思います。

[code]

    import sys
    from PyQt5 import*
    from PyQt5.QtWidgets import *
    from PyQt5.QtGui import *
    from PyQt5.QtCore import *
    from PyQt5 import QtGui,QtCore, QtWidgets
    import time
    from time import sleep
    
    
    class Second(QtWidgets.QWidget):
        def __init__(self, parent=None):
            super(Second, self).__init__(parent)
            #Setting a title, locating and sizing the window
            self.title = 'My Second Window'
            self.left = 200
            self.top = 200
            self.width = 500
            self.height = 500
            self.setWindowTitle(self.title)
            self.setGeometry(self.left, self.top, self.width, self.height)
            lbl = QtWidgets.QLabel("計算中")
    
            layout1=QHBoxLayout()
            layout1.addWidget(lbl)
            self.setLayout(layout1)
    
    
    class First(QtWidgets.QWidget):
        def __init__(self, parent=None):
            super(First, self).__init__(parent)
            self.title = 'My First Window'
            self.left = 100
            self.top = 100
            self.width = 500
            self.height = 500
            self.setWindowTitle(self.title)
            self.setGeometry(self.left, self.top, self.width, self.height)
            self.pushButton = QtWidgets.QPushButton("Open Me", self)
            self.pushButton2 = QtWidgets.QPushButton("close", self)
            self.pushButton.clicked.connect(self.on_pushButton_clicked)
            self.pushButton2.clicked.connect(self.on_pushButton2_clicked)
            self.newWindow = Second()
    #        self.newWindow.setAttribute(QtCore.Qt.WA_ShowWithoutActivating)
            #self.timer = QBasicTimer()
            #self.step=0
            #self.calctime=1000
    
            layout1=QHBoxLayout()
            layout1.addWidget(self.pushButton)
            layout1.addWidget(self.pushButton2)
    
            self.setLayout(layout1)
    
    
        def on_pushButton_clicked(self):
            self.newWindow.show()
            QtWidgets.QApplication.processEvents()
            j = self.calc()
            QtWidgets.QApplication.processEvents()
            self.newWindow.close()
            print("the result of calculation is",j)
        def calc(self):
            j = 0        
            for i in range(100000):                
                j += i
            return j   
    
        def on_pushButton2_clicked(self):
            self.newWindow.close()
    
    if __name__ == '__main__':
        app = QtWidgets.QApplication(sys.argv)
        main = First()
        main.show()
        sys.exit(app.exec_())
    
[/code]

* * *

**以前**

toma さんのされているコードは、ウィジェットの表示、`calc`関数でコードの実行を3秒間止める。  
そして`close`するという意味なので、肝心の表示したいウィジェットが、3秒間実行をストップされていることになります。以下のようにコードを書き換えられて見てください。  
`QtCore.QTimer`を使った例です。`PySide`からの情報ですが、意図通りに動作すると思います。

参考文献は[こちら](https://pyside.github.io/docs/pyside/PySide/QtCore/QTimer.html#PySide.QtCore.PySide.QtCore.QTimer.setInterval)です。

[code]

    import sys
    from PyQt5 import*
    from PyQt5.QtWidgets import *
    from PyQt5.QtGui import *
    from PyQt5.QtCore import *
    from PyQt5 import QtGui,QtCore, QtWidgets
    import time
    from time import sleep
    
    
    class Second(QtWidgets.QWidget):
        def __init__(self, parent=None):
            super(Second, self).__init__(parent)
            #Setting a title, locating and sizing the window
            self.title = 'My Second Window'
            self.left = 200
            self.top = 200
            self.width = 500
            self.height = 500
            self.setWindowTitle(self.title)
            self.setGeometry(self.left, self.top, self.width, self.height)
            lbl = QtWidgets.QLabel("計算中")
    
            layout1=QHBoxLayout()
            layout1.addWidget(lbl)
            self.setLayout(layout1)
    
    
    class First(QtWidgets.QWidget):
        def __init__(self, parent=None):
            super(First, self).__init__(parent)
            self.title = 'My First Window'
            self.left = 100
            self.top = 100
            self.width = 500
            self.height = 500
            self.setWindowTitle(self.title)
            self.setGeometry(self.left, self.top, self.width, self.height)
            self.pushButton = QtWidgets.QPushButton("Open Me", self)
            self.pushButton2 = QtWidgets.QPushButton("close", self)
            self.pushButton.clicked.connect(self.on_pushButton_clicked)
            self.pushButton2.clicked.connect(self.on_pushButton2_clicked)
            self.newWindow = Second()
            #self.timer = QBasicTimer()
            #self.step=0
            #self.calctime=1000
    
            layout1=QHBoxLayout()
            layout1.addWidget(self.pushButton)
            layout1.addWidget(self.pushButton2)
    
            self.setLayout(layout1)
    
    
        def on_pushButton_clicked(self):
            self.newWindow.show()
            self.calc()
    
    
        def calc(self):
            QtCore.QTimer.singleShot(3000,self.newWindow.close)
    
    
        def on_pushButton2_clicked(self):
            self.newWindow.close()
    
    if __name__ == '__main__':
        app = QtWidgets.QApplication(sys.argv)
        main = First()
        main.show()
        sys.exit(app.exec_())
    
[/code]


CC BY-SA 4.0
2019-01-23T10:35:52.003
52260
2019-01-24T00:51:37.990
2019-01-24T00:51:37.990
24284
24284
52221
answer