0

问题:

我可以将 QPushButton 添加到 QStyledItemDelegate 就好了。我在委托的 editorEvent 方法中伪造按钮按下,所以当你按下它时,就会发生动作。我无法让我的 QPushButton 的样式表正常工作 - 它只读取第一个背景参数,即“红色”并且在鼠标悬停或按下时不会改变

目前尚不清楚我应该如何设置按钮单击和悬停检测以使按钮像代理上的真实按钮一样。我需要设置一个事件过滤器吗?我应该在视图级别执行此操作吗?我是否在委托的绘制方法中执行此操作?一切的结合?

目标:

  • 将鼠标悬停在列表时间上将显示按钮按钮的图标。
  • 将鼠标悬停在按钮上将更改其背景颜色。
  • 鼠标点击按钮会使背景颜色变暗以显示发生了点击。
  • 如果可能的话,我想在样式表中设置这些参数,但我也不介意在绘制函数中完成所有这些。什么都行!

当前实施

按钮小部件是红色的,带有文件夹图标。这些项目在选择和悬停时正确改变颜色(我想保留它),但项目的按钮根本没有改变。

在此处输入图像描述

谢谢!

到目前为止,这是我汇总的内容:

import sys

from PySide2 import QtCore
from PySide2 import QtGui
from PySide2 import QtWidgets


class DelegateButton(QtWidgets.QPushButton):
    def __init__(self, parent=None):
        super(DelegateButton, self).__init__(parent)

        # self.setLayout(QHBoxLayout())
        size = 50
        self.setFixedSize(size, size)
        self.setIcon(self.style().standardIcon(QtWidgets.QStyle.SP_DialogOpenButton))
        self.setStyleSheet("""
            QPushButton{
                background:red;
                height: 30px;
                font: 12px "Roboto Thin";
                border-radius: 25
            }
            QPushButton:hover{
                background: green;
            }
            QPushButton:hover:pressed{
                background: blue;
            }
            QPushButton:pressed{
                background:  yellow;
            }
            """)


class MainWindow(QtWidgets.QWidget):
    def __init__(self):
        super(MainWindow, self).__init__()

        self.resize(300, 300)

        # Model/View
        entries = ['one', 'two', 'three']
        model = QtGui.QStandardItemModel()
        delegate = ListItemDelegate()
        self.listView = QtWidgets.QListView(self)
        self.listView.setModel(model)
        self.listView.setItemDelegate(delegate)

        for i in entries:
            item = QtGui.QStandardItem(i)
            model.appendRow(item)

        # Layout
        main_layout = QtWidgets.QVBoxLayout()
        main_layout.addWidget(self.listView)
        self.setLayout(main_layout)

        # Connections
        delegate.delegateButtonPressed.connect(self.on_delegate_button_pressed)

    def on_delegate_button_pressed(self, index):

        print('"{}" delegate button pressed'.format(index.data(QtCore.Qt.DisplayRole)))


class ListItemDelegate(QtWidgets.QStyledItemDelegate):
    delegateButtonPressed = QtCore.Signal(QtCore.QModelIndex)

    def __init__(self):
        super(ListItemDelegate, self).__init__()

        self.button = DelegateButton()

    def sizeHint(self, option, index):
        size = super(ListItemDelegate, self).sizeHint(option, index)
        size.setHeight(50)
        return size

    def editorEvent(self, event, model, option, index):

        # Launch app when launch button clicked
        if event.type() == QtCore.QEvent.MouseButtonRelease:
            click_pos = event.pos()
            rect_button = self.rect_button

            if rect_button.contains(click_pos):
                self.delegateButtonPressed.emit(index)
                return True
            else:
                return False
        else:
            return False

    def paint(self, painter, option, index):
        spacing = 10
        icon_size = 40

        # Item BG #########################################
        painter.save()
        if option.state & QtWidgets.QStyle.State_Selected:
            painter.setBrush(QtGui.QColor('orange'))
        elif option.state & QtWidgets.QStyle.State_MouseOver:
            painter.setBrush(QtGui.QColor('black'))
        else:
            painter.setBrush(QtGui.QColor('purple'))
        painter.drawRect(option.rect)
        painter.restore()

        # Item Text ########################################
        rect_text = option.rect
        QtWidgets.QApplication.style().drawItemText(painter, rect_text, QtCore.Qt.AlignVCenter | QtCore.Qt.AlignLeft, QtWidgets.QApplication.palette(), True, index.data(QtCore.Qt.DisplayRole))

        # Custom Button ######################################
        self.rect_button = QtCore.QRect(
            option.rect.right() - icon_size - spacing,
            option.rect.bottom() - int(option.rect.height() / 2) - int(icon_size / 2),
            icon_size,
            icon_size
        )

        option = QtWidgets.QStyleOptionButton()
        option.initFrom(self.button)
        option.rect = self.rect_button
        # Button interactive logic
        if self.button.isDown():
            option.state = QtWidgets.QStyle.State_Sunken
        else:
            pass
        if self.button.isDefault():
            option.features = option.features or QtWidgets.QStyleOptionButton.DefaultButton
        option.icon = self.button.icon()
        option.iconSize = QtCore.QSize(30, 30)

        painter.save()
        self.button.style().drawControl(QtWidgets.QStyle.CE_PushButton, option, painter, self.button)
        painter.restore()


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())
4

