gpt4 book ai didi

python - 从 Linux 终端执行包含子进程的 PyQt5 GUI 会导致 GUI 出现黑屏并卡住

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:13:21 32 4
gpt4 key购买 nike

首先,我想向您展示目前有效的方法。下面是一个简单的 GUI,其构建原理与导致问题的 GUI 相同。它有一个按钮,当您单击它时,计数器会增加。

#!/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_())

我可以使用以下命令从 Linux 终端执行脚本:

python3 TestGUI.py

GUI 按预期打开,我可以与按钮交互。

一旦脚本中包含子进程,如下所示,GUI 仍会打开,但它完全是黑色且没有响应。

p1 = subprocess.Popen("onedrive", stdout = subprocess.PIPE, shell = True)
(output, err) = p1.communicate()

我认为当您使用终端执行 python 脚本时会出现问题,该脚本本身会在终端中执行命令。

你知道如何解决这个问题吗?

非常感谢您的支持。

最佳答案

你不应该使用 Popen,因为 communicate()方法是阻塞的,请改用 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_())

更新:

如果你想将选项传递给命令,你必须使用 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_())

关于python - 从 Linux 终端执行包含子进程的 PyQt5 GUI 会导致 GUI 出现黑屏并卡住,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57981552/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com