Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Language Bindings
  4. PySide - Source functions defined outside of a class
Forum Updated to NodeBB v4.3 + New Features

PySide - Source functions defined outside of a class

Scheduled Pinned Locked Moved Language Bindings
10 Posts 2 Posters 6.2k Views 1 Watching
  • 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.
  • B Offline
    B Offline
    Blackbear
    wrote on last edited by
    #1

    First, I am very new to pySide. Been using about a week.

    I am using designer-qt4 in Mint Linux to create the GUI and pyside-uic utility to generate the python code. For the most part it works very well. One thing I have not figured out is how to properly call functions not defined within the class structure that pyside-uic creates.

    Example the following works when added to the class definition.

    @def get_quota(self):
    process = subprocess.Popen(['df', '-kh'], stdout=subprocess.PIPE)
    quotaoutput = process.communicate()[0]
    self.txtQuota.clear()
    self.txtQuota.append(quotaoutput)@

    The function is called with a pushbutton, 'self.btnQuota.clicked.connect(self.get_quota)'.

    The push button and most of the GUI elements are created in a def statement called 'setupUi' defined within the class object. The class is called Ui_StatCheck(object).

    If this code is in a seperate file called defs.py and use 'from defs import *' I get errors.

    First, the GUI wouldn't start and I got this error returned;

    bq. Traceback (most recent call last):
    File "./top.py", line 13, in <module>
    statchk = ControlStatCheck()
    File "./top.py", line 9, in init
    self.ui.setupUi(self)
    File "/home/howell/scripts/pySide/statchk_scratch/statchk.py", line 44, in setupUi
    self.btnQuota.clicked.connect(self.get_quota)
    AttributeError: 'Ui_StatCheck' object has no attribute 'get_quota'

    Changed the command to 'self.btnQuota.clicked.connect(get_quota)' and the GUI would start but clicking the button caused the following error.

    bq. TypeError: get_quota() takes exactly 1 argument (0 given)

    I can keep the function definitions within the class and keep working but I'd prefer to minimize the editing everytime I change the GUI in designer.

    I am open to suggestions. Thanks in advance.

    1 Reply Last reply
    0
    • jazzycamelJ Offline
      jazzycamelJ Offline
      jazzycamel
      wrote on last edited by
      #2

      Your issue is simply that if 'get_quota' is defined as a function rather than a method then it cannot expect (and will not receive) the 'self' parameter. The following example works with PyQt4 (and should with PySide):

      @
      from PyQt4.QtCore import *
      from PyQt4.QtGui import *

      def mySlot(): print "SLOT"

      class MyGui(QWidget):
      def init(self, parent=None, **kwargs):
      QWidget.init(self, parent, **kwargs)

          l=QVBoxLayout(self)
          p=QPushButton("Test", self)
          p.clicked.connect(mySlot)
          l.addWidget(p)
      

      if name=="main":
      from sys import argv, exit

      a=QApplication(argv)
      m=MyGui()
      m.show()
      m.raise_()
      exit(a.exec_())
      

      @

      Hope this helps ;o)

      For the avoidance of doubt:

      1. All my code samples (C++ or Python) are tested before posting
      2. As of 23/03/20, my Python code is formatted to PEP-8 standards using black from the PSF (https://github.com/psf/black)
      1 Reply Last reply
      0
      • jazzycamelJ Offline
        jazzycamelJ Offline
        jazzycamel
        wrote on last edited by
        #3

        Also, the following example shows keeping the subprocess functionality generic by creating it's own class which is simply instantiated by the GUI and using signals and slots to communicate to remove requirement for your static function:

        @
        from PyQt4.QtCore import *
        from PyQt4.QtGui import *

        class QuotaProcess(QProcess):
        quota=pyqtSignal(str)
        def getQuota(self):
        self.start('df',['-kh'])

            if self.waitForReadyRead():
                self.quota.emit(str(self.readAllStandardOutput()))
            self.waitForFinished()
        

        class MyGui(QWidget):
        def init(self, parent=None, **kwargs):
        QWidget.init(self, parent, **kwargs)

            qp=QuotaProcess(self)
        
            l=QVBoxLayout(self)
            p=QPushButton("Test", self)
            p.clicked.connect(qp.getQuota)
            l.addWidget(p)
        
            q=QLabel(self)
            qp.quota.connect(q.setText)
            l.addWidget(q)
        

        if name=="main":
        from sys import argv, exit

        a=QApplication(argv)
        m=MyGui()
        m.show()
        m.raise_()
        exit(a.exec_())
        

        @

        Hope this helps too ;o)

        For the avoidance of doubt:

        1. All my code samples (C++ or Python) are tested before posting
        2. As of 23/03/20, my Python code is formatted to PEP-8 standards using black from the PSF (https://github.com/psf/black)
        1 Reply Last reply
        0
        • B Offline
          B Offline
          Blackbear
          wrote on last edited by
          #4

          Hi Ant Farmer,

          Neither of these worked for me.

          The first solution tells me "NameError: global name 'txtQuota' is not defined"

          The second solution tells me "NameError: name 'QProcess' is not defined"

          Thanks for your help anyway.

          Cheers,

          1 Reply Last reply
          0
          • jazzycamelJ Offline
            jazzycamelJ Offline
            jazzycamel
            wrote on last edited by
            #5

            Can you actually run my examples simply changing the imports from PyQt4 to PySide (they both work fine for me)? Try that before trying to integrate your code with mine. Also, posting your full code would help us help you ;o)

            Your name error for QProcess probably means you haven't imported it:

            @
            ...
            from PySide.QtCore import QProcess
            ...
            @

            Hope this helps ;o)

            For the avoidance of doubt:

            1. All my code samples (C++ or Python) are tested before posting
            2. As of 23/03/20, my Python code is formatted to PEP-8 standards using black from the PSF (https://github.com/psf/black)
            1 Reply Last reply
            0
            • B Offline
              B Offline
              Blackbear
              wrote on last edited by
              #6

              I created a simple demo to illustrate what I am trying to do.

              @#!/usr/bin/python

              import subprocess
              from PySide import QtCore, QtGui

              class Ui_MainWindow(object):
              def setupUi(self, MainWindow):
              MainWindow.setObjectName("MainWindow")
              MainWindow.resize(526, 305)
              self.centralwidget = QtGui.QWidget(MainWindow)
              self.centralwidget.setObjectName("centralwidget")
              self.pshLs = QtGui.QPushButton(self.centralwidget)
              self.pshLs.setGeometry(QtCore.QRect(20, 20, 51, 27))
              self.pshLs.setObjectName("pshLs")
              self.textEdit = QtGui.QTextEdit(self.centralwidget)
              self.textEdit.setGeometry(QtCore.QRect(90, 20, 411, 261))
              self.textEdit.setObjectName("textEdit")
              MainWindow.setCentralWidget(self.centralwidget)
              self.pshLs.clicked.connect(self.list_dir)
              self.retranslateUi(MainWindow)
              QtCore.QMetaObject.connectSlotsByName(MainWindow)

              def retranslateUi(self, MainWindow):
                MainWindow.setWindowTitle(QtGui.QApplication.translate("MainWindow", "MainWindow", None, QtGui.QApplication.UnicodeUTF8))
                  self.pshLs.setText(QtGui.QApplication.translate("MainWindow", "ls", None, QtGui.QApplication.UnicodeUTF8))
              
              def list_dir(self):
                  process = subprocess.Popen(['ls'], stdout=subprocess.PIPE)
                  quotaoutput = process.communicate()[0]
                  self.textEdit.clear()
                  self.textEdit.append(quotaoutput)
              

              if name == "main":
              import sys
              app = QtGui.QApplication(sys.argv)
              MainWindow = QtGui.QMainWindow()
              ui = Ui_MainWindow()
              ui.setupUi(MainWindow)
              MainWindow.show()
              sys.exit(app.exec_())
              @

              The preview appears to have broken the indentation but the above works. What does not work is when I place the 'list_dir' function in another file called 'list_dir.py and use 'import list_dir' in the above.

              1 Reply Last reply
              0
              • B Offline
                B Offline
                Blackbear
                wrote on last edited by
                #7

                BTW: this is the error I get;

                @Traceback (most recent call last):
                File "./ls.py", line 39, in <module>
                ui.setupUi(MainWindow)
                File "./ls.py", line 25, in setupUi
                self.pshLs.clicked.connect(list_dir(self))
                RuntimeError: Failed to connect signal clicked().
                @

                1 Reply Last reply
                0
                • B Offline
                  B Offline
                  Blackbear
                  wrote on last edited by
                  #8

                  jazzycamel, in your second example -is there a pyside version of pyqtSignal-?

                  update: nevermind - I found it.

                  Noticed that your method works with QWidget but not with QMainWindow.

                  Tried this and the window comes up but the test button does not do anything. No errors are returned.

                  @#!/usr/bin/python

                  from PySide.QtCore import *
                  from PySide.QtGui import *

                  class QuotaProcess(QProcess):
                  quota=Signal(str)
                  def getQuota(self):
                  self.start('df',['-kh'])

                      if self.waitForReadyRead():
                          self.quota.emit(str(self.readAllStandardOutput()))
                      self.waitForFinished()
                  

                  class MyGui(QMainWindow):
                  def init(self, parent=None, **kwargs):
                  QMainWindow.init(self, parent, **kwargs)

                      qp=QuotaProcess(self)
                  
                      #l=QVBoxLayout(self)
                      p=QPushButton("Test", self)
                      p.clicked.connect(qp.getQuota)
                      #self.addWidget(p)
                  
                      q=QLabel(self)
                      qp.quota.connect(q.setText)
                      #self.addWidget(q)
                  

                  if name=="main":
                  from sys import argv, exit

                  a=QApplication(argv)
                  m=MyGui()
                  m.show()
                  m.raise_()
                  exit(a.exec_())
                  

                  @

                  1 Reply Last reply
                  0
                  • jazzycamelJ Offline
                    jazzycamelJ Offline
                    jazzycamel
                    wrote on last edited by
                    #9

                    When using QMainWindow you need to place your widgets on a single central widget, read the "Qt Main Window Framework":http://qt-project.org/doc/qt-4.8/qmainwindow.html#details section of the docs for more information. I've modified your code to work as follows:

                    @
                    #!/usr/bin/python
                    from PySide.QtCore import *
                    from PySide.QtGui import *

                    class QuotaProcess(QProcess):
                    quota=Signal(str)

                    def getQuota(self):
                        self.start('df',['-kh'])
                       
                        if self.waitForReadyRead():
                            self.quota.emit(str(self.readAllStandardOutput()))
                        self.waitForFinished()
                    

                    class MyGui(QMainWindow):
                    def init(self, parent=None, **kwargs):
                    QMainWindow.init(self, parent, **kwargs)

                        qp=QuotaProcess(self)
                    
                        w=QWidget(self)
                        l=QVBoxLayout(w)
                    
                        p=QPushButton("Test", self)
                        p.clicked.connect(qp.getQuota)
                        l.addWidget(p)
                    
                        q=QLabel(self)
                        qp.quota.connect(q.setText)
                        l.addWidget(q)
                    
                        self.setCentralWidget(w)
                    

                    if name=="main":
                    from sys import argv, exit

                    a=QApplication(argv)
                    m=MyGui()
                    m.show()
                    m.raise_()
                    exit(a.exec_())
                    

                    @

                    Hope this helps ;o)

                    For the avoidance of doubt:

                    1. All my code samples (C++ or Python) are tested before posting
                    2. As of 23/03/20, my Python code is formatted to PEP-8 standards using black from the PSF (https://github.com/psf/black)
                    1 Reply Last reply
                    0
                    • B Offline
                      B Offline
                      Blackbear
                      wrote on last edited by
                      #10

                      Still new to PySide but learning. My motivation for this was to isolate the GUI/interface coding from the functional coding.

                      I found a way to reference .ui xml files created in qt designer directly. Now I can easily make changes to the ui without having to touch the python code at all.

                      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