L
L
L_I_Z2018-05-12 13:31:20
Python
L_I_Z, 2018-05-12 13:31:20

What to change so that the interface is not blocked?

I wrote a small program that creates an additional thread in which the ping command is executed, after which the data is displayed on the screen. I can not understand why the interface is blocked, although the similar console code on python\threading is not blocked. Tell me what's wrong in the code? I assume that I used signals\slots incorrectly.
About the code:
create a Worker(QThread) class
add a runping signal
in the main class
pingFromOS(ip) method creates a ping process and returns the result
OnPing() method -- called on the thread via runping.connect()

Code here
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from subprocess import Popen,PIPE
import sys


lock = QReadWriteLock()

class Worker(QThread):
    runping = pyqtSignal()
    def __init__(self,parent = None ):
        QThread.__init__(self,parent)

    def run(self):
        self.runping.emit()

class MainWindow(QMainWindow):
    def __init__(self,*args,**kwargs):
        super(MainWindow,self).__init__(*args,**kwargs)
        self.initUI()

    def initUI(self):
        self.width = 600
        self.height = 600
        self.resize(self.width,self.height)
        self.center()
        self.ipField = QLineEdit(self)
        self.ipField.setText('127.1.1.0')
        self.ipField.setGeometry(10,10,100,25)
        self.button = QPushButton("ping",self)
        self.button.setGeometry(120,10,100,25)
        self.button.clicked.connect(self.onPressPing)
        self.console = QPlainTextEdit(self)
        self.console.setGeometry(5,50,self.width-10,self.height-60)
        self.setWindowTitle('Ping from os')
        self.w = Worker()
        self.w.runping.connect(self.OnPing)
        self.show()

    def onPressPing(self):
        self.w.run()


    def OnPing(self):
        lock.lockForWrite()
        ip = self.ipField.text()
        lock.unlock()
        res  = self.pingFromOS('localhost')
        lock.lockForWrite()
        self.console.appendPlainText(res)
        lock.unlock()


    def center(self):
        qr = self.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())

    def pingFromOS(self,ip):
        if ip is None:
            return b"ip is None"
        if ip=='':
            return b'ip is empty'
        pcArg=['ping','-c','9',ip]
        proc = Popen(pcArg,stdout=PIPE)
        out = proc.stdout.readlines()
        res = b""
        for row in out:
            res+=row
        proc.stdout.close()
        return res.decode()


if __name__ == '__main__':
    # Next, create an application object.
    QApplication.setDesktopSettingsAware(False)
    app = QApplication(sys.argv)
    # Show it.
    frame = MainWindow()
    # Start the event loop.
    sys.exit(app.exec_())

Answer the question

In order to leave comments, you need to log in

1 answer(s)
L
L_I_Z, 2018-05-12
@L_I_Z

I rewrote the code, now it works, the code is just an example. Locks and queues are not implemented.
Signals slots official. documentation
Example on github

spoiler
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from subprocess import Popen,PIPE
import sys


lock = QReadWriteLock()

class Worker(QThread):
    finished = pyqtSignal(str)
    def __init__(self,parent = None ):
        super(Worker,self).__init__(parent)

    def setIP(self,ip):
        self.ip = ip

    def pingFromOS(self,ip):
        if ip is None:
            return b"ip is None"
        if ip=='':
            return b'ip is empty'
        pcArg=['ping','-c','9',ip]
        proc = Popen(pcArg,stdout=PIPE)
        out = proc.stdout.readlines()
        res = b""
        for row in out:
            res+=row
        proc.stdout.close()
        return res.decode()


    def run(self):
        res  = self.pingFromOS(self.ip)
        self.finished.emit(res)



class MainWindow(QMainWindow):
    def __init__(self,*args,**kwargs):
        super(MainWindow,self).__init__(*args,**kwargs)
        self.initUI()

    def initUI(self):
        self.width = 600
        self.height = 600
        self.resize(self.width,self.height)
        self.center()
        self.ipField = QLineEdit(self)
        self.ipField.setText('127.1.1.0')
        self.ipField.setGeometry(10,10,100,25)
        self.button = QPushButton("ping",self)
        self.button.setGeometry(120,10,100,25)
        self.button.clicked.connect(self.onPressPing)
        self.console = QPlainTextEdit(self)
        self.console.setGeometry(5,50,self.width-10,self.height-60)
        self.setWindowTitle('Ping from os')
        self.show()

    def onPressPing(self):
        self.w = Worker()
        self.w.setIP(self.ipField.text())
        self.w.start()
        self.w.finished.connect(self.OnPing)


    def OnPing(self,res):
        self.console.appendPlainText(res)

    def center(self):
        qr = self.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())



if __name__ == '__main__':
    # Next, create an application object.
    QApplication.setDesktopSettingsAware(False)
    app = QApplication(sys.argv)
    # Show it.
    frame = MainWindow()
    # Start the event loop.
    sys.exit(app.exec_())

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question