Re: (pyqt)set different column font for qtableview

Maziar Parsijani <[email protected]>
Newsgroups gmane.comp.python.pyqt-pykde
Message-ID <CAPD04aOTaKVrCJ_xno5bn61SKA+uFwoxi3oBrUX_SkLjaX2uOg@mail.gmail.com>
This is great, thank you so much!

On Fri, Apr 26, 2019 at 3:43 AM Maurizio Berti <[email protected]>
wrote:

> Il giorno gio 25 apr 2019 alle ore 21:04 Maziar Parsijani <
> [email protected]> ha scritto:
>
>> Hi
>> I want to know if it is possible to change font for each column in
>> Qtableview and if it is possible even more different appearances in columns
>> like backgrounds and font colors.
>>
>
>
> There are different possible approaches, and the choice usually depends on
> how the table data is filled and if it's editable.
> The most common way is to set the QtCore.Qt.ItemDataRole for each field
> index, by providing the FontRole, ForegroundRole and BackgroundRole to the
> index.setData(value, role).
> If you're using a QStandardItemModel, the data is simple and you don't
> need interaction, just use setData method on each item.
>
> If you are using any model based on QAbstractItemModel you could subclass
> its data method like this:
>
> class SimpleModel(QtGui.QStandardItemModel):
>     backgrounds = QtGui.QColor(QtCore.Qt.lightGray),
> QtGui.QColor(QtCore.Qt.darkCyan), QtGui.QColor(QtCore.Qt.darkGray)
>     foregrounds = QtGui.QColor(QtCore.Qt.darkGreen),
> QtGui.QColor(QtCore.Qt.darkBlue), QtGui.QColor(QtCore.Qt.yellow)
>     fonts = QtGui.QFont('monospace'), QtGui.QFont(), QtGui.QFont('times')
>
>     def data(self, index, role=QtCore.Qt.DisplayRole):
>         if role == QtCore.Qt.BackgroundRole:
>             return self.backgrounds[index.column()]
>         elif role == QtCore.Qt.ForegroundRole:
>             return self.foregrounds[index.column()]
>         elif role == QtCore.Qt.FontRole:
>             return self.fonts[index.column()]
>         return QtGui.QStandardItemModel.data(self, index, role)
>
> Note that you could also set a QIdentityProxyModel with your original
> model (and use the proxy on the table instead) and then implement the
> data() method in the same way. Just use the code above with
> QIdentityProxyModel instead of QStandardItemModel, do a
> setSource(originalModel) and you're done; this is usually better and much
> more transparent.
>
> If you cannot have that kind of access, the alternative is to create your
> own item delegate subclass and implement the paint() method. Be aware that
> item painting is not an easy task, expecially if you want to mimic the
> default implementation.
>
> class SimpleDelegate(QtWidgets.QStyledItemDelegate):
>     backgrounds = QtGui.QColor(QtCore.Qt.lightGray),
> QtGui.QColor(QtCore.Qt.darkCyan), QtGui.QColor(QtCore.Qt.darkGray)
>     foregrounds = QtGui.QColor(QtCore.Qt.darkGreen),
> QtGui.QColor(QtCore.Qt.darkBlue), QtGui.QColor(QtCore.Qt.yellow)
>     fonts = QtGui.QFont('monospace'), QtGui.QFont(), QtGui.QFont('times')
>     fontData = zip(backgrounds, foregrounds, fonts)
>
>     def paint(self, qp, option, index):
>         #painting needs performance, let's get all data at once
>         background, foreground, font = self.fontData[index.column()]
>
>         # never reuse the given option argument, always create a new one
> based on it!
>         # reusing QStyleOptions might create issues and inconsistencies
> with item "siblings"
>         option = QtWidgets.QStyleOptionViewItem(option)
>         self.initStyleOption(option, index)
>
>         # reset the text so that QStyle won't paint it
>         option.text = ''
>         option.backgroundBrush = background
>
>         widget = option.widget
>         style = widget.style()
>
>         # we could use the drawPrimitive instead, but it won't paint the
> decoration (icon),
>         # if it exists; drawControl paints everything, that's why I
> cleared the text before,
>         # otherwise you'll see the text drawn twice
>         style.drawControl(QtWidgets.QStyle.CE_ItemViewItem, option, qp)
>         #style.drawPrimitive(QtWidgets.QStyle.PE_PanelItemViewItem,
> option, qp)
>
>         # get the rectangle available for item text and adjust it to
> standard margins;
>         # one pixel is added for consistency with the original Qt painting
> behavior
>         textRect = style.subElementRect(style.SE_ItemViewItemText, option,
> widget)
>         margin = style.pixelMetric(style.PM_FocusFrameHMargin, option,
> widget) + 1
>         textRect.adjust(margin, 0, -margin, 0)
>
>         # set the foreground color to the palette (not to the painter!)
>         option.palette.setColor(option.palette.Active,
> option.palette.Base, foreground)
>         # if you want to have differrent colors for disabled items, use
> again the setColor
>         # method with option.palette.Disabled
>         #option.palette.setColor(option.palette.Disabled,
> option.palette.Base, disabledColor)
>
>         qp.setFont(font)
>         style.drawItemText(qp, textRect,
> style.visualAlignment(option.direction, option.displayAlignment),
>             option.palette, option.state & style.State_Enabled,
>             option.fontMetrics.elidedText(index.data(),
> option.textElideMode, textRect.width()),
>             option.palette.Base)
>
>
> class MyTable(QtWidget.QTableView):
>     def __init__(self, *args, **kwargs):
>         QtWidgets.QTableView.__init__(self, *args, **kwargs)
>         self.setItemDelegate(SimpleDelegate())
>
>
> Unfortunately, this is not quite perfect: while it should be fine for most
> user cases, it doesn't take into account the word wrapping, meaning that
> the text will always be on one line, no matter how much the row height is
> big. To fix this, it would take about 60-70 more lines of code, which would
> be run at each paintEvent for each visible item. Not always a good idea,
> but if you think it's good enough, you can find how it's done from the
> calculateElidedText method called by viewItemDrawText in here:
> https://code.woboq.org/qt5/qtbase/src/widgets/styles/qcommonstyle.cpp.html
>
> Cheers,
> Maurizio
>
> --
> È difficile avere una convinzione precisa quando si parla delle ragioni
> del cuore. - "Sostiene Pereira", Antonio Tabucchi
> http://www.jidesk.net
>

_______________________________________________
PyQt mailing list    [email protected]
https://www.riverbankcomputing.com/mailman/listinfo/pyqt
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.