如果我知道它存在,为啥我 pyqt5 告诉我这个小部件不存在?

Posted

技术标签:

【中文标题】如果我知道它存在,为啥我 pyqt5 告诉我这个小部件不存在?【英文标题】:why i pyqt5 tell me this widget does not exist if i know it does?如果我知道它存在,为什么我 pyqt5 告诉我这个小部件不存在? 【发布时间】:2020-03-01 12:30:33 【问题描述】:
# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'messagerGUI.ui'
#
# Created by: PyQt5 UI code generator 5.13.0
#
# WARNING! All changes made in this file will be lost!
# ""

from PyQt5 import QtCore, QtGui, QtWidgets
import socket
import threading


class Ui_MainWindow(object):
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    header = 12
    connections = []
    ip = socket.gethostname()
    port = 1234
    connections_allowed = 3
    sock.bind((ip, port))
    sock.listen(connections_allowed)
    new_message = False

    def start(self):
        while True:
            self.conn, self.addr = self.sock.accept()
            threading.Thread(target=self.receive_data, args=[
                             self.conn], daemon=True).start()
            self.connections.append(self.conn)

    def receive_data(self, conn):
        self.reply = ""
        while True:
            try:

                message_lenth = conn.recv(self.header)
                lenth_of_message = message_lenth.decode("utf-8")

                if not message_lenth:
                    break

                elif message_lenth:
                    data = conn.recv(int(lenth_of_message))
                    self.reply = data.decode("utf-8")

                    print(self.reply)
                    self.new_message = True

                    for connection in self.connections:
                        if connection != conn:
                            connection.send(message_lenth.encode("utf-8"))
                            connection.send(self.reply.encode("utf-8"))

            except:
                break

    def packing_data_lenth(self, text):
        return len(text) * 4

    def send_data(self, data):
        try:
            for connection in self.connections:
                connection.send(
                    bytes(str(self.packing_data_lenth(data)), "utf-8"))
                connection.send(bytes(data, "utf-8"))
        except:
            pass


    def setupUi(self, MainWindow):
        threading.Thread(target=self.start, daemon=True).start()
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(499, 367)
        MainWindow.setStyleSheet("background-color: #113e4a;")
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.horizontalLayout = QtWidgets.QHBoxLayout(self.centralwidget)
        self.horizontalLayout.setContentsMargins(5, 5, 5, 5)
        self.horizontalLayout.setSpacing(5)
        self.horizontalLayout.setObjectName("horizontalLayout")

        self.info = QtWidgets.QWidget(self.centralwidget)
        sizePolicy = QtWidgets.QSizePolicy(
            QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Minimum)
        sizePolicy.setHeightForWidth(
            self.info.sizePolicy().hasHeightForWidth())
        self.info.setSizePolicy(sizePolicy)
        self.info.setMinimumSize(QtCore.QSize(178, 357))
        self.info.setStyleSheet("background-color: #429178;\n"
                                "border-radius: 2px;")
        self.info.setObjectName("info")
        self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.info)

        self.verticalLayout_3.setObjectName("verticalLayout_3")
        self.label_3 = QtWidgets.QLabel(self.info)
        self.label_3.setObjectName("label_3")
        self.verticalLayout_3.addWidget(self.label_3)
        spacerItem = QtWidgets.QSpacerItem(
            20, 317, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
        self.verticalLayout_3.addItem(spacerItem)
        self.horizontalLayout.addWidget(self.info)

        self.message_widget()

        self.chat_area = QtWidgets.QWidget(self.centralwidget)
        sizePolicy = QtWidgets.QSizePolicy(
            QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
        sizePolicy.setHeightForWidth(
            self.chat_area.sizePolicy().hasHeightForWidth())
        self.chat_area.setSizePolicy(sizePolicy)
        self.chat_area.setMinimumSize(QtCore.QSize(306, 0))
        self.chat_area.setStyleSheet("background-color: #429178;")
        self.chat_area.setObjectName("chat_area")
        self.verticalLayout = QtWidgets.QVBoxLayout(self.chat_area)
        self.verticalLayout.setContentsMargins(2, 2, 2, 2)
        self.verticalLayout.setSpacing(1)
        self.verticalLayout.setObjectName("verticalLayout")

        self.messages_area = QtWidgets.QScrollArea(self.chat_area)
        sizePolicy = QtWidgets.QSizePolicy(
            QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.MinimumExpanding)
        sizePolicy.setHeightForWidth(
            self.messages_area.sizePolicy().hasHeightForWidth())
        self.messages_area.setSizePolicy(sizePolicy)
        self.messages_area.setMinimumSize(QtCore.QSize(0, 259))
        self.messages_area.setStyleSheet("background-color: #113e4a;")
        self.messages_area.setWidgetResizable(True)
        self.messages_area.setObjectName("messages_area")

        self.scrollAreaWidgetContents = QtWidgets.QWidget()
        self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 300, 316))
        sizePolicy = QtWidgets.QSizePolicy(
            QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum)
        sizePolicy.setHeightForWidth(
            self.scrollAreaWidgetContents.sizePolicy().hasHeightForWidth())
        self.scrollAreaWidgetContents.setSizePolicy(sizePolicy)
        self.scrollAreaWidgetContents.setLayoutDirection(QtCore.Qt.LeftToRight)
        self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")
        self.verticalLayout_2 = QtWidgets.QVBoxLayout(
            self.scrollAreaWidgetContents)
        self.verticalLayout_2.setSizeConstraint(
            QtWidgets.QLayout.SetNoConstraint)
        self.verticalLayout_2.setSpacing(6)
        self.verticalLayout_2.setObjectName("verticalLayout_2")

        spacerItem1 = QtWidgets.QSpacerItem(
            20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.MinimumExpanding)
        self.verticalLayout_2.addItem(spacerItem1)
        self.messages_area.setWidget(self.scrollAreaWidgetContents)
        self.verticalLayout.addWidget(self.messages_area)

        self.input_area = QtWidgets.QWidget(self.chat_area)
        self.input_area.setMinimumSize(QtCore.QSize(0, 30))
        self.input_area.setObjectName("input_area")
        self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.input_area)
        self.horizontalLayout_2.setContentsMargins(1, 1, 1, 1)
        self.horizontalLayout_2.setSpacing(1)
        self.horizontalLayout_2.setObjectName("horizontalLayout_2")
        self.userInput = QtWidgets.QLineEdit(self.input_area)
        sizePolicy = QtWidgets.QSizePolicy(
            QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Minimum)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.userInput.sizePolicy().hasHeightForWidth())
        self.userInput.setSizePolicy(sizePolicy)
        self.userInput.setMinimumSize(QtCore.QSize(22, 32))
        font = QtGui.QFont()
        font.setPointSize(12)
        self.userInput.setFont(font)
        self.userInput.setStyleSheet("background-color: rgb(17, 62, 74);\n"
                                     "color: #d0e8ce;\n"
                                     "border: 0px;")
        self.userInput.setInputMethodHints(QtCore.Qt.ImhNone)
        self.userInput.setFrame(True)
        self.userInput.setDragEnabled(True)
        self.userInput.setPlaceholderText("Type a message")
        self.userInput.setObjectName("userInput")
        self.horizontalLayout_2.addWidget(self.userInput)
        self.sendButton = QtWidgets.QPushButton(self.input_area)
        sizePolicy = QtWidgets.QSizePolicy(
            QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.sendButton.sizePolicy().hasHeightForWidth())
        self.sendButton.setSizePolicy(sizePolicy)
        self.sendButton.setMinimumSize(QtCore.QSize(12, 32))
        font = QtGui.QFont()
        font.setPointSize(12)
        self.sendButton.setFont(font)
        self.sendButton.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor))
        self.sendButton.setMouseTracking(True)
        self.sendButton.setObjectName("sendButton")
        self.sendButton.clicked.connect(self.get_user_input)
        self.horizontalLayout_2.addWidget(self.sendButton)
        self.verticalLayout.addWidget(self.input_area)
        self.horizontalLayout.addWidget(self.chat_area)
        MainWindow.setCentralWidget(self.centralwidget)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

