sdbbs
sdbbs

Reputation: 5384

Vertically centering a QLineEdit in QWidget in QTableWidget cell in PyQt5?

Ok, so I have a table widget placed in QtDesigner; then I programmatically try to add a widget consisting of labels and a line edit as a cell in that table.

As you can see from the screenshot:

pyqt5-table-with-widget

... the labels seem to be vertically centered in the cell - but the line edit is so much down, it actually goes out of the bounds of the cell.

How can I have the line edit centrally vertically aligned in the cell - same as the labels? Or more precisely - how can I have the text inside the line edit be the same size and alignment as the text in the labels?

test.ui:

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>400</width>
    <height>300</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <layout class="QHBoxLayout" name="horizontalLayout">
    <item>
     <widget class="QTableWidget" name="tableWidget">
      <column>
       <property name="text">
        <string>Hello</string>
       </property>
      </column>
      <column>
       <property name="text">
        <string>World</string>
       </property>
      </column>
     </widget>
    </item>
   </layout>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>400</width>
     <height>21</height>
    </rect>
   </property>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <resources/>
 <connections/>
</ui>

test.py

import sys
from PyQt5 import QtCore, QtWidgets, QtGui, uic
from PyQt5.QtCore import pyqtSlot


class MyMainWindow(QtWidgets.QMainWindow):
  def __init__(self):
    super(MyMainWindow, self).__init__()
    uic.loadUi('test.ui', self)
    QtCore.QTimer.singleShot(1, self.delayed_init)
    self.show()

  def delayed_init(self):
    # stretch the column widths manually - must be in delayed_init, in __init__ table does not yet know its own width
    numcols = self.tableWidget.columnCount()
    newcolwidth = int( self.tableWidget.width()/numcols )
    for i in range(numcols):
      self.tableWidget.setColumnWidth(i, newcolwidth) # SO:46715061
    # test - add cell
    self.tableWidget.setRowCount(2)
    linewidget = QtWidgets.QWidget(self.tableWidget)
    linelayout = QtWidgets.QHBoxLayout()
    linewidget.setLayout(linelayout)
    linelbl1 = QtWidgets.QLabel()
    linelbl1.setText("Hello ")
    lineedit = QtWidgets.QLineEdit(linewidget)
    lineedit.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Expanding)
    lineedit.setMinimumHeight( self.tableWidget.verticalHeader().minimumSectionSize() + 10 )
    lineedit.setMaximumWidth( 30 )
    lineedit.setMaxLength( 3 ) # 3 characters
    linelbl2 = QtWidgets.QLabel()
    linelbl2.setText(" buddy")
    linelayout.addWidget(linelbl1)
    linelayout.addWidget(lineedit, QtCore.Qt.AlignCenter)
    linelayout.addWidget(linelbl2)
    self.tableWidget.setCellWidget(0, 1, linewidget)



def main():
  app = QtWidgets.QApplication(sys.argv)
  window = MyMainWindow()
  sys.exit(app.exec_())

if __name__ == "__main__":
  main()

Upvotes: 0

Views: 482

Answers (1)

musicamante
musicamante

Reputation: 48260

The line edit is vertically centered, or at least it tries to: the problem is that you're setting a minimum height bigger than the available vertical space for the item, and since the widget is too tall, it cannot move higher than it already is.

Here is how it would appear when enough space is given:

optimal size

But, when the available space is smaller than the line edit height, the result is this:

not very good

Remember that, while you can technically make a widget smaller than its contents, the origin point will always be the top left, no matter what alignment is set for children added to its layout.

A partial solution is to set the layout's contents margins to 0, so that the cell widget will be able to use as much space as possible:

    linelayout.setContentsMargins(0, 0, 0, 0)

But you'll always end up with some alignment problems, so you either avoid setting a minimum height for the lineedit or you set a minimum height for the vertical header sections that gives the lineedit enough space:

    lineedit.setMinimumHeight(self.tableWidget.verticalHeader().defaultSectionSize() + 10)
    # ...
    self.tableWidget.verticalHeader().setDefaultSectionSize(linewidget.sizeHint().height())

Upvotes: 1

Related Questions