python - QLabel 未显示在 QWidget 窗口中

标签 python python-3.x pyqt pyqt5

我有下面的一段代码,它给出了下面的图片。

enter image description here

import os
import numpy as np
from PyQt5 import QtCore, QtWidgets
import sqlite3


class Ui_Form():

    def __init__(self):

        #Checking if the loading database is in place
        if not os.path.exists("loading_database.db"):
            QtWidgets.QMessageBox.information(None,'Loading database missing','Loading database has not been found. Creation of a new one will be attempted')
            self.loadingDatabaseCreator()
            QtWidgets.QMessageBox.information(None,'Successful','Loading database succesfully created')

        #Asking the user for the input file to be parsed and the number of componenets determined
        filePath, _ = QtWidgets.QFileDialog.getOpenFileName(None, "Select input model","","Input deck (*.inp)","*.inp")
        filePath = str(filePath)

        self.pleaseWait = waitWindow()
        self.pleaseWait.show()

        #If no file has been inputted the script will exit
        if not filePath:
            exit()
        else:
            #If a file has been inputted now it will be opened and a list containing all the lines will be created
            readInputFile(filePath)

           #Searching in the file for all the valid components. We disregards collectors containing RBE3 elements
           #as they don't require fatigue analysis
            self.pleaseWait.close()
            for line in model_file:
                if "*ELEMENT," in line and "DCOUP3D" not in line:
                    #If a valid collector is found it will be added to the array of type numpy.
                    try:
                        #Checks if the collector has already been recorded as different element types partaining of the same component
                        #will be specified in different collectors win the input deck
                        if not line.split("ELSET=")[1][:-1] in self.collector_array:
                            self.collector_array = np.concatenate((self.collector_array,np.array([line.split("ELSET=")[1][:-1]])),axis=0)
                    except:
                        self.collector_array = np.array([line.split("ELSET=")[1][:-1]])
            #model_file_obj.close

            #Testing to see if the array has been created indicating the presence of at least one entity
            #This will be useful if the user loads a load deck instead of a model as they have the same .inp extension
            try:
                self.collector_array
            except:
                QtWidgets.QMessageBox.information(None,'Error','File contains no element collectors')

            #Creating the initial Window
            self.mainWidget = QtWidgets.QWidget()
            self.mainWidget.resize(500, 500)
            self.mainWidget.setWindowFlags(self.mainWidget.windowFlags() | QtCore.Qt.MSWindowsFixedSizeDialogHint)
            self.mainWidget.setWindowTitle("nCode analysis set-up")

            #Creating the top level grid layout
            self.mainGrid = QtWidgets.QGridLayout(self.mainWidget)

            #Creating the boxes which will describe the analysis to be written in the .dcl file
            self.analysis_type_label = QtWidgets.QLabel(self.mainWidget)
            self.analysis_type_label.setText("Type of analysis")
            self.mainGrid.addWidget(self.analysis_type_label,0,0)
            self.analysis_type_combo = QtWidgets.QComboBox(self.mainWidget)
            self.analysis_type_combo.addItems(["Fatigue","Proof plus fatigue"])
            self.mainGrid.addWidget(self.analysis_type_combo,0,1,1,2)
            self.load_deck_type_label = QtWidgets.QLabel(self.mainWidget)
            self.load_deck_type_label.setText("Type of fatigue deck")
            self.mainGrid.addWidget(self.load_deck_type_label,1,0)
            self.load_deck_type_combo = QtWidgets.QComboBox(self.mainWidget)
            self.load_deck_type_combo.addItems(["Regen braking","No regen braking"])
            self.mainGrid.addWidget(self.load_deck_type_combo,1,1,1,2)
            self.analysis_engine_type_label = QtWidgets.QLabel(self.mainWidget)
            self.analysis_engine_type_label.setText("Analysis Engine")
            self.mainGrid.addWidget(self.analysis_engine_type_label,2,0)
            self.analysis_engine_type_combo = QtWidgets.QComboBox(self.mainWidget)
            self.analysis_engine_type_combo.addItems(["EN analysis","SN analysis"])
            self.mainGrid.addWidget(self.analysis_engine_type_combo,2,1,1,2)

            #Creating a scrolable area to accommodate for a large number of components with possible lenghty names
            self.scrollArea = QtWidgets.QScrollArea(self.mainWidget)
            #The line below is absolutely required to make the scrollable area work.
            self.scrollArea.setWidgetResizable(True)
            self.mainGrid.addWidget(self.scrollArea,3,0,1,3)
            self.secondaryWidget = QtWidgets.QWidget()
            self.scrollArea.setWidget(self.secondaryWidget)
            self.secondaryGrid = QtWidgets.QGridLayout(self.secondaryWidget)

            #This bit creates the necessary object for every componenet that was found in the input deck.
            #The globals method is used to dynamically assign objects to variables for subsequent manipulation.
            for i in range(0, self.collector_array.shape[0]):
                globals()["self.materialLabel"+str(i)] = QtWidgets.QLabel(self.secondaryWidget)
                globals()["self.materialLabel"+str(i)].setText(self.collector_array[i]+" material")
                self.secondaryGrid.addWidget(globals()["self.materialLabel"+str(i)],2+i,0)
                globals()["self.materialName"+str(i)] = QtWidgets.QLineEdit(self.secondaryWidget)
                globals()["self.materialName"+str(i)].setPlaceholderText("Drop material name here")
                globals()["self.materialName"+str(i)].setFixedWidth(150)
                self.secondaryGrid.addWidget(globals()["self.materialName"+str(i)],2+i,1)
                globals()["self.materialPickingButton"+str(i)] = QtWidgets.QPushButton(self.secondaryWidget)
                globals()["self.materialPickingButton"+str(i)].setText("Pick material")
                globals()["self.materialPickingButton"+str(i)].clicked.connect(self.material_lookup)
                self.secondaryGrid.addWidget(globals()["self.materialPickingButton"+str(i)],2+i,2)

            #Creates the button that connects to the DLC_writer function
            self.createDCL = QtWidgets.QPushButton(self.mainWidget)
            self.createDCL.setText("Create DCL")
            self.mainGrid.addWidget(self.createDCL,4,0,1,3)
            self.createDCL.clicked.connect(self.DCL_guide)
            self.mainWidget.show()