在这部分(函数 message_widget)我得到一个错误:

self.widget = QtWidgets.QWidget(self.scrollAreaWidgetContents) AttributeError: 'Ui_MainWindow' 对象没有属性 'scrollAreaWidgetContents'

即使我在 get_user_input 函数中做了类似的事情, 我知道代码是一团糟,但唯一不工作的部分是这部分, 套接字服务器和客户端都正常工作,我测试了打印 终端收到文本,所以是的,我想知道为什么会出现此错误?

    def message_widget(self):
        self.widget = QtWidgets.QWidget(self.scrollAreaWidgetContents)
        sizePolicy = QtWidgets.QSizePolicy(
            QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum)
        sizePolicy.setHeightForWidth(
            self.widget.sizePolicy().hasHeightForWidth())
        self.widget.setSizePolicy(sizePolicy)
        self.widget.setMinimumSize(QtCore.QSize(158, 25))
        self.widget.setLayoutDirection(QtCore.Qt.LeftToRight)
        self.widget.setStyleSheet(
            "background-color: #d35439;\n" "border-radius: 4px;")
        self.widget.setObjectName("widget")
        self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.widget)
        self.horizontalLayout_3.setObjectName("horizontalLayout_3")

        self.label = QtWidgets.QLabel(self.widget)
        self.label.setScaledContents(True)
        self.label.setObjectName("label")
        self.label.text(self.reply)
        self.horizontalLayout_3.addWidget(self.label)
        self.verticalLayout_2.addWidget(self.widget)

    def get_user_input(self):
        self.user_msg = self.userInput.text()

        threading.Thread(target=self.send_data, args=[
                         self.user_msg], daemon=True).start()

        self.widget_2 = QtWidgets.QWidget(self.scrollAreaWidgetContents)
        sizePolicy = QtWidgets.QSizePolicy(
            QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
        sizePolicy.setHeightForWidth(
            self.widget_2.sizePolicy().hasHeightForWidth())
        self.widget_2.setSizePolicy(sizePolicy)
        self.widget_2.setMinimumSize(QtCore.QSize(182, 25))
        self.widget_2.setLayoutDirection(QtCore.Qt.RightToLeft)
        self.widget_2.setStyleSheet("background-color: rgb(236, 172, 55);\n"
                                    "border-radius: 4px;")
        self.widget_2.setObjectName("widget_2")
        self.horizontalLayout_4 = QtWidgets.QHBoxLayout(self.widget_2)
        self.horizontalLayout_4.setObjectName("horizontalLayout_4")

        self.label_2 = QtWidgets.QLabel(self.widget_2)
        self.label_2.setLayoutDirection(QtCore.Qt.RightToLeft)
        self.label_2.setAlignment(
            QtCore.Qt.AlignRight | QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter)
        self.label_2.setObjectName("label_2")
        self.label_2.setText(self.user_msg)
        self.horizontalLayout_4.addWidget(self.label_2)
        self.verticalLayout_2.addWidget(self.widget_2)
        self.userInput.setText("")

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "PadoMessager"))
        self.label_3.setText(_translate("MainWindow", "Server"))
        self.sendButton.setText(_translate("MainWindow", "Send"))
        self.sendButton.setShortcut(_translate("MainWindow", "Return"))