1 回答 1

0

试试: https ://doc.qt.io/qt-4.8/qstyle.html#StateFlag-enum

import sys
import PySide.QtCore as core
import PySide.QtGui as gui

QPushButton#pushButton {
    background-color: yellow;
}

QPushButton#pushButton:hover {
    background-color: rgb(224, 255, 0);
}

QPushButton#pushButton:pressed {
    background-color: rgb(224, 0, 0);     
}

您的自定义 QStyledItemDelegate 捕获鼠标事件,因此它不会传递给 QListView。所以在 QStyledItemDelegate.editor(Event) 中只需要添加一个。

if event.type() == core.QEvent.MouseButtonPress:
    return False

现在可以使用 option.state 和 gui.QStyle.State_Selected 在paint() 方法中识别选择。

if __name__ == '__main__':


    app = gui.QApplication(sys.argv)
    app.setStyleSheet('QListView::item:hover {background: none;}')
    mw = gui.QMainWindow()

    model = MyListModel()
    view = gui.QListView()
    view.setItemDelegate(MyListDelegate(parent=view))
    view.setSpacing(5)
    view.setModel(model)

    mw.setCentralWidget(view)
    mw.show()

    sys.exit(app.exec_())

class MyListDelegate(gui.QStyledItemDelegate):

    w = 300
    imSize = 90
    pad = 5
    h = imSize + 2*pad
    sepX = 10

    def __init__(self, parent=None):
        super(MyListDelegate, self).__init__(parent)

    def paint(self, painter, option, index):
        mouseOver = option.state in [73985, 73729]

        if option.state & QStyle.State_MouseOver::
            painter.fillRect(option.rect, painter.brush())

        pen = painter.pen()
        painter.save()

        x,y = (option.rect.x(), option.rect.y())
        dataRef = index.data()
        pixmap = dataRef.pixmap()
        upperLabel = dataRef.upperLabel()
        lowerLabel = dataRef.lowerLabel()

        if mouseOver:
            newPen = gui.QPen(core.Qt.green, 1, core.Qt.SolidLine)
            painter.setPen(newPen)
        else:
            painter.setPen(pen)
        painter.drawRect(x, y, self.w, self.h)
        painter.setPen(pen)

        x += self.pad
        y += self.pad

        painter.drawPixmap(x, y, pixmap)

        font = painter.font()
        textHeight  = gui.QFontMetrics(font).height()

        sX = self.imSize + self.sepX
        sY = textHeight/2

        font.setBold(True)
        painter.setFont(font)
        painter.drawText(x+sX, y-sY, 
                         self.w-self.imSize-self.sepX, self.imSize,
                         core.Qt.AlignVCenter,
                         upperLabel)
        font.setBold(False)
        font.setItalic(True)
        painter.setFont(font)
        painter.drawText(x+sX, y+sY,
                         self.w-self.imSize-self.sepX, self.imSize,
                         core.Qt.AlignVCenter,
                         lowerLabel)

        painter.restore()

    def sizeHint(self, option, index):
        return core.QSize(self.w, self.imSize+2*self.pad)

    def editorEvent(self, event, model, option, index):
        if event.type() == core.QEvent.MouseButtonRelease:
            print 'Clicked on Item', index.row()
        if event.type() == core.QEvent.MouseButtonDblClick:
            print 'Double-Clicked on Item', index.row()
        return True


window.button->setAutoFillBackground(false);
window.button->setAutoFillBackground(true);
window.button->setPalette(*palette_red);

设置 CSS 的另一种解决方案:

import sys
from PyQt5 import Qt as qt 

class TopLabelNewProject(qt.QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)

        layout = qt.QHBoxLayout(self)
        layout.setContentsMargins(40, 0, 32, 0)
        self.setLayout(layout)
        self.setFixedHeight(80)

        self.label = qt.QLabel("Dashboard")

        layout.addWidget(self.label, alignment=qt.Qt.AlignLeft)

#        self.newProjectButton = Buttons.DefaultButton("New project", self)
        self.newProjectButton = qt.QPushButton("New project", self)
        layout.addWidget(self.newProjectButton, alignment=qt.Qt.AlignRight)


style = '''
QWidget {
    background-color: white;
} 

QLabel {
    font: medium Ubuntu;
    font-size: 20px;
    color: #006325;     
}        

QPushButton {
    background-color: #006325;
    color: white;

    min-width:  70px;
    max-width:  70px;
    min-height: 70px;
    max-height: 70px;

    border-radius: 35px;        
    border-width: 1px;
    border-color: #ae32a0;
    border-style: solid;
}
QPushButton:hover {
    background-color: #328930;
}
QPushButton:pressed {
    background-color: #80c342;
}    

'''


if __name__ == '__main__':
    app = qt.QApplication(sys.argv)

    app.setStyleSheet(style)

    ex = TopLabelNewProject()
    ex.show()
    sys.exit(app.exec_())  
于 2020-04-25T20:33:54.913 回答