class waitWindow(QtWidgets.QDialog):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Info")
        self.resize(600,200)
        self.VLayout = QtWidgets.QVBoxLayout(self)
        self.message = QtWidgets.QLabel(self)
        self.message.setFixedWidth(550)
        self.message.setText("Please wait while input file is being read")
        self.VLayout.addWidget(self.message)

class readInputFile():
    def __init__(self,filePath):
        model_file_obj = open(filePath, "r")
        globals()['model_file'] = model_file_obj.readlines()
        model_file_obj.close

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    ui = Ui_Form()
    sys.exit(app.exec_())

问题是此窗口中缺少我的文本标签。我把它做得很大,以防标签没有足够的空间来完全显示,但在那种情况下,我认为它会显示它有空间的内容。希望有人知道为什么。

编辑:我已经包含了 Ui_Form 的整个 init 函数。我所有的问题都是由这一点引起的,其余的工作正常。

最佳答案

您正在查看的窗口不是 pleaseWait 窗口而是 mainWidget 窗口。

上面的解释假设:

  • 读取的文件很小,所以 pleaseWait 窗口会立即打开和关闭,因此作为同步操作 Qt 将没有时间执行它,并且对于用户来说窗口永远不会显示。对于这种情况,解决方案是为用户提供合理的时间来查看窗口。

  • 文件很大,读取时间长会阻塞eventloop,会导致显示一个窗口等任务无法执行,为避免阻塞任务必须在另一个线程中执行。

结合这两种解决方案,我们获得以下代码:

import os
from functools import partial
from PyQt5 import QtCore, QtWidgets


