0

I've been Googling for almost two days now to find an answer about my problem in Python. And I'm totally lost and confused on how am I supposed to solve my problem.

Here's what I want to do. I have a Python file name mymain.py(GUI) and its running and active, I want to change and update the Qlabel text in my GUI by running this command in terminal

sudo python myarg.py -i [any number]

where [number] is user defined. For example I ran this code in the terminal

sudo python myarg.py -i 5

the Qlabel text in GUI should change to 5.

Here's my code:

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:])

The version of Python that I'm using is 2.7 and my machine is Raspberry Pi.

halfer
  • 19,824
  • 17
  • 99
  • 186
  • 1
    Why do you want to do this? What you are asking is not exactly trivial. You need to set up some sort of inter-process communication (you are launching a separate process to update a GUI which is highly unusual) – three_pineapples Jul 29 '15 at 10:33
  • @three_pineapples. It's actually quite common - for example, tabbed editors/browsers which open all documents in the same window. – ekhumoro Jul 30 '15 at 00:31

1 Answers1

0

Your use-case is very similar to a single-instance application. On the first invocation of the command, the main window is shown; then all subsequent invocations just send their arguments to the running application.

Their are many ways to do this, but one of the simplest is to use local sockets. To give you an idea of how this works, here's a demo based on an osd volume control I once wrote:

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())
ekhumoro
  • 115,249
  • 20
  • 229
  • 336
  • Thanks for the example sir, I'm going to analyze it when i got home. :D – Polan Santiago Jul 30 '15 at 01:18
  • one more questions sir, how I supposed to send command to the running application? via terminal? and what is the command? thanks again. – Polan Santiago Jul 30 '15 at 01:26
  • @PolanSantiago. Start the script in a console with `python demo.py`. Then in another console, run `python demo.py "hello world"`, which will show the message in the label. – ekhumoro Jul 30 '15 at 02:10