title: Pyqt5 - grid layout misbehaving
body: <p>So I'm trying to get a grip on Qt (more specifically, Pyqt), and I want to create a simple feedback form. It should have </p>
  
  <ul>
  <li>a title</li>
  <li>a name ('author')</li>
  <li>a message</li>
  <li>a send and a cancel button</li>
  </ul>
  
  <p>Let's try without the buttons, first (the <code>App</code> class just provides a button to create a popup. the question concerns the <code>Form</code> class below it):</p>
  
  <pre><code>import sys
  from PyQt5.QtWidgets import QApplication, QWidget, QMainWindow, QDesktopWidget,\
      QHBoxLayout, QVBoxLayout, QGridLayout,\
      QPushButton, QLabel,QLineEdit, QTextEdit,\
      qApp
  from PyQt5.QtGui import QIcon
  
  
  class App(QMainWindow):
  
      def __init__(self):
          super().__init__()
          self.title = 'PyQt5 Layout Demo'
          self.popup = None
  
          self.initUI()
  
      def initUI(self):
          self.setWindowTitle(self.title)
          self.setWindowIcon(QIcon('imgs/python3.png'))
  
          formButton = QPushButton("show form")
          formButton.clicked.connect(self.showPopup)
  
          formBox = QHBoxLayout()
          formBox.addWidget(formButton)
          formBox.addStretch(1)
  
          vbox = QVBoxLayout()
          vbox.addLayout(formBox)
          vbox.addStretch(1)
  
          # self.setLayout(vbox)  # would work if this was a QWidget
  
          # instead, define new central widget
          window = QWidget()
          window.setLayout(vbox)
          self.setCentralWidget(window)
  
          self.center(self)
          self.show()
  
      @staticmethod
      def center(w: QWidget):
          qr = w.frameGeometry()  # get a rectangle for the entire window
  
          # center point = center of screen resolution
          cp = QDesktopWidget().availableGeometry().center()
  
          qr.moveCenter(cp)  # move center of rectangle to cp
          w.move(qr.topLeft())  # move top-left point of window to top-let point of rectangle
  
      def showPopup(self):
          if self.popup is None:
              self.popup = Form(self)
              self.popup.setGeometry(10, 10, 300, 400)
              self.center(self.popup)
  
          self.popup.show()
  
  
  class Form(QWidget):
      def __init__(self, main):
          super().__init__()
          self.initUI()
          self.main = main
  
      def initUI(self):
          self.setWindowTitle('Feedback')
          self.setWindowIcon(QIcon('imgs/python3.png'))
  
          title = QLabel('Title')
          author = QLabel('Author')
          message = QLabel('Message')
  
          titleEdit = QLineEdit()
          authorEdit = QLineEdit()
          messageEdit = QTextEdit()
  
          grid = QGridLayout()
          grid.setSpacing(10)
  
          grid.addWidget(title, 1, 0)
          grid.addWidget(titleEdit,1, 1)
  
          grid.addWidget(author, 2, 0)
          grid.addWidget(authorEdit,2, 1)
  
          grid.addWidget(message, 3, 0)
          grid.addWidget(messageEdit, 4, 0, 6, 0)
  
          self.setLayout(grid)
  
      # probably should delegate to self.main, but bear with me
      def send(self):
          self.main.popup = None
          self.hide()
  
      def cancel(self):
          self.hide()
  
  if __name__ == '__main__':
      app = QApplication(sys.argv)
      ex = App()
      sys.exit(app.exec_())
  </code></pre>
  
  <p><a href="https://i.stack.imgur.com/NZGWu.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/NZGWu.png" alt="enter image description here"></a></p>
  
  <p>Ok, looks about right. There's a bit too much spacing in-between the line edits and the text edit, but since I want to add some buttons below it, that should be be a problem.</p>
  
  <p>So I add:</p>
  
  <pre><code>    sendBtn = QPushButton("send")
      cancelBtn = QPushButton("cancel")
  
      sendBtn.clicked.connect(self.send)
      cancelBtn.clicked.connect(self.cancel)
  
      grid.addWidget(sendBtn, 7, 1)
      grid.addWidget(cancelBtn, 7, 2)
  </code></pre>
  
  <p>which yields</p>
  
  <p><a href="https://i.stack.imgur.com/TLgDw.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/TLgDw.png" alt="enter image description here"></a></p>
  
  <p>Now obviously, I forgot to stretch the title and author line edits to the newly introduced column 2. Easy enough to fix but what really bothers me is the placement of the buttons.</p>
  
  <p><em>WHY</em> do they show up in the middle of the text edit? I can see how Qt chooses the column size, and why that would lead to the buttons' being of different size, but since the tutorial doesn't actually add buttons to the form, I have no idea how to fix that.</p>
  
  <p>I could, of course, simply add boxes:</p>
  
  <pre><code>sendBtn = QPushButton("send")
  cancelBtn = QPushButton("cancel")
  
  sendBtn.clicked.connect(self.send)
  cancelBtn.clicked.connect(self.cancel)
  
  btns = QHBoxLayout()
  btns.addStretch(1)
  btns.addWidget(sendBtn)
  btns.addWidget(cancelBtn)
  
  l = QVBoxLayout()
  l.addLayout(grid)
  l.addLayout(btns)
  
  self.setLayout(l)
  </code></pre>
  
  <p>With which the popup then actually starts looking closer to something acceptable:</p>
  
  <p><a href="https://i.stack.imgur.com/Amjk8.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/Amjk8.png" alt="enter image description here"></a></p>
  
  <p>But is there a way to fix this within the grid layout, instead?</p>