1 回答
TA贡献1735条经验 获得超5个赞
for-loop 或 sleep 等耗时的任务会阻塞 GUI 事件循环,导致窗口冻结。在这些情况下,解决方案是在另一个线程中执行该任务并通过信号在线程之间发送信息
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_())
添加回答
举报