Reputation: 67
First, I would like to show you what works so far. Below is a simple GUI built with the same principles as the one that causes problems. It has a button and when you click it a counter increases.
#!/usr/bin/python3.5
import sys
from PyQt5 import QtWidgets
class GUI(QtWidgets.QWidget):
def __init__(self):
QtWidgets.QWidget.__init__(self)
self.initGUI()
self.behaviours()
self.counter = 0
def initGUI(self):
self.button = QtWidgets.QPushButton("Button")
self.label = QtWidgets.QLabel()
self.box = QtWidgets.QVBoxLayout()
self.box.addWidget(self.button)
self.box.addWidget(self.label)
self.setLayout(self.box)
self.show()
def behaviours(self):
self.button.clicked.connect(self.add)
def add(self):
self.counter = self.counter + 1
self.label.setText(str(self.counter))
app = QtWidgets.QApplication(sys.argv)
ex = GUI()
sys.exit(app.exec_())
I am able to execute the script from the Linux terminal with the following command:
python3 TestGUI.py
The GUI opens as intended and I can interact with the button.
As soon as a subprocess gets included in the script, like the one below, the GUI does still open but it is completely black and non-responsive.
p1 = subprocess.Popen("onedrive", stdout = subprocess.PIPE, shell = True)
(output, err) = p1.communicate()
I think that there is a problem when you use the terminal to execute a python script which itself executes commands in the terminal.
Do you have any idea on how this problem can be solved?
Thank you very much for your support.
Upvotes: 2
Views: 748
Reputation: 243907
You should not use Popen since the communicate()
method is blocking, instead use QProcess
:
#!/usr/bin/python3.5
from PyQt5 import QtCore, QtWidgets
class GUI(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.initGUI()
self.behaviours()
def initGUI(self):
self.button = QtWidgets.QPushButton("Button")
self.label = QtWidgets.QLabel()
box = QtWidgets.QVBoxLayout(self)
box.addWidget(self.button)
box.addWidget(self.label)
self.show()
def behaviours(self):
self._onedrive_process = QtCore.QProcess(self)
self._onedrive_process.setProcessChannelMode(QtCore.QProcess.MergedChannels)
self._onedrive_process.readyReadStandardOutput.connect(
self.on_readyReadStandardOutput
)
self._onedrive_process.setProgram("onedrive")
self.button.clicked.connect(self.connect_to_onedrive)
@QtCore.pyqtSlot()
def connect_to_onedrive(self):
self._onedrive_process.start()
@QtCore.pyqtSlot()
def on_readyReadStandardOutput(self):
result = self._onedrive_process.readAllStandardOutput()
print(result)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
ex = GUI()
sys.exit(app.exec_())
Update:
If you want to pass options to the command you must use setArguments()
:
from PyQt5 import QtCore, QtGui, QtWidgets
class OneDriveManager(QtCore.QObject):
logChanged = QtCore.pyqtSignal(str)
def __init__(self, parent=None):
super().__init__(parent)
self._process = QtCore.QProcess(self)
self._process.readyReadStandardOutput.connect(self.on_readyReadStandardOutput)
self._process.setProgram("onedrive")
def launch(self, options=None):
self._process.setArguments(options)
if self._process.state() != QtCore.QProcess.NotRunning:
self._process.kill()
self._process.start()
def help(self):
self.launch(["--help"])
def synchronize(self):
self.launch(["--synchronize"])
@QtCore.pyqtSlot()
def on_readyReadStandardOutput(self):
res = self._process.readAllStandardOutput().data().decode()
self.logChanged.emit(res)
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self._onedrive_manager = OneDriveManager(self)
help_button = QtWidgets.QPushButton("Help")
help_button.clicked.connect(self._onedrive_manager.help)
synchronize_button = QtWidgets.QPushButton("Synchronize")
synchronize_button.clicked.connect(self._onedrive_manager.synchronize)
log_plaintextedit = QtWidgets.QPlainTextEdit()
self._onedrive_manager.logChanged.connect(log_plaintextedit.setPlainText)
lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(help_button)
lay.addWidget(synchronize_button)
lay.addWidget(log_plaintextedit)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
Upvotes: 1