Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Qt for Python
  4. VPN connect app. PyQt5. how to display output in second display?

VPN connect app. PyQt5. how to display output in second display?

Scheduled Pinned Locked Moved Solved Qt for Python
28 Posts 5 Posters 3.2k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • A Offline
    A Offline
    Al3x
    wrote on last edited by
    #1

    Hi everyone.

    Im trying to create a VPN connection app with PyQt5 and python.
    The app works, partly, if you click the "Connect to VPN" button it connects to the vpn, also if you click any of the other buttons they all display their output in the fist display (QTextEdit).

    But what im trying to do is have the other buttons show their output in the Second display, or third.
    I've tried adding a second run_command2, adding a second worker, adding a second result2, nothing is working. It seems like ive tried everything..

    Could someone please be so kind to shine some light on how to do this?

    vpn_ui.py

    import sys
    import os
    
    from PyQt5.QtCore import pyqtSlot
    from PyQt5.QtWidgets import QApplication, QGridLayout, QPushButton, QTextEdit, QListView, QWidget
    
    from worker import Worker
    
    
    class TestUI(QWidget):
        def __init__(self):
            super().__init__()
            self.worker = Worker()
            self.worker.outSignal.connect(self.logging)
            self.btn1 = QPushButton("Connect to VPN")
            self.btn2 = QPushButton("check IP")
            self.btn3 = QPushButton("Ping")
            self.btn4 = QPushButton("ls /")
            self.result = QTextEdit()
            self.result2 = QTextEdit()
            self.init_ui()
    
        def init_ui(self):
            self.btn1.clicked.connect(self.press_btn1)
            self.btn2.clicked.connect(self.press_btn2)
            self.btn3.clicked.connect(self.press_btn3)
            self.btn4.clicked.connect(self.press_btn4)
    
            lay = QGridLayout(self)
            lay.addWidget(self.btn1, 0, 0)
            lay.addWidget(self.btn2, 0, 1)
            lay.addWidget(self.btn3, 0, 2)
            lay.addWidget(self.btn4, 0, 3)
            lay.addWidget(self.result, 1, 0, 1, 3)
            lay.addWidget(self.result2, 1, 5)
    
        @pyqtSlot()
        def press_btn1(self):
            command1 = "sudo openvpn myip.ovpn"
            path = "./"
            self.worker.run_command(command1, cwd=path, shell=True)
    
        @pyqtSlot()
        def press_btn2(self):
            command2 = "dig +short myip.opendns.com @resolver1.opendns.com"
            path = "./"
            self.worker.run_command(command2, cwd=path, shell=True)
    
        @pyqtSlot()
        def press_btn3(self):
            command3 = "ping -c 5 google.com"
            path = "./"
            self.worker.run_command(command3, cwd=path, shell=True)
           
        @pyqtSlot()
        def press_btn4(self):
            command4 = "ls"
            path = "/"
            self.worker.run_command(command4, cwd=path)
    
    
    
    #--------------------------------------------------------------------------
        @pyqtSlot(str)
        def logging(self, string):
            self.result.append(string.strip())
    
     
    
    
    
    if __name__ == "__main__":
        APP = QApplication(sys.argv)
        ex = TestUI()
        ex.show()
        sys.exit(APP.exec_())
    

    worker.py

    import subprocess
    import threading
    
    from PyQt5 import QtCore
    
    
    class Worker(QtCore.QObject):
        outSignal = QtCore.pyqtSignal(str)
    
        def run_command(self, cmd, **kwargs):
            threading.Thread(
                target=self._execute_command, args=(cmd,), kwargs=kwargs, daemon=True
            ).start()
    
    
    
        def _execute_command(self, cmd, **kwargs):
            proc = subprocess.Popen(
                cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, **kwargs
            )
            for line in proc.stdout:
                self.outSignal.emit(line.decode())
    
    
    
    

    Many thanks!!
    Alex

    jsulmJ 1 Reply Last reply
    0
    • A Al3x

      @jsulm said in VPN connect app. PyQt5. how to display output in second display?:

      @Al3x You already emit a signal to send the command output, but you do not use it anywhere. Just connect it to a slot whereever you want to show this output and show it.

      Im not really understanding whhat you mean. An example would help! im not using the QT designer, perhaps i should?

      @JonB said in VPN connect app. PyQt5. how to display output in second display?:

      @Al3x
      You probably don't need any "worker" threads at all, at least if you used Qt's QProcess to run commands, but that's a different matter.

      I don't follow your question. You emit a signal for all lines read from any process and you attach that to append into self.result. If you are saying you want some(?) commands to append to self.result2(?) then you need a different signal or a parameter from the signal to say which command it is coming from or a different object to emit the signal from so you can connect separately, is that what you mean?

      Yes i think thats what i want... -to append to self.result2...
      All of the buttons now, when pressed, show their output in self.result = QTextEdit(), and i cant figure out how to change that behaviour so instead some of the other buttons when pressed, would show in self.result2 = QTextEdit()

      This is why i was asking if i need another worker.
      Previously i tried creating a new "outSignal2" but it didnt work. perhaps i didnt do it right..

      An example would really help!
      Thanks!

      JonBJ Offline
      JonBJ Offline
      JonB
      wrote on last edited by JonB
      #7

      @Al3x
      @jsulm did not see that you are attaching the signal to a slot. In the politest way to him, ignore his comment ;-)

      I wouldn't really start from where you are now if I were writing for Qt. I would do things via QProcess and not threads. But let's leave that as I'm not offering to rewrite it for you.

      From where you are now I think the simplest change would be to create a second Worker instance and a second logging function which logs to the second QTextEdit. Then when a button sets off a worker-command it should use the worker instance which logs to the desired target widget. Something like:

              self.worker1 = Worker()
              self.worker1.outSignal.connect(self.logging1)
              self.worker2 = Worker()
              self.worker2.outSignal.connect(self.logging2)
      
      def press_btn1(self):
          self.worker1.run_command(...)
      
      def press_btn2(self):
          self.worker2.run_command(...)
      
       @pyqtSlot(str)
       def logging1(self, string):
           self.result1.append(string.strip())
      
       @pyqtSlot(str)
       def logging2(self, string):
           self.result2.append(string.strip())
      

      Btw, this approach would not scale nicely if you had 100 or even 10 separate commands/output widgets, then we would look to refactor or take a different approach, but for 2 or 3 it seems fine. And I'm trying to keep it simplest for you.

      A 2 Replies Last reply
      2
      • A Al3x

        Hi everyone.

        Im trying to create a VPN connection app with PyQt5 and python.
        The app works, partly, if you click the "Connect to VPN" button it connects to the vpn, also if you click any of the other buttons they all display their output in the fist display (QTextEdit).

        But what im trying to do is have the other buttons show their output in the Second display, or third.
        I've tried adding a second run_command2, adding a second worker, adding a second result2, nothing is working. It seems like ive tried everything..

        Could someone please be so kind to shine some light on how to do this?

        vpn_ui.py

        import sys
        import os
        
        from PyQt5.QtCore import pyqtSlot
        from PyQt5.QtWidgets import QApplication, QGridLayout, QPushButton, QTextEdit, QListView, QWidget
        
        from worker import Worker
        
        
        class TestUI(QWidget):
            def __init__(self):
                super().__init__()
                self.worker = Worker()
                self.worker.outSignal.connect(self.logging)
                self.btn1 = QPushButton("Connect to VPN")
                self.btn2 = QPushButton("check IP")
                self.btn3 = QPushButton("Ping")
                self.btn4 = QPushButton("ls /")
                self.result = QTextEdit()
                self.result2 = QTextEdit()
                self.init_ui()
        
            def init_ui(self):
                self.btn1.clicked.connect(self.press_btn1)
                self.btn2.clicked.connect(self.press_btn2)
                self.btn3.clicked.connect(self.press_btn3)
                self.btn4.clicked.connect(self.press_btn4)
        
                lay = QGridLayout(self)
                lay.addWidget(self.btn1, 0, 0)
                lay.addWidget(self.btn2, 0, 1)
                lay.addWidget(self.btn3, 0, 2)
                lay.addWidget(self.btn4, 0, 3)
                lay.addWidget(self.result, 1, 0, 1, 3)
                lay.addWidget(self.result2, 1, 5)
        
            @pyqtSlot()
            def press_btn1(self):
                command1 = "sudo openvpn myip.ovpn"
                path = "./"
                self.worker.run_command(command1, cwd=path, shell=True)
        
            @pyqtSlot()
            def press_btn2(self):
                command2 = "dig +short myip.opendns.com @resolver1.opendns.com"
                path = "./"
                self.worker.run_command(command2, cwd=path, shell=True)
        
            @pyqtSlot()
            def press_btn3(self):
                command3 = "ping -c 5 google.com"
                path = "./"
                self.worker.run_command(command3, cwd=path, shell=True)
               
            @pyqtSlot()
            def press_btn4(self):
                command4 = "ls"
                path = "/"
                self.worker.run_command(command4, cwd=path)
        
        
        
        #--------------------------------------------------------------------------
            @pyqtSlot(str)
            def logging(self, string):
                self.result.append(string.strip())
        
         
        
        
        
        if __name__ == "__main__":
            APP = QApplication(sys.argv)
            ex = TestUI()
            ex.show()
            sys.exit(APP.exec_())
        

        worker.py

        import subprocess
        import threading
        
        from PyQt5 import QtCore
        
        
        class Worker(QtCore.QObject):
            outSignal = QtCore.pyqtSignal(str)
        
            def run_command(self, cmd, **kwargs):
                threading.Thread(
                    target=self._execute_command, args=(cmd,), kwargs=kwargs, daemon=True
                ).start()
        
        
        
            def _execute_command(self, cmd, **kwargs):
                proc = subprocess.Popen(
                    cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, **kwargs
                )
                for line in proc.stdout:
                    self.outSignal.emit(line.decode())
        
        
        
        

        Many thanks!!
        Alex

        jsulmJ Online
        jsulmJ Online
        jsulm
        Lifetime Qt Champion
        wrote on last edited by
        #2

        @Al3x said in VPN connect app. PyQt5. how to display output in second display?:

        command1 = "sudo openvpn myip.ovpn"

        Shouldn't you pass the command and its parameters as list? I mean like:

        Popen(["/usr/bin/git", "commit", "-m", "Fixes a bug."])
        

        https://forum.qt.io/topic/113070/qt-code-of-conduct

        A 1 Reply Last reply
        0
        • jsulmJ jsulm

          @Al3x said in VPN connect app. PyQt5. how to display output in second display?:

          command1 = "sudo openvpn myip.ovpn"

          Shouldn't you pass the command and its parameters as list? I mean like:

          Popen(["/usr/bin/git", "commit", "-m", "Fixes a bug."])
          
          A Offline
          A Offline
          Al3x
          wrote on last edited by
          #3

          @jsulm

          The command works as is, what i cant figure out is how to route the output of the other buttons to the other Widget.
          Im completely new to QT and not that great at python either..
          Do i need a new worker?
          Thanks!

          jsulmJ JonBJ 2 Replies Last reply
          0
          • A Al3x

            @jsulm

            The command works as is, what i cant figure out is how to route the output of the other buttons to the other Widget.
            Im completely new to QT and not that great at python either..
            Do i need a new worker?
            Thanks!

            jsulmJ Online
            jsulmJ Online
            jsulm
            Lifetime Qt Champion
            wrote on last edited by
            #4

            @Al3x You already emit a signal to send the command output, but you do not use it anywhere. Just connect it to a slot whereever you want to show this output and show it.

            https://forum.qt.io/topic/113070/qt-code-of-conduct

            A 1 Reply Last reply
            0
            • A Al3x

              @jsulm

              The command works as is, what i cant figure out is how to route the output of the other buttons to the other Widget.
              Im completely new to QT and not that great at python either..
              Do i need a new worker?
              Thanks!

              JonBJ Offline
              JonBJ Offline
              JonB
              wrote on last edited by JonB
              #5

              @Al3x
              You probably don't need any "worker" threads at all, at least if you used Qt's QProcess to run commands, but that's a different matter.

              I don't follow your question. You emit a signal for all lines read from any process and you attach that to append into self.result. If you are saying you want some(?) commands to append to self.result2(?) then you need one of: (a) a different signal or (b) a parameter from the signal to say which command it is coming from or (c) a different object to emit the signal from so you can connect separately. Is that what you mean?

              1 Reply Last reply
              0
              • jsulmJ jsulm

                @Al3x You already emit a signal to send the command output, but you do not use it anywhere. Just connect it to a slot whereever you want to show this output and show it.

                A Offline
                A Offline
                Al3x
                wrote on last edited by Al3x
                #6

                @jsulm said in VPN connect app. PyQt5. how to display output in second display?:

                @Al3x You already emit a signal to send the command output, but you do not use it anywhere. Just connect it to a slot whereever you want to show this output and show it.

                Im not really understanding whhat you mean. An example would help! im not using the QT designer, perhaps i should?

                @JonB said in VPN connect app. PyQt5. how to display output in second display?:

                @Al3x
                You probably don't need any "worker" threads at all, at least if you used Qt's QProcess to run commands, but that's a different matter.

                I don't follow your question. You emit a signal for all lines read from any process and you attach that to append into self.result. If you are saying you want some(?) commands to append to self.result2(?) then you need a different signal or a parameter from the signal to say which command it is coming from or a different object to emit the signal from so you can connect separately, is that what you mean?

                Yes i think thats what i want... -to append to self.result2...
                All of the buttons now, when pressed, show their output in self.result = QTextEdit(), and i cant figure out how to change that behaviour so instead some of the other buttons when pressed, would show in self.result2 = QTextEdit()

                This is why i was asking if i need another worker.
                Previously i tried creating a new "outSignal2" but it didnt work. perhaps i didnt do it right..

                An example would really help!
                Thanks!

                JonBJ 1 Reply Last reply
                0
                • A Al3x

                  @jsulm said in VPN connect app. PyQt5. how to display output in second display?:

                  @Al3x You already emit a signal to send the command output, but you do not use it anywhere. Just connect it to a slot whereever you want to show this output and show it.

                  Im not really understanding whhat you mean. An example would help! im not using the QT designer, perhaps i should?

                  @JonB said in VPN connect app. PyQt5. how to display output in second display?:

                  @Al3x
                  You probably don't need any "worker" threads at all, at least if you used Qt's QProcess to run commands, but that's a different matter.

                  I don't follow your question. You emit a signal for all lines read from any process and you attach that to append into self.result. If you are saying you want some(?) commands to append to self.result2(?) then you need a different signal or a parameter from the signal to say which command it is coming from or a different object to emit the signal from so you can connect separately, is that what you mean?

                  Yes i think thats what i want... -to append to self.result2...
                  All of the buttons now, when pressed, show their output in self.result = QTextEdit(), and i cant figure out how to change that behaviour so instead some of the other buttons when pressed, would show in self.result2 = QTextEdit()

                  This is why i was asking if i need another worker.
                  Previously i tried creating a new "outSignal2" but it didnt work. perhaps i didnt do it right..

                  An example would really help!
                  Thanks!

                  JonBJ Offline
                  JonBJ Offline
                  JonB
                  wrote on last edited by JonB
                  #7

                  @Al3x
                  @jsulm did not see that you are attaching the signal to a slot. In the politest way to him, ignore his comment ;-)

                  I wouldn't really start from where you are now if I were writing for Qt. I would do things via QProcess and not threads. But let's leave that as I'm not offering to rewrite it for you.

                  From where you are now I think the simplest change would be to create a second Worker instance and a second logging function which logs to the second QTextEdit. Then when a button sets off a worker-command it should use the worker instance which logs to the desired target widget. Something like:

                          self.worker1 = Worker()
                          self.worker1.outSignal.connect(self.logging1)
                          self.worker2 = Worker()
                          self.worker2.outSignal.connect(self.logging2)
                  
                  def press_btn1(self):
                      self.worker1.run_command(...)
                  
                  def press_btn2(self):
                      self.worker2.run_command(...)
                  
                   @pyqtSlot(str)
                   def logging1(self, string):
                       self.result1.append(string.strip())
                  
                   @pyqtSlot(str)
                   def logging2(self, string):
                       self.result2.append(string.strip())
                  

                  Btw, this approach would not scale nicely if you had 100 or even 10 separate commands/output widgets, then we would look to refactor or take a different approach, but for 2 or 3 it seems fine. And I'm trying to keep it simplest for you.

                  A 2 Replies Last reply
                  2
                  • JonBJ JonB

                    @Al3x
                    @jsulm did not see that you are attaching the signal to a slot. In the politest way to him, ignore his comment ;-)

                    I wouldn't really start from where you are now if I were writing for Qt. I would do things via QProcess and not threads. But let's leave that as I'm not offering to rewrite it for you.

                    From where you are now I think the simplest change would be to create a second Worker instance and a second logging function which logs to the second QTextEdit. Then when a button sets off a worker-command it should use the worker instance which logs to the desired target widget. Something like:

                            self.worker1 = Worker()
                            self.worker1.outSignal.connect(self.logging1)
                            self.worker2 = Worker()
                            self.worker2.outSignal.connect(self.logging2)
                    
                    def press_btn1(self):
                        self.worker1.run_command(...)
                    
                    def press_btn2(self):
                        self.worker2.run_command(...)
                    
                     @pyqtSlot(str)
                     def logging1(self, string):
                         self.result1.append(string.strip())
                    
                     @pyqtSlot(str)
                     def logging2(self, string):
                         self.result2.append(string.strip())
                    

                    Btw, this approach would not scale nicely if you had 100 or even 10 separate commands/output widgets, then we would look to refactor or take a different approach, but for 2 or 3 it seems fine. And I'm trying to keep it simplest for you.

                    A Offline
                    A Offline
                    Al3x
                    wrote on last edited by
                    #8

                    @JonB
                    Yes! Working! Thanks so much!!!
                    I had it setup similar to your example before, but this makes sense.
                    Im begining to understand the QT logic a little better now!

                    Thanks thanks Again!!

                    1 Reply Last reply
                    0
                    • A Al3x has marked this topic as solved on
                    • JonBJ JonB

                      @Al3x
                      @jsulm did not see that you are attaching the signal to a slot. In the politest way to him, ignore his comment ;-)

                      I wouldn't really start from where you are now if I were writing for Qt. I would do things via QProcess and not threads. But let's leave that as I'm not offering to rewrite it for you.

                      From where you are now I think the simplest change would be to create a second Worker instance and a second logging function which logs to the second QTextEdit. Then when a button sets off a worker-command it should use the worker instance which logs to the desired target widget. Something like:

                              self.worker1 = Worker()
                              self.worker1.outSignal.connect(self.logging1)
                              self.worker2 = Worker()
                              self.worker2.outSignal.connect(self.logging2)
                      
                      def press_btn1(self):
                          self.worker1.run_command(...)
                      
                      def press_btn2(self):
                          self.worker2.run_command(...)
                      
                       @pyqtSlot(str)
                       def logging1(self, string):
                           self.result1.append(string.strip())
                      
                       @pyqtSlot(str)
                       def logging2(self, string):
                           self.result2.append(string.strip())
                      

                      Btw, this approach would not scale nicely if you had 100 or even 10 separate commands/output widgets, then we would look to refactor or take a different approach, but for 2 or 3 it seems fine. And I'm trying to keep it simplest for you.

                      A Offline
                      A Offline
                      Al3x
                      wrote on last edited by
                      #9

                      @JonB

                      @JonB said in VPN connect app. PyQt5. how to display output in second display?:

                      Btw, this approach would not scale nicely if you had 100 or even 10 separate commands/output widgets, then we would look to refactor or take a different approach, but for 2 or 3 it seems fine. And I'm trying to keep it simplest for you.

                      Can you tell me more? how would i go about doing that? because im beginning to add many different commands i want to access. and if i could make it more streamlined that would be great to know!

                      Thanks!

                      JonBJ 1 Reply Last reply
                      0
                      • A Al3x

                        @JonB

                        @JonB said in VPN connect app. PyQt5. how to display output in second display?:

                        Btw, this approach would not scale nicely if you had 100 or even 10 separate commands/output widgets, then we would look to refactor or take a different approach, but for 2 or 3 it seems fine. And I'm trying to keep it simplest for you.

                        Can you tell me more? how would i go about doing that? because im beginning to add many different commands i want to access. and if i could make it more streamlined that would be great to know!

                        Thanks!

                        JonBJ Offline
                        JonBJ Offline
                        JonB
                        wrote on last edited by JonB
                        #10

                        @Al3x
                        Well only general good programming approaches. At present you have/need per command/output:

                        • One named/designed button.
                        • One Worker instance.
                        • One logging...() function, to attach signal to.
                        • One press_btn...() function.
                        • One named/created self.result... text edit widget.

                        You can continue that way, but if you had 100 buttons/output windows it would get a bit much. You might create arrays for these so that the code works no matter how many of these you need without having to write explicit code for each instance.

                        But then again, I'm not sure you want 100 different QTextEdits for the user to look at, each one for a different command, so that probably needs rethinking anyway.

                        A 1 Reply Last reply
                        0
                        • JonBJ JonB

                          @Al3x
                          Well only general good programming approaches. At present you have/need per command/output:

                          • One named/designed button.
                          • One Worker instance.
                          • One logging...() function, to attach signal to.
                          • One press_btn...() function.
                          • One named/created self.result... text edit widget.

                          You can continue that way, but if you had 100 buttons/output windows it would get a bit much. You might create arrays for these so that the code works no matter how many of these you need without having to write explicit code for each instance.

                          But then again, I'm not sure you want 100 different QTextEdits for the user to look at, each one for a different command, so that probably needs rethinking anyway.

                          A Offline
                          A Offline
                          Al3x
                          wrote on last edited by
                          #11

                          @JonB
                          i havent had time to read the full Doc. i will this week.

                          Yes, 1 Worker seems enough.. now... though i donno.... im completely new to QT.

                          Definitely not looking to do 100 instances, 20 at most maybe.. Do you mean "at bit much" in terms of managing the code rather than performance?

                          I know how to make an Array, but how do you make it with slots?
                          Thanks!

                          JonBJ 1 Reply Last reply
                          0
                          • A Al3x

                            @JonB
                            i havent had time to read the full Doc. i will this week.

                            Yes, 1 Worker seems enough.. now... though i donno.... im completely new to QT.

                            Definitely not looking to do 100 instances, 20 at most maybe.. Do you mean "at bit much" in terms of managing the code rather than performance?

                            I know how to make an Array, but how do you make it with slots?
                            Thanks!

                            JonBJ Offline
                            JonBJ Offline
                            JonB
                            wrote on last edited by JonB
                            #12

                            @Al3x
                            "A bit much" only in terms of writing/maintaining code. Performance won't be an issue either way.

                            For the array, let's take one example. You presently have:

                                    self.worker1 = Worker()
                                    self.worker1.outSignal.connect(self.logging1)
                                    self.worker2 = Worker()
                                    self.worker2.outSignal.connect(self.logging2)
                            

                            Let's say you had 20 of these. That's a lot of self.worker1 and self.logging1 variables and statements to write. Let's say you refactored these into a list/array of workers and a list/array of references to the slot functions. Then you could do this in a loop. Something like:

                            self.workers = [ Worker(), Worker(), ... ]
                            self.slots = [ self.logging1, self.logging2, ... ]
                            for i in range(len(self.workers)):
                                self.workers[i].outSignal.connect(self.slots[i])
                            

                            I am not saying that I would necessarily do things this way/the way you have done, there are other approaches, you might use passing parameters/lambdas more and so on. But I'm afraid I'm not here to teach, that's for you to learn :) I am just illustrating how it could be done, from where you are now, if you have a lot of items. You have enough to learn with being new to Qt and to Python, one step at a time. You can write out the "long-hand" way you are doing things now and look into refactoring at a later date when you are more familiar with Qt/Python.

                            A 1 Reply Last reply
                            0
                            • JonBJ JonB

                              @Al3x
                              "A bit much" only in terms of writing/maintaining code. Performance won't be an issue either way.

                              For the array, let's take one example. You presently have:

                                      self.worker1 = Worker()
                                      self.worker1.outSignal.connect(self.logging1)
                                      self.worker2 = Worker()
                                      self.worker2.outSignal.connect(self.logging2)
                              

                              Let's say you had 20 of these. That's a lot of self.worker1 and self.logging1 variables and statements to write. Let's say you refactored these into a list/array of workers and a list/array of references to the slot functions. Then you could do this in a loop. Something like:

                              self.workers = [ Worker(), Worker(), ... ]
                              self.slots = [ self.logging1, self.logging2, ... ]
                              for i in range(len(self.workers)):
                                  self.workers[i].outSignal.connect(self.slots[i])
                              

                              I am not saying that I would necessarily do things this way/the way you have done, there are other approaches, you might use passing parameters/lambdas more and so on. But I'm afraid I'm not here to teach, that's for you to learn :) I am just illustrating how it could be done, from where you are now, if you have a lot of items. You have enough to learn with being new to Qt and to Python, one step at a time. You can write out the "long-hand" way you are doing things now and look into refactoring at a later date when you are more familiar with Qt/Python.

                              A Offline
                              A Offline
                              Al3x
                              wrote on last edited by
                              #13

                              @JonB
                              I know javascript, php, its very much the similar in terms of arrays i see. Cool!
                              I dont want for anyone to rewrite my code, i wish to do it myself! but examples help alot!

                              Thanks man! ive learned learned alot!
                              more than i can digest today!

                              Its always the same, first learn the buttons and basics then expand

                              JonBJ 1 Reply Last reply
                              0
                              • A Al3x

                                @JonB
                                I know javascript, php, its very much the similar in terms of arrays i see. Cool!
                                I dont want for anyone to rewrite my code, i wish to do it myself! but examples help alot!

                                Thanks man! ive learned learned alot!
                                more than i can digest today!

                                Its always the same, first learn the buttons and basics then expand

                                JonBJ Offline
                                JonBJ Offline
                                JonB
                                wrote on last edited by
                                #14

                                @Al3x
                                There is a lot to learn if you are new to both Qt and Python. Take your time, try not to bite off more than you can chew to start with.

                                1 Reply Last reply
                                0
                                • Axel SpoerlA Axel Spoerl referenced this topic on
                                • A Offline
                                  A Offline
                                  Al3x
                                  wrote on last edited by
                                  #15

                                  Ugh this @Axel-Spoerl guy. Had a bad day looks like.
                                  He closed my topic "for waisting time" and directed it to this Topic,. so i guess i ask here... :) not that its anything to do with this Topic..
                                  #############################
                                  Im trying to create a QTree that displays XML content. Basic xml that has multiple entries for various VPN ips.
                                  The script as is now works but thats with the actual 'Data' hardcoded inside the script. I need to read an xml and display it equivalent to how it does now.
                                  Ive read a few articles but im struggling to get it working..
                                  Could someone give me some pointers?
                                  Cheers!

                                  import sys
                                  from PyQt5 import QtCore, QtGui, QtWidgets
                                  from PyQt5.QtWidgets import QTreeWidgetItem
                                  
                                  #import xml.etree.ElementTree as ET
                                  #tree = ET.parse('data.xml')
                                  #root = tree.getroot()
                                  
                                  class Widget(QtWidgets.QWidget):
                                     def __init__(self, parent=None):
                                         super(Widget, self).__init__(parent)
                                         lay = QtWidgets.QVBoxLayout(self)
                                         tree = QtWidgets.QTreeWidget()
                                         tree.setColumnCount(3)
                                         tree.setHeaderLabels(["VPN", "2", "3"])
                                         lay.addWidget(tree)
                                  
                                  
                                  
                                  #########################################################
                                  ## new - not working
                                  #        f = open("data.xml", 'r').read()
                                  #        self.printtree(f)
                                  #
                                  #    def printtree(self, s):
                                  #        tree = ET.fromstring(s)
                                  #        a=QTreeWidgetItem([tree.tag])
                                  #        self.tree.addtTopLevelItems(a)
                                  #
                                  #        def displaytree(a,s):
                                  #            for child in s:
                                  #                branch=QTreeWidgetItem([child.tag])
                                  #                a.addChild(branch)
                                  #                displaytree(branch,child)
                                  #        displaytree(a,tree)
                                  
                                  ###########################################################
                                  ## new - not working
                                  
                                  
                                  ## working
                                         data = {
                                         "USA": ["18.122.x.xx.ovpn", "0.22.0.0.ovpn", "11.0.0.0.ovpn"],
                                         "Europe": ["77.0.0.0.ovpn", "66.0.0.0.ovpn"],
                                         "Asia": ["99.0.0.0.ovpn","0.99.0.0.ovpn"]}
                                  
                                         items = []
                                         for key, values in data.items():
                                             item = QTreeWidgetItem([key])
                                             for value in values:
                                                 ext = value.split(".")[-1].upper()
                                                 child = QTreeWidgetItem([value, ext])
                                                 item.addChild(child)
                                             items.append(item)
                                         tree.insertTopLevelItems(0, items)
                                  
                                         tree.expandAll()
                                         tree.itemClicked.connect(self.onItemClicked)
                                  
                                     @QtCore.pyqtSlot(QtWidgets.QTreeWidgetItem, int)
                                     def onItemClicked(self, it, col):
                                         print(it.text(col))
                                  ## working ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                  
                                  
                                  
                                  #####################################################################
                                  if __name__ == '__main__':
                                     import sys
                                  
                                     app = QtWidgets.QApplication(sys.argv)
                                     w = Widget()
                                     w.show()
                                     sys.exit(app.exec_())
                                  
                                  
                                  
                                  Axel SpoerlA JonBJ 2 Replies Last reply
                                  0
                                  • A Al3x

                                    Ugh this @Axel-Spoerl guy. Had a bad day looks like.
                                    He closed my topic "for waisting time" and directed it to this Topic,. so i guess i ask here... :) not that its anything to do with this Topic..
                                    #############################
                                    Im trying to create a QTree that displays XML content. Basic xml that has multiple entries for various VPN ips.
                                    The script as is now works but thats with the actual 'Data' hardcoded inside the script. I need to read an xml and display it equivalent to how it does now.
                                    Ive read a few articles but im struggling to get it working..
                                    Could someone give me some pointers?
                                    Cheers!

                                    import sys
                                    from PyQt5 import QtCore, QtGui, QtWidgets
                                    from PyQt5.QtWidgets import QTreeWidgetItem
                                    
                                    #import xml.etree.ElementTree as ET
                                    #tree = ET.parse('data.xml')
                                    #root = tree.getroot()
                                    
                                    class Widget(QtWidgets.QWidget):
                                       def __init__(self, parent=None):
                                           super(Widget, self).__init__(parent)
                                           lay = QtWidgets.QVBoxLayout(self)
                                           tree = QtWidgets.QTreeWidget()
                                           tree.setColumnCount(3)
                                           tree.setHeaderLabels(["VPN", "2", "3"])
                                           lay.addWidget(tree)
                                    
                                    
                                    
                                    #########################################################
                                    ## new - not working
                                    #        f = open("data.xml", 'r').read()
                                    #        self.printtree(f)
                                    #
                                    #    def printtree(self, s):
                                    #        tree = ET.fromstring(s)
                                    #        a=QTreeWidgetItem([tree.tag])
                                    #        self.tree.addtTopLevelItems(a)
                                    #
                                    #        def displaytree(a,s):
                                    #            for child in s:
                                    #                branch=QTreeWidgetItem([child.tag])
                                    #                a.addChild(branch)
                                    #                displaytree(branch,child)
                                    #        displaytree(a,tree)
                                    
                                    ###########################################################
                                    ## new - not working
                                    
                                    
                                    ## working
                                           data = {
                                           "USA": ["18.122.x.xx.ovpn", "0.22.0.0.ovpn", "11.0.0.0.ovpn"],
                                           "Europe": ["77.0.0.0.ovpn", "66.0.0.0.ovpn"],
                                           "Asia": ["99.0.0.0.ovpn","0.99.0.0.ovpn"]}
                                    
                                           items = []
                                           for key, values in data.items():
                                               item = QTreeWidgetItem([key])
                                               for value in values:
                                                   ext = value.split(".")[-1].upper()
                                                   child = QTreeWidgetItem([value, ext])
                                                   item.addChild(child)
                                               items.append(item)
                                           tree.insertTopLevelItems(0, items)
                                    
                                           tree.expandAll()
                                           tree.itemClicked.connect(self.onItemClicked)
                                    
                                       @QtCore.pyqtSlot(QtWidgets.QTreeWidgetItem, int)
                                       def onItemClicked(self, it, col):
                                           print(it.text(col))
                                    ## working ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                    
                                    
                                    
                                    #####################################################################
                                    if __name__ == '__main__':
                                       import sys
                                    
                                       app = QtWidgets.QApplication(sys.argv)
                                       w = Widget()
                                       w.show()
                                       sys.exit(app.exec_())
                                    
                                    
                                    
                                    Axel SpoerlA Offline
                                    Axel SpoerlA Offline
                                    Axel Spoerl
                                    Moderators
                                    wrote on last edited by
                                    #16

                                    Ugh this @Axel-Spoerl guy. Had a bad day looks like.

                                    Hm. 6 days as a user, two topics - already passing judgement on others. Impressive bravery.

                                    QDomDocument is the class representing an XML document.
                                    I questioned the usage of XML for your purpose, because XML is way more powerful and complex than just to transmit and display data.
                                    That's why you haven't found a straight forward implementation in the net.

                                    Your question is very general. If you want any pointers, maybe post an XML example rather than a JSON example.

                                    Software Engineer
                                    The Qt Company, Oslo

                                    1 Reply Last reply
                                    0
                                    • A Offline
                                      A Offline
                                      Al3x
                                      wrote on last edited by
                                      #17

                                      Listen @Axel-Spoerl. I dont like you. I havent judged anything or anyone! you better take a look at your self!
                                      "QDomDocument is the class representing an XML document." --yea i can read but thats not what i asked.
                                      You havent questioned anything.. you shut the Topic down!

                                      The code has a commented out section which if you take a look at, im trying to Open and read an XML file, pass it as a string, and display it.
                                      Its commented out because i couldnt get it working, hence my post..

                                      1 Reply Last reply
                                      0
                                      • A Al3x

                                        Ugh this @Axel-Spoerl guy. Had a bad day looks like.
                                        He closed my topic "for waisting time" and directed it to this Topic,. so i guess i ask here... :) not that its anything to do with this Topic..
                                        #############################
                                        Im trying to create a QTree that displays XML content. Basic xml that has multiple entries for various VPN ips.
                                        The script as is now works but thats with the actual 'Data' hardcoded inside the script. I need to read an xml and display it equivalent to how it does now.
                                        Ive read a few articles but im struggling to get it working..
                                        Could someone give me some pointers?
                                        Cheers!

                                        import sys
                                        from PyQt5 import QtCore, QtGui, QtWidgets
                                        from PyQt5.QtWidgets import QTreeWidgetItem
                                        
                                        #import xml.etree.ElementTree as ET
                                        #tree = ET.parse('data.xml')
                                        #root = tree.getroot()
                                        
                                        class Widget(QtWidgets.QWidget):
                                           def __init__(self, parent=None):
                                               super(Widget, self).__init__(parent)
                                               lay = QtWidgets.QVBoxLayout(self)
                                               tree = QtWidgets.QTreeWidget()
                                               tree.setColumnCount(3)
                                               tree.setHeaderLabels(["VPN", "2", "3"])
                                               lay.addWidget(tree)
                                        
                                        
                                        
                                        #########################################################
                                        ## new - not working
                                        #        f = open("data.xml", 'r').read()
                                        #        self.printtree(f)
                                        #
                                        #    def printtree(self, s):
                                        #        tree = ET.fromstring(s)
                                        #        a=QTreeWidgetItem([tree.tag])
                                        #        self.tree.addtTopLevelItems(a)
                                        #
                                        #        def displaytree(a,s):
                                        #            for child in s:
                                        #                branch=QTreeWidgetItem([child.tag])
                                        #                a.addChild(branch)
                                        #                displaytree(branch,child)
                                        #        displaytree(a,tree)
                                        
                                        ###########################################################
                                        ## new - not working
                                        
                                        
                                        ## working
                                               data = {
                                               "USA": ["18.122.x.xx.ovpn", "0.22.0.0.ovpn", "11.0.0.0.ovpn"],
                                               "Europe": ["77.0.0.0.ovpn", "66.0.0.0.ovpn"],
                                               "Asia": ["99.0.0.0.ovpn","0.99.0.0.ovpn"]}
                                        
                                               items = []
                                               for key, values in data.items():
                                                   item = QTreeWidgetItem([key])
                                                   for value in values:
                                                       ext = value.split(".")[-1].upper()
                                                       child = QTreeWidgetItem([value, ext])
                                                       item.addChild(child)
                                                   items.append(item)
                                               tree.insertTopLevelItems(0, items)
                                        
                                               tree.expandAll()
                                               tree.itemClicked.connect(self.onItemClicked)
                                        
                                           @QtCore.pyqtSlot(QtWidgets.QTreeWidgetItem, int)
                                           def onItemClicked(self, it, col):
                                               print(it.text(col))
                                        ## working ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                        
                                        
                                        
                                        #####################################################################
                                        if __name__ == '__main__':
                                           import sys
                                        
                                           app = QtWidgets.QApplication(sys.argv)
                                           w = Widget()
                                           w.show()
                                           sys.exit(app.exec_())
                                        
                                        
                                        
                                        JonBJ Offline
                                        JonBJ Offline
                                        JonB
                                        wrote on last edited by JonB
                                        #18

                                        @Al3x
                                        I don't know whether your goal/requirement is to use XML or JSON. The code you show is actually just Python (objects, arrays), which is pretty close to JSON. If that is all the data there is you don't really need more than JSON. You have to decide whether you want JSON or XML.

                                        If you want to use Qt classes there is QJsonDocument for JSON or, as @Axel-Spoerl said, QDomDocument for XML. Python also has its own classes/code for both of these, if you want to use them you are on your own.

                                        If your issue is about wanting to read from XML/JSON file instead of hard-coding then both of those, whether Qt's or Python's, have methods to read/create a complete document from an external file.

                                        Both XML and JSON produce a hierarchical tree structure. QTreeView can display a hierarchical tree. It needs a model, derived from QAbstractItemModel. You can either take the simpler but less efficient route of copying your data into, say, a QStandardItemModel, which can create a hierarchical tree model suitable for use with a QTreeView (maybe see https://www.qtcentre.org/threads/44877-Convert-XML-to-QTreeView), or you can take the more ambitious route of writing your own subclass of QAbstractItemModel which links directly to your in-memory JSON or XML model, whether that is with Qt classes or Python ones. For example, https://forum.qt.io/topic/49771/jsonmodel-for-qtreeview appears to give a couple of links where someone has done so for JSON.

                                        For the code you appear to have started on but commented out. It uses some Python class import xml.etree.ElementTree as ET. But nobody here knows anything about what structure that Python produces and what you have to do with it to populate a QTreeWidget. If you say "it does not work" you might step through your code in Python debugger and diagnose what is going on.

                                        If nothing else, in the code you show self.tree.addtTopLevelItems(a) is simply wrong and will produce an error, even if self.tree existed. Which as per your __init__() it does not, you have no self.tree.

                                        (And btw don't use the same variable name, tree, for two quite different things: the Qt QTreeWidget and whatever parsed tree structure xml.etree.ElementTree produces. It simply leads to confusion and potential mishaps. Use different, meaningful variable names.)

                                        A 1 Reply Last reply
                                        0
                                        • JonBJ JonB

                                          @Al3x
                                          I don't know whether your goal/requirement is to use XML or JSON. The code you show is actually just Python (objects, arrays), which is pretty close to JSON. If that is all the data there is you don't really need more than JSON. You have to decide whether you want JSON or XML.

                                          If you want to use Qt classes there is QJsonDocument for JSON or, as @Axel-Spoerl said, QDomDocument for XML. Python also has its own classes/code for both of these, if you want to use them you are on your own.

                                          If your issue is about wanting to read from XML/JSON file instead of hard-coding then both of those, whether Qt's or Python's, have methods to read/create a complete document from an external file.

                                          Both XML and JSON produce a hierarchical tree structure. QTreeView can display a hierarchical tree. It needs a model, derived from QAbstractItemModel. You can either take the simpler but less efficient route of copying your data into, say, a QStandardItemModel, which can create a hierarchical tree model suitable for use with a QTreeView (maybe see https://www.qtcentre.org/threads/44877-Convert-XML-to-QTreeView), or you can take the more ambitious route of writing your own subclass of QAbstractItemModel which links directly to your in-memory JSON or XML model, whether that is with Qt classes or Python ones. For example, https://forum.qt.io/topic/49771/jsonmodel-for-qtreeview appears to give a couple of links where someone has done so for JSON.

                                          For the code you appear to have started on but commented out. It uses some Python class import xml.etree.ElementTree as ET. But nobody here knows anything about what structure that Python produces and what you have to do with it to populate a QTreeWidget. If you say "it does not work" you might step through your code in Python debugger and diagnose what is going on.

                                          If nothing else, in the code you show self.tree.addtTopLevelItems(a) is simply wrong and will produce an error, even if self.tree existed. Which as per your __init__() it does not, you have no self.tree.

                                          (And btw don't use the same variable name, tree, for two quite different things: the Qt QTreeWidget and whatever parsed tree structure xml.etree.ElementTree produces. It simply leads to confusion and potential mishaps. Use different, meaningful variable names.)

                                          A Offline
                                          A Offline
                                          Al3x
                                          wrote on last edited by
                                          #19

                                          @JonB
                                          Thanks for the lengthy reply!! This i class as an answer, as oppose to through-ing out a link and saying "go read it all".

                                          No, what i still very much wish to do is use XML. DOM from reading is old and is more mem/cpu intensive. Whats your take on that?

                                          The script that i have is using ElementTree, its opening and reading the XML succesfully. i can also write to it succesfully
                                          And i can print it to string successfully:

                                          XMLtoStr = ET.tostring(root, encoding='utf8').decode('utf8')
                                          
                                          

                                          The problem is i cant manage to print into the Tree!
                                          Im using Qwidget.
                                          So perhaps thats the problem? -i should use QTreeView? with a model?

                                          This is the script now, if you run it, you will see it print the XML in the terminal, but it doesnt print it in the UI widget.

                                          tree.py

                                          import sys
                                          from PyQt5 import QtCore, QtGui, QtWidgets
                                          from PyQt5.QtWidgets import QTreeWidgetItem
                                          import xml.etree.ElementTree as ET
                                          ## access and set root for XML file
                                          tree = ET.parse('data.xml')
                                          root = tree.getroot()
                                          
                                          class Widget(QtWidgets.QWidget):
                                              def __init__(self):
                                                  super(Widget, self).__init__()
                                                  lay = QtWidgets.QVBoxLayout(self)
                                                  tree = QtWidgets.QTreeWidget()
                                                  tree.setColumnCount(3)
                                                  tree.setHeaderLabels(["VPN", "2", "3"])
                                                  lay.addWidget(tree)
                                                  #self.tree = QTreeView()
                                                  XMLtoStr = ET.tostring(root, encoding='utf8').decode('utf8')
                                                  #self.printtree(f)
                                          
                                          ## print XML data in the file to string
                                          XMLtoStr = ET.tostring(root, encoding='utf8').decode('utf8')
                                          print(XMLtoStr)
                                          
                                          
                                          def printtree(self, s):
                                              #tree = ET.fromstring(s)
                                              tree = ET.tostring(root, encoding='utf8').decode('utf8')
                                          
                                              a = QTreeWidgetItem([tree.tag])
                                              self.tree.addtTopLevelItems(a)
                                          
                                              def displaytree(a,s):
                                                  for child in s:
                                                      branch = QTreeWidgetItem([child.tag])
                                                      a.addChild(branch)
                                                      displaytree(branch,child)
                                                  if s.text is not None:
                                                      content=s.text
                                                      a.addChild(QTreeWidgetItem([content]))
                                          
                                          
                                              displaytree(a,tree)
                                          
                                          
                                          #####################################################################
                                          if __name__ == '__main__':
                                              import sys
                                          
                                              app = QtWidgets.QApplication(sys.argv)
                                              w = Widget()
                                              w.show()
                                              sys.exit(app.exec_())
                                          
                                          

                                          data.xml

                                          <?xml version="1.0" encoding="UTF-8"?>
                                          <catalog>
                                              <vpn id="vpn01">
                                                  <config>1.1.1.1.ovpn</config>
                                                  <ip>1.1.1.1</ip>
                                                  <port>443</port>
                                                  <protocol>TCP</protocol>
                                                  <country>US</country>
                                                  <details>
                                                  'info....'
                                                </details>
                                              </vpn>
                                              <vpn id="vpn02">
                                                  <config>1.1.1.1.ovpn</config>
                                                  <ip>1.1.1.1</ip>
                                                  <port>443</port>
                                                  <protocol>TCP</protocol>
                                                  <country>US</country>
                                                  <details>
                                                  'info....'
                                                </details>
                                              </vpn>
                                              <vpn id="vpn03">
                                                  <config>1.1.1.1.ovpn</config>
                                                  <ip>1.1.1.1</ip>
                                                  <port>443</port>
                                                  <protocol>TCP</protocol>
                                                  <country>US</country>
                                                  <details>
                                                  'info....'
                                                </details>
                                              </vpn>
                                          
                                          </catalog>
                                          
                                          

                                          Im still strugling to get to grips with QT
                                          Many thanks!

                                          1 Reply Last reply
                                          0
                                          • Axel SpoerlA Offline
                                            Axel SpoerlA Offline
                                            Axel Spoerl
                                            Moderators
                                            wrote on last edited by
                                            #20

                                            I would definitively use a QTreeView and implement a model to view the XML tree.
                                            You can have a look a the document viewer example, to see how this can be implemented. It's in C++ and has a JSON viewer, but the principle is the same.

                                            Software Engineer
                                            The Qt Company, Oslo

                                            A 1 Reply Last reply
                                            0

                                            • Login

                                            • Login or register to search.
                                            • First post
                                              Last post
                                            0
                                            • Categories
                                            • Recent
                                            • Tags
                                            • Popular
                                            • Users
                                            • Groups
                                            • Search
                                            • Get Qt Extensions
                                            • Unsolved