class Worker(QtCore.QObject):
    finished = QtCore.pyqtSignal()
    contentChanged = QtCore.pyqtSignal(list)

    @QtCore.pyqtSlot(str)
    def read_file(self, fileName):
        with open(fileName, "r") as model_file_obj:
            model_file = model_file_obj.readlines()
            print(model_file)
            self.contentChanged.emit(model_file)
        self.finished.emit()


class MainWidget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.resize(500, 500)
        self.setWindowFlags(
            self.windowFlags() | QtCore.Qt.MSWindowsFixedSizeDialogHint
        )
        self.setWindowTitle("nCode analysis set-up")
        mainGrid = QtWidgets.QGridLayout(self)

        thread = QtCore.QThread(self)
        thread.start()

        self.m_worker = Worker()
        self.m_worker.moveToThread(thread)
        self.m_worker.contentChanged.connect(self.get_content)

    def launch_task(self):
        if not os.path.exists("loading_database.db"):
            QtWidgets.QMessageBox.information(
                None,
                "Loading database missing",
                "Loading database has not been found. Creation of a new one will be attempted",
            )
            # self.loadingDatabaseCreator()
            QtWidgets.QMessageBox.information(
                None, "Successful", "Loading database succesfully created"
            )
        fileName, _ = QtWidgets.QFileDialog.getOpenFileName(
            None, "Select input model", "", "Input deck (*.inp)", "*.inp"
        )
        self.pleaseWait = WaitWindow()
        self.pleaseWait.show()
        self.m_worker.finished.connect(self.pleaseWait.close)
        wrapper = partial(self.m_worker.read_file, fileName)
        # Launch the task in a reasonable time for the window to show
        QtCore.QTimer.singleShot(100, wrapper)  #

    @QtCore.pyqtSlot(list)
    def get_content(self, lines):
        print(lines)


class WaitWindow(QtWidgets.QDialog):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Info")
        self.resize(600, 200)
        layout = QtWidgets.QVBoxLayout(self)
        self.message = QtWidgets.QLabel(self)
        self.message.setFixedWidth(550)
        self.message.setText("Please wait while input file is being read")
        layout.addWidget(self.message)


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = MainWidget()
    w.show()
    w.launch_task()
    sys.exit(app.exec_())

更新:

import os
from functools import partial
import numpy as np
from PyQt5 import QtCore, QtWidgets


