Yes, I have mouse tracking enabled.
Maybe my description of the issue was not very clear, sorry. When I click for the first time on the button, it does not change its style to QStyle.State_Sunken and then back to QStyle.State_Raised on release, this happens only on the every second click. Also button does not change its style on mouse hover.
Here is a minimal example
import sys from PyQt5.QtGui import * from PyQt5.QtCore import * from PyQt5.QtWidgets import * class MyDelegate(QStyledItemDelegate): def __init__(self): super(MyDelegate, self).__init__() self.buttonRect = None def sizeHint(self, option, index): fm = QFontMetrics(option.font) return QSize(150, fm.height() * 5 + fm.leading()) def paint(self, painter, option, index): name = index.data(Qt.DisplayRole) description = index.data(Qt.UserRole + 1) btnStyle = QStyle.State(index.data(Qt.UserRole + 2)) nameFont = QFont(option.font) nameFont.setWeight(QFont.Weight.Bold) fm = QFontMetrics(nameFont) padding = fm.lineSpacing() // 2 nameRect = QRect(option.rect) nameRect.setLeft(nameRect.left() + padding) nameRect.setTop(nameRect.top() + padding) nameRect.setRight(nameRect.right() - padding) nameRect.setHeight(fm.lineSpacing()) descrRect = QRect(option.rect) descrRect.setLeft(descrRect.left() + padding) descrRect.setTop(nameRect.bottom()) descrRect.setRight(descrRect.right() - padding) descrRect.setHeight(fm.lineSpacing()) btnText = "Add" textWidth = fm.width(btnText) self.btnRect = QRect(option.rect) self.btnRect.setLeft(descrRect.right() - textWidth * 2) self.btnRect.setTop(descrRect.bottom() + padding) self.btnRect.setRight(descrRect.right() - padding) self.btnRect.setHeight(fm.lineSpacing() * 2) borderRect = QRect(option.rect.marginsRemoved(QMargins(4, 4, 4, 4))) painter.save() pen = painter.pen() if option.state & QStyle.State_MouseOver: pp = QPen(option.palette.highlight().color()) pp.setWidth(2) painter.setPen(pp) painter.drawRect(borderRect) painter.setPen(pen) painter.setFont(nameFont) elided_text = fm.elidedText(name, Qt.ElideRight, nameRect.width()) painter.drawText(nameRect, Qt.AlignLeading, elided_text) painter.setFont(option.font) fm = QFontMetrics(QFont(option.font)) elided_text = fm.elidedText(description, Qt.ElideRight, descrRect.width()) painter.drawText(descrRect, Qt.AlignLeading, elided_text) button = QStyleOptionButton() button.text = btnText button.state = btnStyle button.rect = self.btnRect QApplication.style().drawControl(QStyle.CE_PushButton, button, painter) painter.restore() def editorEvent(self, event, model, option, index): if self.btnRect.contains(event.pos()): if event.type() == QEvent.MouseButtonPress: model.setData(index, QStyle.State_Sunken, Qt.UserRole + 2) elif event.type() == QEvent.MouseButtonRelease: model.setData(index, QStyle.State_Raised, Qt.UserRole + 2) self.do_something() else: model.setData(index, QStyle.State_Enabled | QStyle.State_HasFocus, Qt.UserRole + 2) else: model.setData(index, QStyle.State_Enabled, Qt.UserRole + 2) return super(MyDelegate, self).editorEvent(event, model, option, index) def do_something(self): print("button clicked") if __name__ == "__main__": app = QApplication(sys.argv) model = QStandardItemModel() for i in range(10): item = QStandardItem() item.setData(f"Item {i}", Qt.DisplayRole) item.setData("Item description, can be very long", Qt.UserRole + 1) item.setData(QStyle.State_Enabled, Qt.UserRole + 2) model.appendRow(item) listView = QListView() listView.setMouseTracking(True) listView.setItemDelegate(MyDelegate()) listView.setModel(model) listView.show() app.exec()