Search code examples
pythonpyqtalignmentqtreeviewqlistview

PyQt: align text left and right in a QListView


I have a list-view which shows lists of strings representing key, value pairs. The strings all have the same character length, but due to the different pixel length, they show a different length in the list. So, it looks something like this:

someValue         1000.93
someOtherValue     98.7
oneMoreValue     11200000.00

Is there a way to nicely format the strings so that it looks aligned left and right, like this:

someValue          1000.93
someOtherValue        98.7
oneMoreValue   11200000.00

I create the strings like this:

s = '{:20}'.format(key) + '{:>20}'.format(val)

Solution

  • A QTreeView can be configured to work like a QListView, which will then allow for multiple columns. Each column can then have its own aligment settings (amongst other things). It will also preserve the alignment after resizing.

    A basic implementation would be something like this:

    import sys
    from PyQt5 import QtCore, QtGui, QtWidgets
    
    class ListView(QtWidgets.QTreeView):
        def __init__(self, *args, **kwargs):
            super(ListView, self).__init__(*args, **kwargs)
            self.setModel(QtGui.QStandardItemModel(self))
            self.model().setColumnCount(2)
            self.setRootIsDecorated(False)
            self.setAllColumnsShowFocus(True)
            self.setSelectionBehavior(
                QtWidgets.QAbstractItemView.SelectRows)
            self.setHeaderHidden(True)
            self.header().setStretchLastSection(False)
            self.header().setSectionResizeMode(
                0, QtWidgets.QHeaderView.Stretch)
            self.header().setSectionResizeMode(
                1, QtWidgets.QHeaderView.ResizeToContents)
    
        def addItem(self, key, value):
            first = QtGui.QStandardItem(key)
            second = QtGui.QStandardItem(value)
            second.setTextAlignment(QtCore.Qt.AlignRight)
            self.model().appendRow([first, second])
    
    class Window(QtWidgets.QWidget):
        def __init__(self):
            super(Window, self).__init__()
            self.view = ListView(self)
            for text in 'Aquamarine Red Green Purple Blue Yellow '.split():
                self.view.addItem(text, str(16 ** len(text)))
            layout = QtWidgets.QVBoxLayout(self)
            layout.addWidget(self.view)
    
    if __name__ == '__main__':
    
        app = QtWidgets.QApplication(sys.argv)
        window = Window()
        window.setGeometry(600, 100, 300, 200)
        window.show()
        sys.exit(app.exec_())