title: Overriding QPushButton Class Event Method with PySide
body: <p>I am wanting to make a custom button class that allows for <strong>clicking</strong> and <strong>drag and drop</strong>. I also want the ability to control the aesthetics of it (button color, mouse over color, clicked color, drag over color, etc.). </p>
  
  <p><strong><em>Note: these examples are shorter, generic versions of what I need to do. I know it doesn't contain all necessary things to work and some names of variables and functions are just examples. My real example will need as many as 15 instances of this class instead of the 4 shown.</em></strong></p>
  
  <p>In the example of <strong>clicking</strong> the button, as soon as I override the <strong>mousePressEvent</strong> and the <strong>mouseReleaseEvent</strong> the <code>my_button.clicked.connect(my_func)</code> statement no longer works. And being that I want to use this custom class for all kinds of button functions I can't just put the button functions in the overridden method, which is what my current solution is and I hate it (see below). I tried using the <code>super(DropZone_Category, self)mouseReleaseEvent(event)</code> statement after my style sheet changes (as suggested in other questions) but this did absolutely nothing for me. All I really wanted to do with these overrides was control the style sheet so if there is a better way to do this, please advise. </p>
  
  <pre><code>from PySide import QtGui, QtCore
  
  
  class DropZone_Category(QtGui.QPushButton):
      def __init__(self, parent=None, *args, **kwargs):
          super(DropZone_Category, self).__init__(parent, *args, **kwargs)
  
          # Instance Attrs
          self.parent = parent
  
          # Style Variables
          self.dropZone_font = QtGui.QFont()
          self.dropZone_font.setPointSize(16)
          self.dropZone_font.setFamily("Calibri")
          self.default_button_stylesheet = "background-color: rgb(100,100,100);" \
                                           "color: lightgrey;" \
                                           "border-radius: 3px;"
  
          self.drag_button_stylesheet = "background-color: rgb(166,215,176);" \
                                            "color: rgb(0,97,19);" \
                                            "border-radius: 3px;"
  
          self.hover_button_stylesheet =  "background-color: rgb(150,150,150);" \
                                           "color: lightgrey;" \
                                           "border-radius: 3px;"
  
          self.clicked_button_stylesheet = "background-color: rgb(80,80,80);" \
                                           "color: lightgrey;" \
                                           "border-radius: 3px;"
  
          # Overrides
          self.resize(QtCore.QSize(120, 120))
          self.setFont(self.dropZone_font)
          self.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
          self.setMinimumSize(90, 90)
          self.setAcceptDrops(True)
          self.setStyleSheet(self.default_button_stylesheet)
  
      def enterEvent(self, *args, **kwargs):
          self.setStyleSheet(self.hover_button_stylesheet)
  
      def leaveEvent(self, *args, **kwargs):
          self.setStyleSheet(self.default_button_stylesheet)
  
      def mousePressEvent(self, *args, **kwargs):
          self.setStyleSheet(self.clicked_button_stylesheet)
          # super(DropZone_Category, self).mousePressEvent(event)
  
      def mouseReleaseEvent(self, event,*args, **kwargs):
          button_used = self.text()
          self.setStyleSheet(self.default_button_stylesheet)
          # super(DropZone_Category, self).mouseReleaseEvent(event)
  
          if button_used == "btn1":
              btn1_clicked_func()
          elif button_used == "btn2":
              btn2_clicked_func()
          elif button_used == "btn3":
              btn3_clicked_func()
          elif button_used == "btn4":
              btn4_clicked_func()
  </code></pre>
  
  <p>In the example of the <strong>drag and drop</strong> functionality, I need an easier, cleaner way of setting up the drop function for each button, as it is different for each instance needed. Something similar to the <code>my_button.clicked.connect(my_func)</code> if possible. If not possible I'm open to other suggestions. I am currently handling it like the mouseReleaseEvent method above but in the <strong>dropEvent</strong> method, which I again...hate.</p>
  
  <pre><code>def dragEnterEvent(self, event):
          if event.mimeData().hasUrls():
              self.setStyleSheet(self.drag_button_stylesheet)
  
              event.acceptProposedAction()
          else:
              super(DropZone_Category, self).dragEnterEvent(event)
  
  def dragLeaveEvent(self, event):
      self.setStyleSheet(self.default_button_stylesheet)
  
  def dragMoveEvent(self, event):
      super(DropZone_Category, self).dragMoveEvent(event)
  
  def dropEvent(self, event):
      zone_used = self.text()
      paths_list = [url.toLocalFile() for url in event.mimeData().urls()]
      num_files = len(paths_list)
  
      if not utils.isImages(paths_list): # check if drop objects are images
          print "Drop Rejected: Not all files dropped were images"
      elif not event.mimeData().hasUrls(): # check if drop objects are files
          print "Drop Rejected: Not all items dropped were files"
      else:
          if button_used == "btn1":
              btn1_dropped_func(paths_list )
          elif button_used == "btn2":
              btn2_dropped_func(paths_list )
          elif button_used == "btn3":
              btn3_dropped_func(paths_list )
          elif button_used == "btn4":
              btn4_dropped_func(paths_list )
  
  
          sleep(.5)
          self.setStyleSheet(self.default_button_stylesheet)
  </code></pre>
  
  <p>As said above, the main reason for this mess is that that I really want to learn how to control the aesthetics of a UI. That coupled with the large number of very specific instances that will be used from these classes and the added drag and drop functionality has turned this into a headache for me. My current conclusion (with others advice) is to create a sub class of this base class for each special instance I need (ie 15 subclasses of DropZone_Categories). I would really hate to do this because it feels like it violates the entire reason for making classes. If this is the only solution I will happily do it but I just wanted to see before making even more of a mess. Thanks and SORRY for for the long post. </p>