if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())

【问题讨论】:

【参考方案1】:

认为它存在,但是当你调用message_widget()时它还不存在。

事实上,你在之前这一行调用了那个函数:

self.scrollAreaWidgetContents = QtWidgets.QWidget()

因此,如果您至少在创建该小部件之后 放置该函数,它可以工作。

不幸的是,您的代码还存在其他严重问题。

最重要的是你正在修改 pyuic 的输出来创建你的程序,这是非常不鼓励的(并且开头的 WARNING 消息应该是一个提示)。

从 UI 文件生成的 Python 脚本应该绝不被编辑,而是在您的实际程序文件中用作导入。最明显的原因是,一旦您想在 ui 中进行一些更改,您就会发现自己陷入了试图将新生成的代码与您目前编写的代码合并的混乱中。

要了解更多信息,请阅读有关 using Designer 的文档。

代码中的其他问题:

Qt中的threading应该尽量配合Qt自带的QThread使用; UI 对象不应被外部线程访问或修改;为此,您必须使用 QThread,并使用信号和插槽与主 Qt 线程进行通信; QLabel.text() 不接受参数,因为它用于访问文本属性;要设置标签的文本,请使用setText()

【讨论】:

不客气,但我宁愿简单地检查一下我的答案中接受的标志;-)

以上是关于如果我知道它存在,为啥我 pyqt5 告诉我这个小部件不存在?的主要内容,如果未能解决你的问题,请参考以下文章

推荐题目(我不会做,如果有人明白了一定要告诉我,万分感谢)

PyQt5,让用户调整小部件的大小

通过 pyqt5 动态添加和删除小部件

为啥我的方法不是我的方法删除存在的表?

有人能告诉我为啥这个方法会进入无限循环吗?

有人可以告诉我为啥 foreachloop 不将 i 作为 1,这是一个用于检查它是不是存在于数组中的变量 [关闭]