Pyqt5 QCoreApplication::exec:事件循环已在运行

2024-09-25 16:25:05 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个主窗口,它有一个按钮,当点击时会打开第二个窗口。第二个窗口包含mayavi图。每次我点击这个按钮都会显示一个错误

QCoreApplication::exec: The event loop is already running

我看过很多类似的问题,但我不能解决我的问题。在

主窗口的代码主界面.py

# Standard library imports
import re
import sys
import string
import inspect
import platform
import importlib
import ctypes
from os.path import abspath, join, dirname, realpath
from functools import wraps
import inspect
import matplotlib as mpl

# Local imports
from loadhistory.stresscorrection import DnvThicknessStressCorrection

# PyQt5 imports
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QMainWindow, QMessageBox, QListView, QWidget, QGridLayout
from PyQt5.QtGui import QPixmap

# Gui package import
import gui.design
import gui.resources
from gui.inputs import Inputs
from gui.filemanager import Filemanager
from gui.datawrapper import RunThread
from gui.mayaviwindow import MayaviWindow


class MainWindow(QMainWindow, gui.design.Ui_MainWindow):
    '''main window of the gui'''

    def __init__(self):
        QMainWindow.__init__(self)
        super().__init__()

        # Bypass needed to set taskbar icon if on windows
        if "Windows" in platform.system():
            myappid = 'LaboSoete'
            ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(myappid)

        self.inputs = Inputs(self)
        self.filemanager = Filemanager(self)
        self.mayaviwindow = MayaviWindow()
        self.setupUi(self)
        self.setWindowTitle("Endurance framework SafeLife")

        # Apply css stylesheet
        sshFile = "gui/stylesheet.css"
        with open(sshFile, "r") as fh:
            self.setStyleSheet(fh.read())

        # Initialize combobox design codes
        self.designcodes = self.inputs.code_dict()
        codes = list(self.designcodes.keys())
        self.design_code_combo.addItems(codes)
        self.design_cat_combo.addItems(self.designcodes[codes[0]])
        self.scrollbar_QComboBox(self.design_code_combo)
        self.scrollbar_QComboBox(self.design_cat_combo)

        # Initialize combobox Damagemodels
        module = importlib.import_module('damagemodels.damagemodels')
        for m in module.__dict__.values():
            if inspect.isclass(m):
                if 'damagemodels.damagemodels.' in str(m):
                    if not inspect.isabstract(m):
                        self.dmgBox.addItem(m.__name__)

        ###### Menubar ######
        self.actionSave.triggered.connect(self.filemanager.save)
        self.actionSave_as.triggered.connect(self.filemanager.save_as)
        self.actionLoad.triggered.connect(self.filemanager.load)
        self.actionOutput.triggered.connect(self.filemanager.change_output_dir)
        self.actionQuit.triggered.connect(self.close)

        ###### Button handeling ######
        self.loadhistory_btn.clicked.connect(self.inputs.lh_browse_file)
        self.odb_btn.clicked.connect(self.inputs.odb_browse_file)
        self.design_code_combo.currentIndexChanged.connect(
            self.inputs.design_combo_currentIndexChanged)
        self.btn_snCustom.clicked.connect(self.inputs.sn_browse_file)
        self.run_btn.clicked.connect(self.run_analysis)
        self.newBtn.clicked.connect(self.filemanager.new)
        self.abaqus_results_btn.clicked.connect(self.filemanager.open_odb_results)
        self.damageNnumber.textChanged.connect(lambda: self.check_numeric_entry(self.damageNnumber))
        self.hss_visualization_btn.clicked.connect(self.mayaviwindow.open_new_window)

        # DNV thickness correction initialization
        self.thicknessFrame.hide()
        self.design_cat_combo.currentIndexChanged.connect(self.show_thickness_correction)
        self.loadhistory_txt.textChanged.connect(self.loadhistory_txt_changed)
        self.radioBtn_snBasquin.toggled.connect(self.show_thickness_correction)
        self.radioBtn_snCustom.toggled.connect(self.show_thickness_correction)
        self.radioBtn_snDesign.toggled.connect(self.show_thickness_correction)
        self.radioBtn_snLog.toggled.connect(self.show_thickness_correction)

        ###### Tab/plot handeling ######

        # Loadhistory plot
        self.tabWidget.setCurrentIndex(0)
        self.loadhistory_txt.textChanged.connect(lambda: self.LhWidget.run(self))
        self.thicknessCorrCheckbox.toggled.connect(lambda: self.LhWidget.run(self))
        self.t_txt.textChanged.connect(lambda: self.LhWidget.run(self))
        self.tref_txt.textChanged.connect(lambda: self.LhWidget.run(self))
        self.k_txt.textChanged.connect(lambda: self.LhWidget.run(self))
        self.mscCheckBox.toggled.connect(lambda: self.LhWidget.run(self))
        self.mscSelectionBox.currentIndexChanged.connect(lambda: self.LhWidget.run(self))


        # Sncurve plot
        self.design_cat_combo.currentIndexChanged.connect(self.inputs.design_cat_combo_change)
        self.design_code_combo.currentIndexChanged.connect(self.inputs.design_combo_currentIndexChanged)
        self.sncurve_txt.textChanged.connect(lambda: self.SnWidget.run(self))
        self.radioBtn_snCustom.clicked.connect(lambda: self.SnWidget.run(self))
        self.radioBtn_snDesign.clicked.connect(lambda: self.SnWidget.run(self))
        self.radioBtn_snBasquin.clicked.connect(self.clear_sntxt_fields)
        self.radioBtn_snLog.clicked.connect(self.clear_sntxt_fields)
        self.Nf_txt.textChanged.connect(lambda: self.SnWidget.run(self))
        self.uts_txt.textChanged.connect(lambda: self.SnWidget.run(self))
        self.m1_txt.textChanged.connect(lambda: self.SnWidget.run(self))
        self.B1_txt.textChanged.connect(lambda: self.SnWidget.run(self))
        self.m2_txt.textChanged.connect(lambda: self.SnWidget.run(self))
        self.B2_txt.textChanged.connect(lambda: self.SnWidget.run(self))

        # HSS handeling
        self.hss_checkbox.toggled.connect(self.show_hss_image)
        self.hss_combobox.currentIndexChanged.connect(self.show_hss_image)
        self.hss_combobox.currentIndexChanged.connect(self.show_hide_hss_spinbox)

        ###### Output related ######
        self.hss_visualization_btn.hide()
        self.hideTab(3)
        self.abaqus_results_btn.hide()
        self.newBtn.hide()
        self.progressBar.hide()


    @staticmethod
    def eval_eq(equation):
        '''
        Check if the string 'equation' only contains allowable characters
        '''
        regex = re.compile(r'(\d+([.]|\*))?\d+(e|[.]|\*)?\d*(e|[.]|\*)?\d*?$')
        if (equation.endswith('e') or equation.endswith('.')) and re.match(regex, equation):
            return eval(equation[:-1])
        elif re.match(regex, equation) and equation.count('e') < 2:
            return eval(equation)
        else:
            raise ValueError(
                'Illegal expression used to define the S-N curve, only e^*'+string.digits+' allowed')

    def check_numeric_entry(self, myQlineEdit):
        '''
        For QlineEdit which can only contain numbers, check whether
        no non-numeric characters are entered
        '''
        if myQlineEdit.text().isdigit() or len(myQlineEdit.text()) < 1:
            return
        else:
            reply = QMessageBox.warning(self, 'TypeError', 'This field only allows for numeric entries')
            if reply == QMessageBox.Ok:
                myQlineEdit.setText(myQlineEdit.text()[:-1])
                return

    def loadhistory_txt_changed(self):
        '''
        If a loadhistory is selected the meanstresscorrection option
        becomes enabled
        '''
        if len(self.loadhistory_txt.text())>0:
            self.mscCheckBox.setEnabled(True)
        else:
            self.mscCheckBox.setDisabled(True)

    def show_thickness_correction(self):
        '''
        Determine whether or not the thickness_correction option should be shown and enabled.
        This is only the case when a DNV SN curve is selected
        '''
        if 'DNV' in self.design_code_combo.currentText() and self.radioBtn_snDesign.isChecked() and len(self.loadhistory_txt.text())>0:
            self.thicknessFrame.show()
            self.thicknessCorrCheckbox.setEnabled(True)
        else:
            self.thicknessFrame.hide()
            self.thicknessCorrCheckbox.setChecked(False)
            self.thicknessCorrCheckbox.setDisabled(True)

    def show_hss_image(self):
        if self.hss_checkbox.isChecked():
            filename = self.hss_combobox.currentText()
            filepath = abspath(join(dirname(realpath(__file__)), 'gui', 'icons', filename))
            pixmap = QPixmap(filepath)
            self.hss_imagelabel.setPixmap(pixmap)
            self.hss_imagelabel.show()
            self.tabWidget.setCurrentIndex(2)
        if not self.hss_checkbox.isChecked():
            self.hss_imagelabel.hide()


    def get_thickness_correction(self):
        '''
        Return a thickness correction object using the values from the
        gui to initialize the object
        '''
        if "DNV" in self.design_code_combo.currentText():
            tref = self.eval_eq(self.tref_txt.text())
            t = self.eval_eq(self.t_txt.text())
            k = self.eval_eq(self.k_txt.text())
            if k >= 1:
                reply = QMessageBox.warning(
                    self, 'ValueError', 'k needs to be less than one, please consult DNV-GL-RP203 for the correct values')
                if reply == QMessageBox.Ok or reply == QMessageBox.Cancel:
                    self.k_txt.clear()
                    return
                else: return
            return DnvThicknessStressCorrection(tref, t, k)

    def show_hide_hss_spinbox(self):
        '''
        hide the hss_spinbox and hss_t_label widgets if a hss method, that does not
        use the plate thickness to determine the extrapolation coords, is selected
        '''
        test = self.hss_combobox.currentText()
        lst = ['1', '2', '3']
        if any(x in test for x in lst):
            self.hss_spinbox.show()
            self.hss_t_label.show()
        else:
            self.hss_t_label.hide()
            self.hss_t_label.show()

    def scrollbar_QComboBox(self, combo):
        '''
        Add a scrollbar to QComboBoxes if the selected text is wider than
        the combobox
        '''
        view = QListView(combo)
        combo.setView(view)
        view.setTextElideMode(Qt.ElideNone)
        view.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)


    def closeEvent(self, event):
        '''
        Handle the event of the user wanting to close the application
        '''
        msgBox = QMessageBox()
        msgBox.setWindowTitle('Exit application?')
        msgBox.setText('Do you want to exit the application?')
        exit_btn = msgBox.addButton('Exit', QMessageBox.YesRole)
        save_exit_btn = msgBox.addButton('Save and Exit', QMessageBox.YesRole)
        cancel_btn = msgBox.addButton('Cancel', QMessageBox.RejectRole)
        msgBox.setEscapeButton(cancel_btn)

        msgBox.exec_()

        if msgBox.clickedButton() == exit_btn:
            event.accept()
        elif msgBox.clickedButton() == save_exit_btn:
            self.filemanager.save()
            event.accept()
        elif msgBox.clickedButton() == cancel_btn:
            event.ignore()



    def start_thread(self, thread):
        '''Pass all MainWindow attributes to the new thread and start the thread'''
        thread.progressBar = self.progressBar
        thread.loadhistory_txt = self.loadhistory_txt
        thread.loadhistory_btn = self.loadhistory_btn
        thread.odb_txt = self.odb_txt
        thread.odb_btn = self.odb_btn
        thread.dmgBox = self.dmgBox
        thread.dmax_box = self.dmax_box
        thread.radioBtn_snCustom = self.radioBtn_snCustom
        thread.radioBtn_snBasquin = self.radioBtn_snBasquin
        thread.radioBtn_snDesign = self.radioBtn_snDesign
        thread.sncurve_txt = self.sncurve_txt
        thread.btn_snCustom = self.btn_snCustom
        thread.design_cat_combo = self.design_cat_combo
        thread.design_code_combo = self.design_code_combo
        thread.mscCheckBox = self.mscCheckBox
        thread.mscSelectionBox = self.mscSelectionBox
        thread.calcLifetimeBox = self.calcLifetimeBox
        thread.calcLifetimeCheckBox = self.calcLifetimeCheckBox
        thread.damageNcheckBox = self.damageNcheckBox
        thread.damageNnumber = self.damageNnumber
        thread.newBtn = self.newBtn
        thread.m1_txt = self.m1_txt
        thread.B1_txt = self.B1_txt
        thread.m2_txt = self.m2_txt
        thread.B2_txt = self.B2_txt
        thread.uts_txt = self.uts_txt
        thread.Nf_txt = self.Nf_txt
        thread.SnWidget = self.SnWidget
        thread.LhWidget = self.LhWidget
        thread.Inputs = self.inputs
        thread.thicknessCorrCheckbox = self.thicknessCorrCheckbox
        thread.k_txt = self.k_txt
        thread.t_txt = self.t_txt
        thread.tref_txt = self.tref_txt
        thread.hss_spinbox = self.hss_spinbox
        thread.hss_combobox = self.hss_combobox
        thread.hss_checkbox = self.hss_combobox
        thread.start()

    def clear_sntxt_fields(self):
        '''Clear all text fields related to SN curve equations'''
        self.Nf_txt.clear()
        self.uts_txt.clear()
        self.m1_txt.clear()
        self.m2_txt.clear()
        self.B1_txt.clear()
        self.B2_txt.clear()

    def initialize(self):
        self.hss_visualization_btn.hide()
        self.run_btn.setDisabled(True)
        self.newBtn.hide()
        self.abaqus_results_btn.hide()
        self.hideTab(3)
        self.output_txt.clear()

    def finished(self):
        if self.hss_checkbox.isChecked():
            self.hss_visualization_btn.show()
        self.run_btn.setEnabled(True)
        self.newBtn.show()
        self.abaqus_results_btn.show()
        self.hide_progressbar()
        self.showTab(3)

    def show_progressbar(self):
        self.progressBar.show()

    def hide_progressbar(self):
        self.progressBar.hide()

    def clear_lhtxt(self):
        self.loadhistory_txt.clear()
        self.loadhistory_txt.setFocus()

    def clear_odbtxt(self):
        self.odb_txt.clear()
        self.odb_txt.setFocus()

    def clear_sncustomtxt(self):
        self.sncurve_txt.clear()
        self.sncurve_txt.setFocus()

    def show_messagebox(self, errortype, msg, methodname):
        reply = QMessageBox.warning(self, errortype, msg)
        if methodname is not "None":
            handle_error = getattr(self, methodname)
        if reply == QMessageBox.Ok:
            if 'handle_error' in locals():
                handle_error()
            return

    def dmg_curve_plot(self, Dplot, nNplot):
        self.DmgWidget.run(self, Dplot, nNplot)

    def hideTab(self, tabIndex):
        self.tabWidget.setTabEnabled(tabIndex, False)

    def showTab(self, tabIndex):
        self.tabWidget.setTabEnabled(tabIndex, True)

    def check_required_inputs(self):
        if "".__eq__(self.loadhistory_txt.text()) or "".__eq__(self.odb_txt.text()) \
            or not self.odb_txt.text().endswith('odb'):
            return False
        if self.radioBtn_snCustom.isChecked() and "".__eq__(self.sncurve_txt.text()):
            return False
        if self.radioBtn_snBasquin.isChecked() or self.radioBtn_snLog.isChecked():
            if ("".__eq__(self.m1_txt.text()) or "".__eq__(self.Nf_txt.text()) or \
               "".__eq__(self.uts_txt.text()) or "".__eq__(self.B1_txt.text())):
                return False
        return True

    def run_analysis(self):

        mpl.pyplot.close(fig="all")

        if self.check_required_inputs() is False:
            self.show_messagebox('IOError', 'Please check all required fields', "None")
            return

        self.run_thread = RunThread(self)
        self.run_thread.initialize.connect(self.initialize)
        self.run_thread.clear_lhtxt.connect(self.clear_lhtxt)
        self.run_thread.clear_odbtxt.connect(self.clear_odbtxt)
        self.run_thread.clear_odbtxt.connect(self.clear_sncustomtxt)
        self.run_thread.show_messagebox.connect(self.show_messagebox)

        self.run_thread.show_progressbar.connect(self.show_progressbar)
        self.run_thread.hide_progressbar.connect(self.hide_progressbar)

        self.run_thread.finished.connect(self.finished)
        self.run_thread.output.connect(self.filemanager.to_output)
        self.run_thread.dmg_curve_plot.connect(self.dmg_curve_plot)
        self.start_thread(self.run_thread)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())

第二个窗口的代码mayaviwindow.py

^{pr2}$

有人能给我解释一下是什么问题吗?在

Edit changing the class MayaviWindow to inherit from QWidget instead of QMainwindow did not solve the problem

class MayaviWindow(QtGui.QWidget):
    def open_new_window(self):
        self.container = QtGui.QWidget()
        self.container.setWindowTitle("Hot spot stress")
        layout = QtGui.QGridLayout(self.container)
        mayavi_widget = MayaviQWidget(self.container)
        layout.addWidget(mayavi_widget, 1, 1)
        self.container.show()

Tags: therunimportselftxtifdefshow