亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

單擊按鈕后程序停止響應

單擊按鈕后程序停止響應

胡說叔叔 2022-06-28 17:35:34
我正在嘗試制作我的第一個程序,一個顯示遠程服務器上所有開放端口的端口掃描器,我已經讓它在 CLI 中工作(感謝互聯網),但決定制作一個 GUI(Qt5)它。我希望 textbox2 在輸入 IP 地址并單擊“掃描!”后輸出所有打開的端口,顯然程序在單擊后不會崩潰。這是復制問題的相關代碼from PyQt5.QtWidgets import QMainWindow, QApplication, QWidget, QPushButton, QAction, QLineEdit, QMessageBox, QPlainTextEdit, QVBoxLayout, QLabelfrom PyQt5.QtGui import QIconfrom PyQt5.QtCore import pyqtSlot, Qtimport socketimport timeimport sysclass 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.label = QLabel('Enter Target Address:', self)        self.label.move(50, -110)        self.label.resize(300, 300)        self.label2 = QLabel('Output:', self)        self.label2.move(50, 80)        self.label2.resize(300, 300)        self.textbox = QLineEdit(self)        self.textbox.move(50, 60)        self.textbox.resize(540, 30)        self.textbox2 = QPlainTextEdit(self)        self.textbox2.move(50, 250)        self.textbox2.resize(700, 100)        self.textbox2.setReadOnly(True)        self.button = QPushButton('Scan!', self)        self.button.move(620, 60)        self.button.clicked.connect(self.on_click)        self.show()textbox2中沒有顯示錯誤,令我感到奇怪的是,即使我self.textbox2.appendPlainText用print()替換,它仍然沒有在vscode終端中輸出任何錯誤消息。但是,輸入無效的 IP 地址會顯示 gaierror(無法解析主機),而不是在 textbox2 中,而是在終端中,與輸入有效 IP 地址(8.8.8.8、192.168.0.1)時它總是崩潰的情況相比. 我懷疑我使用 if/for/try 錯誤地使其循環,但我真的看不出我做錯了什么,因為我幾乎不知道我作為新手在做什么。
查看完整描述

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_())


查看完整回答
反對 回復 2022-06-28
  • 1 回答
  • 0 關注
  • 144 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號