从另一个 Python 进程更新 Python GUI
Posted
技术标签:
【中文标题】从另一个 Python 进程更新 Python GUI【英文标题】:Update Python GUI from another Python process 【发布时间】:2015-07-29 07:19:45 【问题描述】:我已经在谷歌上搜索了将近两天,以找到有关我在 Python 中遇到的问题的答案。而且我完全迷茫和困惑我应该如何解决我的问题。
这就是我想要做的。我有一个 Python 文件名 mymain.py(GUI) 并且它正在运行并处于活动状态,我想通过在终端中运行此命令来更改和更新我的 GUI 中的 Qlabel 文本
sudo python myarg.py -i [任意数字]
其中 [number] 是用户定义的。例如我在终端运行这段代码
sudo python myarg.py -i 5
GUI 中的 Qlabel 文本应更改为 5。
这是我的代码:
mymain.py
from PyQt4 import QtCore, QtGui
import PyQt4
import sys
import os
from time import sleep
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
_fromUtf8 = lambda s: s
class Ui_MainWindow(QtGui.QMainWindow):
updatenumber = QtCore.pyqtSignal(int)
def __init__(self):
QtGui.QWidget.__init__(self)
self.setupUi(self)
self.num = 0
def setupUi(self, MainWindow):
MainWindow.setObjectName(_fromUtf8("MainWindow"))
MainWindow.resize(536, 537)
self.centralwidget = QtGui.QWidget(MainWindow)
self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
self.gridLayout_2 = QtGui.QGridLayout(self.centralwidget)
self.gridLayout_2.setObjectName(_fromUtf8("gridLayout_2"))
self.gridLayout = QtGui.QGridLayout()
self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
self.lblNumber = QtGui.QLabel(self.centralwidget)
font = QtGui.QFont()
font.setFamily(_fromUtf8("DS-Digital"))
font.setPointSize(300)
self.lblNumber.setFont(font)
self.lblNumber.setObjectName(_fromUtf8("lblNumber"))
self.lblNumber.setAlignment(QtCore.Qt.AlignCenter)
self.gridLayout.addWidget(self.lblNumber)
self.gridLayout_2.addLayout(self.gridLayout, 0, 0, 1, 1)
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(QtGui.QApplication.translate("MainWindow", "MainWindow", None, QtGui.QApplication.UnicodeUTF8))
self.lblNumber.setText(QtGui.QApplication.translate("MainWindow", "0", None, QtGui.QApplication.UnicodeUTF8))
self.thread = Thread()
self.thread.update.connect(self.lblNumber.text)
class Thread(QtCore.QThread):
update = QtCore.pyqtSignal(str)
def init(self, parent=app):
QtCore.QThread.init(self,parent)
self.num = ''
def run(self):
self.update.emit(self.num)
if __name__=='__main__':
app = QtGui.QApplication(sys.argv)
ex = Ui_MainWindow()
ex.show()
sys.exit(app.exec_())
myarg.py
from mymain import Thread
import sys, getopt
from PyQt4 import QtCore, QtGui
import PyQt4
def main(argv):
ctr = ''
try:
opts, args = getopt.getopt(argv,"hi:",["ifile="])
except getopt.GetoptError:
print 'sigarg.py -i <ctr>'
sys.exit(1)
for opt, arg in opts:
if opt == '-h':
print 'sigarg.py -i <ctr>'
sys.exit()
elif opt in ("-i", "--ifile"):
ctr = arg
m = Thread()
m.num = ctr
m.start()
if __name__ == "__main__":
main(sys.argv[1:])
我使用的 Python 版本是 2.7,我的机器是 Raspberry Pi。
【问题讨论】:
为什么要这样做?你所问的并不完全是微不足道的。您需要设置某种进程间通信(您正在启动一个单独的进程来更新非常不寻常的 GUI) @three_pineapples。这实际上很常见 - 例如,在同一窗口中打开所有文档的选项卡式编辑器/浏览器。 【参考方案1】:您的用例与单实例应用程序非常相似。在第一次调用命令时,会显示主窗口;然后所有后续调用只是将它们的参数发送到正在运行的应用程序。
他们有很多方法可以做到这一点,但最简单的方法之一是使用本地套接字。为了让您了解它是如何工作的,这里有一个基于我曾经写过的 osd 音量控制的演示:
import sys, getopt
from PyQt4 import QtCore, QtGui, QtNetwork
QtGui.QApplication.setApplicationName('foobar')
QtGui.QApplication.setApplicationVersion('0.1')
class Window(QtGui.QLabel):
def __init__(self, name):
super(Window, self).__init__()
self.server = QtNetwork.QLocalServer(self)
self.server.newConnection.connect(self.handleMessage)
if not self.server.listen(name):
raise RuntimeError(self.server.errorString())
def closeEvent(self, event):
self.server.close()
self.server.removeServer(self.server.fullServerName())
def handleMessage(self, message=None):
socket = self.server.nextPendingConnection()
if socket is not None:
if socket.waitForReadyRead(2000):
message = socket.readAll().data().decode('utf-8')
socket.disconnectFromServer()
socket.deleteLater()
if message == 'stop':
self.close()
else:
self.setText(message)
def usage():
print("""
usage: %s [opts] [message]
options:
-h display this help and exit
-V display version information
-s stop the server
""" % QtGui.QApplication.applicationName())
def main():
keys = 'hVs'
try:
options, args = getopt.getopt(sys.argv[1:], keys)
except getopt.GetoptError as exception:
print('ERROR: %s' % exception)
usage()
return 2
else:
options = dict(options)
if '-h' in options:
usage()
elif '-V' in options:
print('%s-%s' % (
QtGui.QApplication.applicationName(),
QtGui.QApplication.applicationVersion(),
))
else:
if '-s' in options:
message = 'stop'
else:
message = args[0] if args else None
name = '%s_server' % QtGui.QApplication.applicationName()
socket = QtNetwork.QLocalSocket()
socket.connectToServer(name, QtCore.QIODevice.WriteOnly)
if socket.waitForConnected(500):
socket.write(message.encode('utf-8'))
if not socket.waitForBytesWritten(2000):
print('ERROR: could not write to socket: %s' %
socket.errorString())
socket.disconnectFromServer()
elif socket.error() != QtNetwork.QAbstractSocket.HostNotFoundError:
print('ERROR: could not connect to server: %s' %
socket.errorString())
elif message is not None:
print('ERROR: server is not running')
else:
app = QtGui.QApplication(sys.argv)
window = Window(name)
window.setGeometry(50, 50, 200, 30)
window.show()
return app.exec_()
return 0
if __name__ == '__main__':
sys.exit(main())
【讨论】:
谢谢楼主的例子,我回家分析一下。 :D 还有一个问题先生,我应该如何向正在运行的应用程序发送命令?通过终端?命令是什么?再次感谢。 @PolanSantiago。使用python demo.py
在控制台中启动脚本。然后在另一个控制台中,运行python demo.py "hello world"
,这将在标签中显示消息。以上是关于从另一个 Python 进程更新 Python GUI的主要内容,如果未能解决你的问题,请参考以下文章
python下多进程时全局变量在子进程怎么能更新?遇到从子进程更