dfcsdf
dfcsdf

Reputation: 309

calling script when click button

I have a program, this is the simple idea of it. First i run main_window.py it will open sub_window.py this sub_window have 2 buttons Run and Stop.

When i click Run button i need to run hello.py script and close Sub Window GUI same as when i clicked stop i need to stop hello.py script and close Sub Window GUI.

my current code gives me "NameError: name 'Dialog' is not defined" error.

this is main_window.py code

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

this is sub_window.py code

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

this is hello.py code

import time

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

Upvotes: 0

Views: 75

Answers (1)

eyllanesc
eyllanesc

Reputation: 243955

First of all you should not modify the .py generated by pyuic as indicated by the warning of the generated file and the docs so you have to restore those files by running the pyuic command again.

Considering the above, then you must create a main.py where the logic is implemented. On the other hand it is not considered good practice to use exec() so in that case you must modify "hello.py" so that the infinite loop is encapsulated in a function. You also have to keep in mind that an infinite loop cannot be executed in the same GUI thread, so you must execute it in a secondary thread:

main.py

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

hello.py

import time


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

In the case that hello.py cannot be modified or exec() must be used then you must create a function that executes that task:

main.py

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

Upvotes: 2

Related Questions