【问题标题】:PyQt Messagebox is crashingPyQt 消息框正在崩溃
【发布时间】:2019-07-27 13:27:47
【问题描述】:

我正在开发一个文件传输应用程序,包括它的服务器。当我尝试在两个客户端之间发送文件时,我想确保接收客户端会收到一个消息框,例如“x 用户想要发送文件。你接受吗?”。到目前为止,我已经完成了这项工作,但是当我出于测试目的单击“是”按钮时,“是”按钮消失了,接收客户端崩溃了。当我试图在控制台上查看错误时,我看到它在接收客户端上是“QObject::setParent: 无法设置父级,新父级在不同的线程中”。我在网站上搜索了错误,但无法理解解决方案。你能告诉我如何解决这个问题吗?

代码:

from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
import sys
import socket
import json
import base64
from threading import Thread
from time import sleep

username = "admin"
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(("144.122.86.204",5000)) #Fill here later
s.send(username.encode("utf-8"))

app = QApplication(sys.argv)
window = QWidget()
window.setWindowTitle("File Sharing")
window.setGeometry(0,0,500,350)

contactlist= QListWidget(window)
contactlist.setGeometry(5,5,100,250)


def add():
    user, ok = QInputDialog.getText(window, "Add a contact","Enter a 
username:")
    if ok:
        contactlist.addItem(str(user))

def send():
    target_user=contactlist.currentItem().text()
    name = QFileDialog.getOpenFileName(window, 'Open File')
    file = open(name[0], 'rb')
    base64_bytes = base64.b64encode(file.read())
    base64_string = base64_bytes.decode('utf-8')
    data= {"FRM": username, "TO": target_user, "DATA": base64_string}
    encoded_data = json.dumps(data).encode()
    s.sendall(encoded_data)

def receive():
    while True:
        data = s.recv(1024)
        if data:
            if 'wants to send you a file. Do you accept that?' in 
data.decode('utf-8'):
                choice = QMessageBox.question(window, 'FileTransfer', 
data.decode('utf-8'),QMessageBox. Yes|QMessageBox. No)
                if choice == QMessageBox.Yes:
                    s.send("CONFIRMED".encode('utf-8'))




t = Thread(target=receive)
t.start()

add_contact = QPushButton("Add a Contact", window)
add_contact.setGeometry(5,270,100,50)
add_contact.clicked.connect(add)

send_file = QPushButton("Send a File",window)
send_file.setGeometry(110,270,200,50)
send_file.clicked.connect(send)



window.show()

sys.exit(app.exec())

【问题讨论】:

标签: python sockets pyqt pyqt5


【解决方案1】:

您的问题是 QMessageBox 是在 Qt 禁止的另一个线程中创建的,并且它的父窗口位于 Qt 也禁止的主线程中。这种情况下的一般方法是通过线程安全的信号、事件、元对象等将辅助线程的信息发送到主线程,并且在主线程中创建GUI(在您的情况下为QMessageBox)。

在这种情况下,它可能会很复杂,因此最好使用 Qt 的 QtNetwork 模块,而不是使用上述模块,该模块将向您发送通过信号接收到的信息,从而使 while 循环变得不必要,因此使用线程。

import json
import base64

from PyQt5 import QtCore, QtGui, QtWidgets, QtNetwork


class Widget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(Widget, self).__init__(parent)
        self.initUi()

        self.m_username = "admin"

        self.m_socket = QtNetwork.QTcpSocket(self)

        self.m_socket.connected.connect(self.onConnected)
        self.m_socket.readyRead.connect(self.onReadyRead)

        self.m_socket.connectToHost("144.122.86.204", 5000)

    @QtCore.pyqtSlot()
    def onConnected(self):
        username = "admin"
        self.m_socket.write(self.m_username.encode("utf-8"))
        self.m_socket.flush()

    @QtCore.pyqtSlot()
    def onReadyRead(self):
        data = self.m_socket.readAll().data()
        text = data.decode("utf-8")
        if "wants to send you a file. Do you accept that?" in text:
            choice = QtWidgets.QMessageBox.question(
                self,
                "FileTransfer",
                text,
                QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
            )
            if choice == QtWidgets.QMessageBox.Yes:
                self.m_socket.write("CONFIRMED".encode("utf-8"))

    @QtCore.pyqtSlot()
    def add_contant(self):
        user, ok = QtWidgets.QInputDialog.getText(
            self, "Add a contact", "Enter a username:"
        )
        if ok:
            self.m_listwidget.addItem(user)

    @QtCore.pyqtSlot()
    def send_file(self):
        if self.m_socket.state() != QtNetwork.QAbstractSocket.ConnectedState:
            print("Socket not connected")
            return

        item = self.m_listwidget.currentItem()
        if item is None:
            print("Not current item")
            return

        target_user = item.text()
        filename, _ = QtWidgets.QFileDialog.getOpenFileName(self, "Open File")
        with open(filename, "rb") as file:
            base64_bytes = base64.b64encode(file.read())
            base64_string = base64_bytes.decode("utf-8")
            data = {"FRM": self.m_username, "TO": target_user, "DATA": base64_string}
            encoded_data = json.dumps(data).encode()
            self.m_socket.write(encoded_data)
            self.m_socket.flush()

    def initUi(self):
        self.m_listwidget = QtWidgets.QListWidget()
        self.m_listwidget.setFixedWidth(100)

        self.m_add_button = QtWidgets.QPushButton("Add a Contact")
        self.m_add_button.clicked.connect(self.add_contant)
        self.m_add_button.setFixedSize(100, 50)
        self.m_send_file = QtWidgets.QPushButton("Send a File")
        self.m_send_file.clicked.connect(self.send_file)
        self.m_send_file.setFixedSize(200, 50)

        hlay = QtWidgets.QHBoxLayout()
        hlay.addWidget(self.m_listwidget)
        hlay.addStretch()

        hlay2 = QtWidgets.QHBoxLayout()
        hlay2.addWidget(self.m_add_button)
        hlay2.addWidget(self.m_send_file)
        hlay2.addStretch()

        vlay = QtWidgets.QVBoxLayout(self)
        vlay.addLayout(hlay)
        vlay.addLayout(hlay2)

        self.resize(500, 350)

    def closeEvent(self, event):
        if self.m_socket.state() == QtNetwork.QAbstractSocket.ConnectedState:
            self.m_socket.disconnectFromHost()
        super(Widget, self).closeEvent(event)


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = Widget()
    w.show()
    sys.exit(app.exec())

【讨论】:

  • 有没有不禁止这个的GUI框架?
猜你喜欢
  • 1970-01-01
  • 2019-08-16
  • 1970-01-01
  • 1970-01-01
  • 2017-03-20
  • 1970-01-01
  • 2015-10-02
  • 1970-01-01
  • 2012-01-25
相关资源
最近更新 更多