-2

I have a program that requires several scripts to work together.

I managed to recreate the situation with a simplified example.

I have a main window (here called the StartTestUIv01) that is launched from another script (here called LaunchTestv01) so that variables and options can be added in my actual script. This main window have buttons that allows the user to open another window (here the BasicGraphUIv01) that itself uses data obtained by another script (here the LaunchBasicGraphv01).

So the script chain becomes like this: LaunchTestv01 -> StartTestUIv01 -> LaunchBasicGraphv01 -> BasicGraphUIv01

Here is the code for each: LaunchTestv01

## This will launch StartTestUIv01 with the button
from PyQt5 import QtWidgets
from PyQt5.QtCore import QProcess
from StartTestUIv01 import Ui_MainWindow

class Window(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super().__init__(parent=parent)
        self.setupUi(self)
        self.startGraph = QtWidgets.QAction('Launch Graph', self)
        
        self.w = None #Set the default value
        
        self.pushButton.clicked.connect(self.LaunchGraph)
    
    def LaunchGraph(self):
        if self.w is None:
            print("Working")
            # self.message("Executing Graph script")
            self.w = QProcess()
            self.w.finished.connect(self.closeGraph)
            self.w.start("python",['LaunchBasicGraphv01.py'])
    def closeGraph(self):
        print("Closing")
        # self.message("Graph script ended")
        self.w = None

if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    window = Window()
    window.show()
    sys.exit(app.exec())

StartTestUIv01

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(313, 196)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(30, 20, 261, 121))
        self.pushButton.setObjectName("pushButton")
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 313, 22))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.pushButton.setText(_translate("MainWindow", "START"))


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

LaunchBasicGraphv01

## This calculates values to insert in the Graph and displays that Window
from PyQt5 import QtWidgets
import BasicGraphUIv01 as ui
from pyqtgraph.Qt import QtCore
import numpy as np

x = np.arange(0,9)
y = np.random.randint(25, size=(9))

MainWindow = ui.QtWidgets.QMainWindow()
win = ui.Ui_MainWindow()
win.setupUi(MainWindow)
MainWindow.show()

# p0 = win.centralwidget.plot(x,y, pen='b')
p0 = win.graphWidget.plot(x,y, pen='y')

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

def update():
    y = np.random.randint(25, size=(9))
    p0.setData(x,y)

timer = QtCore.QTimer()
timer.timeout.connect(update)
timer.start(0)

BasicGraphUIv01

from PyQt5 import QtCore, QtGui, QtWidgets
from pyqtgraph import PlotWidget

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(473, 283)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.graphWidget = PlotWidget(self.centralwidget)
        self.graphWidget.setGeometry(QtCore.QRect(10, 10, 451, 211))
        self.graphWidget.setObjectName("graphWidget")
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 473, 22))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))


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

Now the obvious problem is that the chain doesn't start ! It seems that if I'm launching a script that is itself launching another window, it just doesn't happen!

What is the proper way of doing this ?

EDIT: So I got banned because this solved question wasn't good enough or something. To clarify; I was searching for the proper way of launching a PyQt script from another in the case where a python script is needed in-between to collect data.

Hope this helps.

Ad Ep
  • 23
  • 7
  • 1
    1. When using QProcess, it's always important to catch errors, otherwise you'll never know if (and what) it doesn't work as expected (for instance, connecto to the [`errorOccurred`](//doc.qt.io/qt-5/qprocess.html#errorOccurred) signal); 2. `ui.QtWidgets.QMainWindow()` in `LaunchBasicGraphv01` makes absolutely no sense at all: 1. `ui` is a global variable of a completely different process; 2. if you want to create a new QMainWindow, then just use `QtWidgets.QMainWindow`, that `ui` prefix makes absolutely no sense at all; 3. no QApplication was created there, so it would crash anyway. – musicamante Oct 21 '22 at 04:23
  • @musicamante I removed the ui variable as suggested, but even with no change, launching that script directly works just fine! Adding the creation of a QApplication there, like on the other scripts, opens two windows instead (one empty). If I can launch the script on it's own just fine, why wouldn't it launch from QProcess ? I also tried "execute" instead of "start", same result. – Ad Ep Oct 21 '22 at 15:11

1 Answers1

0

Solved it!

Thanks to @musicamante for the clues.

I only had to change the two launching scripts as so:

LaunchTestv01

## This will launch StartTestUIv01 with the button
from PyQt5 import QtWidgets
from PyQt5.QtCore import QProcess
from StartTestUIv01 import Ui_MainWindow

class Window(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super().__init__(parent=parent)
        self.setupUi(self)
        self.startGraph = QtWidgets.QAction('Launch Graph', self)
        
        self.w = None #Set the default value
        
        self.pushButton.clicked.connect(self.LaunchGraph)
    
    def LaunchGraph(self):
        if self.w is None:
            print("Working")
            # self.message("Executing Graph script")
            self.w = QProcess()
            self.w.finished.connect(self.closeGraph)
            self.w.execute('python',['LaunchBasicGraphv01.py'])
    def closeGraph(self):
        print("Closing")
        # self.message("Graph script ended")
        self.w = None

if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    window = Window()
    window.show()
    sys.exit(app.exec())

LaunchBasicGraphv01

from PyQt5 import QtWidgets
from BasicGraphUIv01 import Ui_MainWindow
from pyqtgraph.Qt import QtCore
import numpy as np

import sys
app = QtWidgets.QApplication(sys.argv)

x = np.arange(0,9)
y = np.random.randint(25, size=(9))

MainWindow = QtWidgets.QMainWindow()
win = Ui_MainWindow()
win.setupUi(MainWindow)
MainWindow.show()

# p0 = win.centralwidget.plot(x,y, pen='b')
p0 = win.graphWidget.plot(x,y, pen='y')

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

def update():
    y = np.random.randint(25, size=(9))
    p0.setData(x,y)

timer = QtCore.QTimer()
timer.timeout.connect(update)
timer.start(0)

if __name__ == '__main__':
    sys.exit(app.exec())

Thanks for the help !

Ad Ep
  • 23
  • 7