Search code examples
pythonpyqtpyqt5alignmentqpushbutton

How to align a QPushButton inside window?


I want to align a QPushButton to the bottom right corner, but without a fixed size, because if I use a fixed size and resize the window, it doen't look good anymore. Here's my code:

    self.copy_btn = QtWidgets.QPushButton(self)
    self.copy_btn.setText("Copy")
    self.copy_btn.move(370, 350)

As you can see, I'm currenctly using .move(). I tried it with .setAlignment(QtCore.Qt.AlignRight), because it worked for the label, but it doesn't work for QPushButton.


Solution

  • There are several solutions depending on the context:

    • Using a QXBoxLayout

      from PyQt5 import QtCore, QtWidgets
      
      
      class Widget(QtWidgets.QWidget):
          def __init__(self, parent=None):
              super().__init__(parent)
      
              self.copy_btn = QtWidgets.QPushButton()
              self.copy_btn.setText("Copy")
      
              lay = QtWidgets.QVBoxLayout(self)
              lay.setContentsMargins(0, 0, 0, 0)
              lay.addStretch()
              lay.addWidget(self.copy_btn, alignment=QtCore.Qt.AlignRight)
      
              # or
              # lay = QtWidgets.QHBoxLayout(self)
              # lay.setContentsMargins(0, 0, 0, 0)
              # lay.addStretch()
              # lay.addWidget(self.copy_btn, alignment=QtCore.Qt.AlignBottom)
      
              self.resize(640, 480)
      
      
      if __name__ == "__main__":
          import sys
      
          app = QtWidgets.QApplication(sys.argv)
      
          w = Widget()
          w.show()
      
          sys.exit(app.exec_())
      
    • Using an eventFilter

      from PyQt5 import QtCore, QtWidgets
      
      
      class Resizer(QtCore.QObject):
          def __init__(self, widget):
              super().__init__(widget)
      
              self._widget = widget
      
              self.widget.installEventFilter(self)
              if not self.widget.isWindow():
                  self.widget.window().installEventFilter(self)
      
          @property
          def widget(self):
              return self._widget
      
          def eventFilter(self, obj, event):
              if obj is self.widget and not self.widget.isWindow():
                  if event.type() == QtCore.QEvent.ParentAboutToChange:
                      self.widget.window().removeEventFilter(self)
                  elif event.type() == QtCore.QEvent.ParentChange:
                      self.widget.window().installEventFilter(self)
      
              if obj is self.widget.window() and event.type() == QtCore.QEvent.Resize:
                  geom = self.widget.geometry()
                  geom.moveBottomRight(QtCore.QPoint(event.size().width(), event.size().height()))
                  self.widget.setGeometry(geom)
              return super().eventFilter(obj, event)
      
      
      class Widget(QtWidgets.QWidget):
          def __init__(self, parent=None):
              super().__init__(parent)
      
              self.copy_btn = QtWidgets.QPushButton(self)
              self.copy_btn.setText("Copy")
      
              resizer = Resizer(self.copy_btn)
              self.resize(640, 480)
      
      
      if __name__ == "__main__":
          import sys
      
          app = QtWidgets.QApplication(sys.argv)
      
          w = Widget()
          w.show()
      
          sys.exit(app.exec_())
      

      enter image description here