Skip to content Skip to sidebar Skip to footer

Program Stops Responding After Clicking A Button

I'm trying to make my first ever program, a port scanner that shows all the open ports on a remote server, I've gotten it to work in CLI (thanks to the internet) but decided to mak

Solution 1:

Time-consuming tasks such as for-loop or sleep block the GUI event-loop causing the window to freeze. In these cases the solution is to execute that task in another thread and send the information between the threads through signals

import sys
import time
import socket
from functools import partial

from PyQt5.QtCore import pyqtSignal, pyqtSlot, QObject, QThread, QTimer
from PyQt5.QtWidgets import (
    QApplication,
    QGridLayout,
    QLabel,
    QLineEdit,
    QMainWindow,
    QPlainTextEdit,
    QPushButton,
    QWidget,
)


class SocketWorker(QObject):
    messageChanged = pyqtSignal(str)

    @pyqtSlot(str)
    def start_task(self, ip):
        socket.gethostbyname(ip)
        try:
            for port in range(0, 65536):
                socketprofile = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                result = socketprofile.connect_ex((ip, port))
                if result == 0:
                    self.messageChanged.emit("Port {} Is open".format(port))
                socketprofile.close()
        except socket.gaierror:
            self.messageChanged.emit("Hostname could not be resolved")
            time.sleep(5)
            sys.exit()
        except socket.error:
            self.messageChanged.emit("Couldn't connect to server")
            time.sleep(5)
            sys.exit()


class App(QMainWindow):
    def __init__(self):
        super().__init__()
        self.title = "PPort"
        self.left = 10
        self.top = 10
        self.width = 800
        self.height = 400
        self.initUI()

    def initUI(self):
        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)

        self.textbox = QLineEdit()
        self.button = QPushButton("Scan!")
        self.textbox2 = QPlainTextEdit(readOnly=True)

        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        grid_layout = QGridLayout(central_widget)
        grid_layout.addWidget(QLabel("Enter Target Address:"), 0, 0)
        grid_layout.addWidget(self.textbox, 1, 0)
        grid_layout.addWidget(self.button, 1, 1)
        grid_layout.addWidget(QLabel("Output:"), 2, 0)
        grid_layout.addWidget(self.textbox2, 3, 0, 1, 2)

        self.button.clicked.connect(self.on_click)

        thread = QThread(self)
        thread.start()
        self.socker_worker = SocketWorker()
        self.socker_worker.moveToThread(thread)
        self.socker_worker.messageChanged.connect(self.textbox2.appendPlainText)

    @pyqtSlot()
    def on_click(self):
        textboxValue = self.textbox.text()
        wrapper = partial(self.socker_worker.start_task, textboxValue)
        QTimer.singleShot(0, wrapper)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    ex = App()
    ex.show()
    sys.exit(app.exec_())

Post a Comment for "Program Stops Responding After Clicking A Button"