1

I am very new to the pyqt. I am in the process of developing the app. I did the basic app I am using following code to prevent app opens multiple times

''' Class to check weather app is already open or not '''
class SingleApplication(QtWidgets.QApplication):
    messageAvailable = QtCore.pyqtSignal(object)

    def __init__(self, argv, key):
        super().__init__(argv)
        # cleanup (only needed for unix)
        QtCore.QSharedMemory(key).attach()
        self._memory = QtCore.QSharedMemory(self)
        self._memory.setKey(key)
        if self._memory.attach():
            self._running = True
        else:
            self._running = False
            if not self._memory.create(1):
                raise RuntimeError(self._memory.errorString())

    def isRunning(self):
        return self._running



if __name__ == '__main__':

    key = common.appTitle
    app = SingleApplication(sys.argv,key)
    print(app.isRunning())
    if app.isRunning():
        print("App is already running")
        sys.exit(1)
    else:
        appctxt = ApplicationContext()       # 1. Instantiate ApplicationContext
        window = Mainwindow()

        QApplication.setQuitOnLastWindowClosed(False) ## prevent to close while close message box at the time of background running
        mainwindow = window.runwindow()
        mainwindow.show()

        exit_code = appctxt.app.exec_()      # 2. Invoke appctxt.app.exec_()
        sys.exit(exit_code)

The above code prevents multiple opening of the App. If we open app multiple it prevent with log message of "App is already running". I need to focus or activatedwindow already opened app window while clicking the app icon if an app is already in an open state. Please guide me. Thank you

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Sammu Sundar
  • 556
  • 3
  • 9
  • 24

1 Answers1

1

The easiest way is to use QLocalServer and QLocalSocket, which allows to create local connections and communicate between applications, but in this case it's just enough to check if a server already exists or be notified when a new connection is attempted:

from PyQt5 import QtCore, QtNetwork, QtWidgets

class UniqueApplication(QtWidgets.QApplication):
    anotherInstance = QtCore.pyqtSignal()
    def isUnique(self):
        socket = QtNetwork.QLocalSocket()
        socket.connectToServer('myApp')
        return not socket.state()

    def startListener(self):
        self.listener = QtNetwork.QLocalServer(self)
        self.listener.setSocketOptions(self.listener.WorldAccessOption)
        self.listener.newConnection.connect(self.anotherInstance)
        self.listener.listen('myApp')
        print('waiting for connections on "{}"'.format(self.listener.serverName()))


class Test(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        layout = QtWidgets.QVBoxLayout(self)
        self.label = QtWidgets.QLabel('Hello, I am new!')
        layout.addWidget(self.label)
        QtWidgets.QApplication.instance().anotherInstance.connect(self.anotherInstance)
        self.count = 0

    def anotherInstance(self):
        self.count += 1
        self.label.setText('That\'s {}, I am still here!'.format(self.count))
        self.showNormal()
        self.activateWindow()


if __name__ == '__main__':
    import sys
    app = UniqueApplication(sys.argv)
    if not app.isUnique():
        print('Application already running!')
    else:
        app.startListener()
        test = Test()
        test.show()
        sys.exit(app.exec())
musicamante
  • 41,230
  • 6
  • 33
  • 58
  • Thank you for your answer. I will check your concepts in my code :) – Sammu Sundar Feb 26 '20 at 09:31
  • You're welcome. Note that on Linux the server name will probably result in a socket file written on /tmp, so it's usually better to use a much more complex server name to avoid conflicts with other programs etc. – musicamante Feb 26 '20 at 09:35
  • I need to show the already opened window while clicking the icon if it is already run. if it is in the minimized state need to focus on the screen in your example the following part just print "Application is already running" only if not app.isUnique(): if not app.isUnique(): print('Application already running!') – Sammu Sundar Feb 26 '20 at 09:35
  • @SammuSundar Please, read the whole code and try it. – musicamante Feb 26 '20 at 09:38
  • @musicanmate Thanks man, sorry for the late reply. your code is working fine. but in my case, I am using FBS appctxt = ApplicationContext() . so I am getting error " AttributeError: 'QApplication' object has no attribute 'anotherInstance' ". I am trying to resolve this. If you know this let me know. your code is working properly without FBS.Thanks – Sammu Sundar Feb 26 '20 at 11:26
  • I've never used FBS, so I can only suggest you to `return self.listener` at the end of `startListener()` and do something like `listener = app.startListener(); test = Test(); listener.newConnection.connect(test.anotherInstance)` – musicamante Feb 26 '20 at 11:54
  • Okay thanks. i will try and let you know – Sammu Sundar Feb 26 '20 at 11:59
  • Works fine, You save my time. Thank you @musicamante :) – Sammu Sundar Feb 26 '20 at 12:06