首页 > 解决方案 > 单击按钮时调用脚本

问题描述

我有一个程序,这是它的简单想法。首先我运行 main_window.py 它将打开 sub_window.py 这个 sub_window 有 2 个按钮运行和停止。

当我单击运行按钮时,我需要运行 hello.py 脚本并关闭子窗口 GUI,就像我单击停止时一样,我需要停止 hello.py 脚本并关闭子窗口 GUI。

我当前的代码给了我“NameError: name 'Dialog' is not defined”错误。

这是 main_window.py 代码

from PyQt5 import QtCore, QtGui, QtWidgets
import sub_window

class Ui_MainWindow(object):

    def sub(self):
        self.subwin = QtWidgets.QDialog()
        self.ui =  sub_window.Ui_Dialog()
        self.ui.setupUi(self.subwin)  
        self.subwin.show()

    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(397, 157)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.btnClick = QtWidgets.QPushButton(self.centralwidget)
        self.btnClick.setGeometry(QtCore.QRect(100, 50, 161, 51))
        self.btnClick.setObjectName("btnClick")
        MainWindow.setCentralWidget(self.centralwidget)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)

        ################### Butten Event ##################################
        self.btnClick.clicked.connect(self.sub)


        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "Main Window"))
        self.btnClick.setText(_translate("MainWindow", "Click"))


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

这是 sub_window.py 代码

from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_Dialog(object):

    def funRun(self):
        Dialog.hide()
        exec(open("hello.py").read())

    def setupUi(self, Dialog):
        Dialog.setObjectName("Dialog")
        Dialog.resize(332, 108)
        self.btnRun = QtWidgets.QPushButton(Dialog)
        self.btnRun.setGeometry(QtCore.QRect(50, 40, 101, 31))
        self.btnRun.setObjectName("btnRun")
        self.btnStop = QtWidgets.QPushButton(Dialog)
        self.btnStop.setGeometry(QtCore.QRect(180, 40, 101, 31))
        self.btnStop.setObjectName("btnStop")

        self.retranslateUi(Dialog)

        ################### Butten Event ##################################
        self.btnRun.clicked.connect(self.funRun)

        QtCore.QMetaObject.connectSlotsByName(Dialog)

    def retranslateUi(self, Dialog):
        _translate = QtCore.QCoreApplication.translate
        Dialog.setWindowTitle(_translate("Dialog", "Sub Window"))
        self.btnRun.setText(_translate("Dialog", "Run"))
        self.btnStop.setText(_translate("Dialog", "Stop"))


if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    Dialog = QtWidgets.QDialog()
    ui = Ui_Dialog()
    ui.setupUi(Dialog)
    Dialog.show()
    sys.exit(app.exec_())

这是 hello.py 代码

import time

while True:
    print("Hello")
    time.sleep(1)

标签: pythonpyqt5

解决方案


首先,您不应该修改由 pyuic 生成的 .py,如生成的文件和文档的警告所示,因此您必须通过再次运行 pyuic 命令来恢复这些文件。

考虑到上述情况,您必须创建一个 main.py 来实现逻辑。另一方面,使用它不是很好的做法,exec()因此在这种情况下,您必须修改“hello.py”,以便将无限循环封装在一个函数中。您还必须记住,无限循环不能在同一个 GUI 线程中执行,因此您必须在辅助线程中执行它:

主文件

from PyQt5 import QtCore, QtGui, QtWidgets
from main_window import Ui_MainWindow
from sub_window import Ui_Dialog
import threading
from hello import task


class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.setupUi(self)

        self.dialog = Dialog()
        self.btnClick.clicked.connect(self.dialog.show)


class Dialog(QtWidgets.QDialog, Ui_Dialog):
    def __init__(self, parent=None):
        super(Dialog, self).__init__(parent)
        self.setupUi(self)
        self.btnRun.clicked.connect(self.run)

    @QtCore.pyqtSlot()
    def run(self):
        threading.Thread(target=task, daemon=True).start()
        self.hide()


if __name__ == "__main__":
    import sys

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

你好.py

import time


def task():
    while True:
        print("Hello")
        time.sleep(1)

如果 hello.py 无法修改或exec()必须使用,那么您必须创建一个执行该任务的函数:

主文件

from PyQt5 import QtCore, QtGui, QtWidgets
from main_window import Ui_MainWindow
from sub_window import Ui_Dialog
import threading


def task():
    with open("hello.py") as f:
        exec(f.read())


class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.setupUi(self)

        self.dialog = Dialog()
        self.btnClick.clicked.connect(self.dialog.show)


class Dialog(QtWidgets.QDialog, Ui_Dialog):
    def __init__(self, parent=None):
        super(Dialog, self).__init__(parent)
        self.setupUi(self)
        self.btnRun.clicked.connect(self.run)

    @QtCore.pyqtSlot()
    def run(self):
        threading.Thread(target=task, daemon=True).start()
        self.hide()


if __name__ == "__main__":
    import sys

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

推荐阅读