Search code examples
pythonpyside2qabstracttablemodel

How to align one number to the left and one to the right in the same cell? Also make them different colour


I have a QAbstractTableModel and I want to draw one number aligned to the left and one to the right in the same cell like this:

╔══════════════════════╦═════╗
║ 31             +15   ║ foo ║
║══════════════════════╦═════║
║ 11             +15   ║ xxx ║
║══════════════════════╦═════║
║ 15             +15   ║ aaa ║
╚══════════════════════╩═════╝

I also want the left number to have a different colour than the right number

I am using PySide2 with Python 3 but solution in any language is welcome

This is the code I currently use to set data in cells.

    def data(self, index, role=Qt.DisplayRole):
        if index.isValid():
            if role == Qt.DisplayRole:
                return str(self.data[index.row()][index.column()]) + " +15" #how do I align right and change colour
        return None

I thought of making two separate columns and hiding the line between but I believe there must be a better solution.


Solution

  • Here you go. This should point you in the right direction. I'm using a standard model because that's what I have available, but the setup should work for any sort of model.

    Check out this example for a more in depth look at delegates: Star Delegate

    My code answer:

    Table delegate

    import sys
    
    from PySide2 import QtGui, QtCore, QtWidgets
    
    
    data = {
        "31":{
            "status":"foo"
        },
        "11":{
            "status":"xxx"
        },
        "15":{
            "status":"aaa"
        }
    }
    
    class MyTableDelegate(QtWidgets.QItemDelegate):
        def __init__(self, view):
            super(MyTableDelegate, self).__init__()
            self._view = view
    
        def paint(self, painter, option, index):
    
            rect_item = option.rect
    
            # Get Left number
            index_number = index.data(role=QtCore.Qt.DisplayRole)
    
            # Position left number
            rect_number = QtCore.QRect(
                rect_item.left(),
                rect_item.top(),
                rect_item.width(),
                rect_item.height()
            )
    
            font_name = QtGui.QFont("Segoe UI", 12, QtGui.QFont.Normal)
    
            # Store default painter settings
            painter.save()
            painter.setPen(QtGui.QColor('#af1cbd'))
            painter.setFont(font_name)
    
            # Draw text
            QtWidgets.QApplication.style().drawItemText(
                painter,
                rect_number,
                QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter,
                QtWidgets.QApplication.palette(),
                True,
                index_number)
    
            painter.restore()
    
            # Get +15
            index_number = index.data(role=QtCore.Qt.UserRole)
    
            # Position +15
            rect_plus15 = QtCore.QRect(
                rect_item.right() - (rect_item.width()/2),
                rect_item.top(),
                rect_item.width(),
                rect_item.height()
            )
    
            font_name = QtGui.QFont("Segoe UI", 12, QtGui.QFont.Normal)
    
            # Store default painter settings
            painter.save()
            painter.setPen(QtGui.QColor('#1bcc4a'))
            painter.setFont(font_name)
    
            # Draw text
            QtWidgets.QApplication.style().drawItemText(
                painter,
                rect_plus15,
                QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter,
                QtWidgets.QApplication.palette(),
                True,
                str(index_number))
    
            painter.restore()
    
    
    class MainWindow(QtWidgets.QMainWindow):
    
        def __init__(self):
            super(MainWindow, self).__init__()
    
            self.tableview = QtWidgets.QTableView()
            self.tableview.setItemDelegateForColumn(0, MyTableDelegate(self.tableview))
    
            self.setCentralWidget(self.tableview)
    
            self.model = QtGui.QStandardItemModel()
            self.tableview.setModel(self.model)
            self.fillModel()
    
            self.show()
    
        def fillModel(self):
            # For key in dict data
            for i in data:
                name_str = i
                status_str = data[i]["status"]
    
                # Store data in 1st column item using roles
                item_0 = QtGui.QStandardItem()
                item_0.setData(name_str, QtCore.Qt.DisplayRole)
                item_0.setData('+15', QtCore.Qt.UserRole)
                # How to store more data:
                # item_0.setData(+15, QtCore.Qt.UserRole + 1)
                # item_0.setData(+15, QtCore.Qt.UserRole + 2)
                # item_0.setData(+15, QtCore.Qt.UserRole + etc)
                # UserRole is just an integer. This lets you store a bunch of data
    
                # Store data in 2nd column item using roles
                item_1 = QtGui.QStandardItem()
                item_1.setData(status_str, QtCore.Qt.DisplayRole)
    
                # Append row
                items = [item_0, item_1]
                self.model.appendRow(items)
    
    
    if __name__ == '__main__':
        app = QtWidgets.QApplication(sys.argv)
        ex = MainWindow()
        sys.exit(app.exec_())