无法更改自定义QListView行的突出显示文本颜色

时间:2015-04-06 18:07:23

标签: qt pyside osx-yosemite qlistview

由于某些奇怪的原因,无法覆盖QListView中突出显示的文字颜色。它运行正常(突出显示的文本颜色自动更改为白色),直到我定义自己的小部件来表示一行。

现在我可以更改所选行的背景颜色和其他一些视觉方面,但文本颜色始终保持默认黑色。

已经尝试使用QSSQPalettedata() / Qt.ForegroundRole完成所有操作 - 没有技巧有帮助。

这是一个简化的代码,仍然存在OS X上的问题。很遗憾,我没有机会在WindowsGNU/Linux上进行测试。

from PySide.QtCore import *
from PySide.QtGui import *
import sys

view = None
mapp = {}

style = '''
QListView {
    show-decoration-selected: 1;
    selection-color: white;
    selection-background-color: #0068d9;
}

QListView::item:selected:active:hover{
    background-color:red; color: white;
}
QListView::item:selected:active:!hover{
    background-color: #0068d9; color: white;
}
QListView::item:selected:!active{
    background-color:yellow; color: white;
}
QListView::item:!selected:hover{
    background-color:green; color: white;
}
'''

class SimpleListModel(QAbstractListModel):

    def __init__(self, mlist):
        QAbstractListModel.__init__(self)
        self._items = mlist

    def rowCount(self, parent = QModelIndex()):
        return len(self._items)

    def index(self, row, column, parent=QModelIndex()):
        node = self._items[row]

        if not(str(row) in mapp):
            index = self.createIndex(row, column)
            widget = QLabel(node)
            view.setIndexWidget(index, widget)
            mapp[str(row)] = index
            return index

        return mapp[str(row)]

    def data(self, index, role = Qt.DisplayRole):
        return None

    def flags(self, index):
        return Qt.ItemIsSelectable | Qt.ItemIsEnabled    

class MyMainWindow(QWidget):
    def __init__(self):
        global view
        QWidget.__init__(self, None)

        self._model = SimpleListModel(["test", "tes1t", "t3est", "t5est", "t3est"])

        vbox = QVBoxLayout()
        view = QListView()
        view.setModel(self._model)
        vbox.addWidget(view)
        self.setLayout(vbox)

        view.setStyleSheet(style)

        first = self._model.index(0, 0)
        view.setCurrentIndex(first)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    w = MyMainWindow()
    w.show()
    w.raise_()
    app.exec_()
    sys.exit()

2 个答案:

答案 0 :(得分:3)

不是最干净或最好的解决方案,但这是经过一些调整后我带来的。

结果:

enter image description here

蓝色项目是选定的项目。绿色项目是悬停的项目。

代码:

from PySide.QtCore import *
from PySide.QtGui import *
import sys

view = None
mapp = {}

style = '''
QListView {
    show-decoration-selected: 1;
    selection-color: white;
    selection-background-color: #0068d9;
}

QListView::item:selected:active:hover{
    background-color:red; color: white;
}
QListView::item:selected:active:!hover{
    background-color: #0068d9; color: white;
}
QListView::item:selected:!active{
    background-color:yellow; color: white;
}
QListView::item:!selected:hover{
    background-color:green; color: white;
}
'''

class SimpleListModel(QAbstractListModel):

    def __init__(self, mlist):
        QAbstractListModel.__init__(self)
        self._items = mlist

    def rowCount(self, parent = QModelIndex()):
        return len(self._items)

    def index(self, row, column, parent=QModelIndex()):
        node = self._items[row]

        if not(str(row) in mapp):
            index = self.createIndex(row, column)
            widget = QLabel(node)
            view.setIndexWidget(index, widget)

            mapp[str(row)] = index
            return index


        return mapp[str(row)]

    def data(self, index, role = Qt.DisplayRole):
        # The following code shouldn't be put in this function but i'm in a hurry right now...
        selectedIndexes = view.selectedIndexes()

        # Set all items to black
        for i in range(0, self.rowCount()):
            currentRowIndex = self.index(i, 0, QModelIndex())
            myWidget = view.indexWidget(currentRowIndex)
            myWidget.setStyleSheet("color: black")

        # Set selected items to white
        for i in selectedIndexes:
            myWidget = view.indexWidget(i)
            myWidget.setStyleSheet("color: white")

        return None

    def flags(self, index):
        return Qt.ItemIsSelectable | Qt.ItemIsEnabled    

class MyMainWindow(QWidget):
    def __init__(self):
        global view
        QWidget.__init__(self, None)

        self._model = SimpleListModel(["test", "tes1t", "t3est", "t5est", "t3est"])

        vbox = QVBoxLayout()
        view = QListView()
        view.setModel(self._model)
        vbox.addWidget(view)
        self.setLayout(vbox)

        view.setStyleSheet(style)

        first = self._model.index(0, 0)
        view.setCurrentIndex(first)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    w = MyMainWindow()
    w.show()
    w.raise_()
    app.exec_()
    sys.exit()

请告诉我是否有我无法正确理解的内容或代码不够清晰。

答案 1 :(得分:2)

第一: 您的代码以相同的方式处理GNU / Linux(Ubuntu 14.04 LTS,PyQt5)。

由于文字已写入indexWidget,因此必须为text-color设置QLabel的样式表。

由于QLabel不支持悬停伪状态,因此无法以与项目相同的方式完成。

为选定的indexWidgets设置样式表我使用了信号槽机制,对于悬停的indexWidgets,我使用了事件过滤器,

enter image description here

只修改了MyMainWindow类:

class MyMainWindow(QWidget):
    def __init__(self):
        global view
        QWidget.__init__(self, None)

        self._model = SimpleListModel(["test", "tes1t", "t3est", "t5est", "t3est"])

        vbox = QVBoxLayout()
        view = QListView()
        view.setModel(self._model)
        view.setMouseTracking(True)         # to catch mouseEvents
        view.installEventFilter(self)           # for events in ListView 
        vbox.addWidget(view)
        self.setLayout(vbox)

        view.setStyleSheet(style)

        first = self._model.index(0, 0)
        view.setCurrentIndex(first)
        view.clicked.connect(self.setIndexStyle)    # or any other signal

    def setIndexStyle(self, index):
        for i in range(0,view.model().rowCount()):
            style = 'color: black;'
            view.indexWidget(view.model().index(i,0)).setStyleSheet(style)
        for i in view.selectedIndexes():    # works for multiseletion too
            style = 'color: white;'
            view.indexWidget(i).setStyleSheet(style)

    def eventFilter(self,obj,event):
        if event.type() == QEvent.HoverMove and isinstance(obj,QListView):
            i =  view.indexAt(event.pos())      # index at mouse.pos()
            self.setIndexStyle(i)       # selected indexWidgets still have white text
            style = 'color: white;'
            try:                # if no item on mouse.pos()
                view.indexWidget(i).setStyleSheet(style)
            except AttributeError:      
                pass
            return False
        return QWidget.eventFilter(self,obj,event)