class MainWidget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.resize(500, 500)
        self.setWindowFlags(
            self.windowFlags() | QtCore.Qt.MSWindowsFixedSizeDialogHint
        )
        self.setWindowTitle("nCode analysis set-up")

        self.wait_window = WaitWindow()

        thread = QtCore.QThread(self)
        thread.start()

        self.m_worker = Worker()
        self.m_worker.moveToThread(thread)
        self.m_worker.new_content_signal.connect(self.get_content)

        # Creating the top level grid layout
        mainGrid = QtWidgets.QGridLayout(self)

        self.analysis_type_label = QtWidgets.QLabel(self)
        self.analysis_type_label.setText("Type of analysis")
        mainGrid.addWidget(self.analysis_type_label, 0, 0)
        self.analysis_type_combo = QtWidgets.QComboBox(self)
        self.analysis_type_combo.addItems(["Fatigue", "Proof plus fatigue"])
        mainGrid.addWidget(self.analysis_type_combo, 0, 1, 1, 2)
        self.load_deck_type_label = QtWidgets.QLabel(self)
        self.load_deck_type_label.setText("Type of fatigue deck")
        mainGrid.addWidget(self.load_deck_type_label, 1, 0)
        self.load_deck_type_combo = QtWidgets.QComboBox(self)
        self.load_deck_type_combo.addItems(
            ["Regen braking", "No regen braking"]
        )
        mainGrid.addWidget(self.load_deck_type_combo, 1, 1, 1, 2)
        self.analysis_engine_type_label = QtWidgets.QLabel(self)
        self.analysis_engine_type_label.setText("Analysis Engine")
        mainGrid.addWidget(self.analysis_engine_type_label, 2, 0)
        self.analysis_engine_type_combo = QtWidgets.QComboBox(self)
        self.analysis_engine_type_combo.addItems(["EN analysis", "SN analysis"])
        mainGrid.addWidget(self.analysis_engine_type_combo, 2, 1, 1, 2)

        # Creating a scrolable area to accommodate for a large number of components with possible lenghty names
        self.scrollArea = QtWidgets.QScrollArea(self)
        # The line below is absolutely required to make the scrollable area work.
        self.scrollArea.setWidgetResizable(True)
        mainGrid.addWidget(self.scrollArea, 3, 0, 1, 3)
        self.secondaryWidget = QtWidgets.QWidget()
        self.scrollArea.setWidget(self.secondaryWidget)
        self.secondaryGrid = QtWidgets.QGridLayout(self.secondaryWidget)

        self.createDCL = QtWidgets.QPushButton(self)
        self.createDCL.setText("Create DCL")
        mainGrid.addWidget(self.createDCL, 4, 0, 1, 3)

    def start_task(self):
        if not os.path.exists("loading_database.db"):
            QtWidgets.QMessageBox.information(
                None,
                "Loading database missing",
                "Loading database has not been found. Creation of a new one will be attempted",
            )
            # self.loadingDatabaseCreator()
            QtWidgets.QMessageBox.information(
                None, "Successful", "Loading database succesfully created"
            )

        filePath, _ = QtWidgets.QFileDialog.getOpenFileName(
            None, "Select input model", "", "Input deck (*.inp)", "*.inp"
        )
        if filePath:
            self.wait_window.show()
            self.m_worker.finished.connect(self.wait_window.close)
            wrapper = partial(self.m_worker.read_file, filePath)
            # Launch the task in a reasonable time for the window to show
            QtCore.QTimer.singleShot(100, wrapper)

    @QtCore.pyqtSlot(int, str)
    def get_content(self, i, content):
        label = QtWidgets.QLabel("{} material".format(content))
        linedit = QtWidgets.QLineEdit(placeholderText="Drop material name here")
        linedit.setFixedWidth(150)
        button = QtWidgets.QPushButton("Pick material")

        self.secondaryGrid.addWidget(label, 2 + i, 0)
        self.secondaryGrid.addWidget(linedit, 2 + i, 1)
        self.secondaryGrid.addWidget(button, 2 + i, 2)


class WaitWindow(QtWidgets.QDialog):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Info")
        self.resize(600, 200)
        layout = QtWidgets.QVBoxLayout(self)
        self.message = QtWidgets.QLabel()
        self.message.setFixedWidth(550)
        self.message.setText("Please wait while input file is being read")
        layout.addWidget(self.message)


class Worker(QtCore.QObject):
    finished = QtCore.pyqtSignal()
    new_content_signal = QtCore.pyqtSignal(int, str)

    @QtCore.pyqtSlot(str)
    def read_file(self, fileName):
        i = 0
        collector_array = []
        with open(fileName, "r") as model_file_obj:
            for line in model_file_obj.readlines():
                if "*ELEMENT," in line and "DCOUP3D" not in line:
                    t = line.split("ELSET=")[1][:-1]
                    if t not in collector_array:
                        self.new_content_signal.emit(i, t)
                        QtCore.QThread.msleep(10)
                        collector_array.append(t)
                        i += 1
        self.finished.emit()


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = MainWidget()
    w.show()
    w.start_task()
    sys.exit(app.exec_())

关于python - QLabel 未显示在 QWidget 窗口中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56681070/

相关文章:

python-3.x - 重新索引系列会在 Pandas 中返回 NaN

python - 在线程操作期间避免 PyQt5 GUI 卡住?

python - 在 GUI 嵌入图中使用 matplotlib Cursor 小部件

python - 使用 PyQT/PySide 的类似 Metro 的全屏浏览器

python - 编写 python for 循环的更短方法

python - 在类中重复函数

python - 为什么这个记忆化的 Euler14 实现在 Raku 中比 Python 慢得多?

python - 如何对每个组的条目进行计数和求和?

python - 是否可以在 python 中使用 `with` 打开任意数量的项目?

python - 如何抓取带有无限滚动条的网站?