How to control/drive/interact a PyQt GUI from command line in Python

后端 未结 2 1072
春和景丽
春和景丽 2020-12-07 00:02

I have a GUI application created with PyQt and I would like to be able to control it also from the python terminal through a kind of internal API.

Ideas :

2条回答
  •  爱一瞬间的悲伤
    2020-12-07 00:57

    Depending on what you seem to ask, you want to implement something similar to Native Messaging Protocol(Chrome, Mozilla), if so, then you should use QWinEventNotifier or QSocketNotifier depending on the OS to detect if it was written on the console.

    Based on my previous answer I created the following example where the user writes in the console some phrase and press Enter then that phrase is shown in the QLabel (I have only tested my example in Linux).

    import platform
    import sys
    
    from PyQt5 import QtCore, QtGui, QtWidgets
    
    
    class NativeMessenger(QtCore.QObject):
        messageChanged = QtCore.pyqtSignal(str)
    
        def __init__(self, parent=None):
            super().__init__(parent)
    
            self.m_qin = QtCore.QFile()
    
            self.m_qin.open(
                sys.stdin.fileno(), QtCore.QIODevice.ReadOnly | QtCore.QIODevice.Unbuffered
            )
    
            if platform.system() == "Windows":
                import win32api
    
                if sys.platform == "win32":
                    import os
                    import msvcrt
    
                    if platform.python_implementation() == "PyPy":
                        os.fdopen(fh.fileno(), "wb", 0)
                    else:
                        msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)
    
                self.m_notifier = QtCore.QWinEventNotifier(
                    win32api.GetStdHandle(win32api.STD_INPUT_HANDLE)
                )
    
            else:
                self.m_notifier = QtCore.QSocketNotifier(
                    sys.stdin.fileno(), QtCore.QSocketNotifier.Read, self
                )
    
            self.m_notifier.activated.connect(self.readyRead)
    
        @QtCore.pyqtSlot()
        def readyRead(self):
            line = self.m_qin.readLine().data().decode().strip()
            self.messageChanged.emit(line)
    
    
    if __name__ == "__main__":
        app = QtWidgets.QApplication(sys.argv)
    
        w = QtWidgets.QLabel(alignment=QtCore.Qt.AlignCenter)
        w.resize(640, 480)
        w.show()
    
        messenger = NativeMessenger()
        messenger.messageChanged.connect(w.setText)
    
        sys.exit(app.exec_())
    

    Output:

    Stack Overflow
    

    The above can be taken as the basis for implementing your API.


    Although another approach is to have 2 applications where a CLI controls the GUI by communicating through sockets and other protocols such as IPC (dbus, etc.), ZeroMQ, MQTT, etc.

提交回复
热议问题