Reputation: 309
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
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