PyQt5 QTableView中选择的细胞的背景与代表

问题描述 投票:0回答:1

我有其使用QTableView中/ QAbstractTableModel组合的应用程序。该视图中,我定义,其显示在表视图中的一列的图像(的QPixmap,从图像文件加载)的委托。

基本上,问题是,当选择在与代表所述列的单元格,有时背景显示,有时它没有。

以下是我已经通过实验发现,到目前为止,我不能让它多大意义:

我有这个相对短的测试程序:

from PyQt5 import QtCore, QtWidgets, QtGui
import sys


# ------------------------------------------------------------------------------
class TableModel(QtCore.QAbstractTableModel):

    def __init__(self, data = [[]], headers = None, parent = None):
        QtCore.QAbstractTableModel.__init__(self, parent)
        self.__data = data

    def rowCount(self, parent):
        return len(self.__data)

    def columnCount(self, parent):
        return len(self.__data[0])

    def data(self, index, role):
        row = index.row()
        column = index.column()
        if role == QtCore.Qt.DisplayRole:
            value = self.__data[row][column]
            return value

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


# ------------------------------------------------------------------------------
class Delegate(QtWidgets.QStyledItemDelegate):

    def paint(self, painter, option, index):        

        if (index.column() == 0):
            image = QtGui.QImage('open.png')
            pixmap = QtGui.QPixmap.fromImage(image)

            x = option.rect.center().x() - pixmap.rect().width() / 2
            y = option.rect.center().y() - pixmap.rect().height() / 2
            painter.drawPixmap(x, y, pixmap)


# ------------------------------------------------------------------------------
if __name__ == '__main__':

    app = QtWidgets.QApplication(sys.argv)
    app.setStyle('fusion')

    tableView = QtWidgets.QTableView()
    tableView.setItemDelegateForColumn(0, Delegate())
    tableView.resize(550, 160)
    tableView.show()

    rowCount = 3
    columnCount = 4
    data = [
        [i for i in range(columnCount)]
        for j in range(rowCount)
    ]

    model = TableModel(data)
    tableView.setModel(model)

    sys.exit(app.exec_())

当我指定app.setStyle('fusion') __main__,我得到我所期待的:当选择与代表该列的单元格,单元格的背景是蓝色和形象出现在它的面前:

fusion

但是,如果我改变app.setStyle('windows'),即使在总体上采用选定单元格相同的蓝色背景,当我移动到第一列的单元格,背景消失:

windows

(你不能明显地看出来,但在同一小区被选作第一个例子)。

这只是一段测试代码,我不完全理解。

在实际应用中我写的,我使用Qt Designer创建的用户界面。尽管我指定app.setStyle('fusion'),表中有完全不同的造型,具有不同的外观,以所选择的单元格的背景:

Qt Designer table

我不能为我的生活出在那里拿起不同的风格。它必须以某种方式来自Qt设计,但我已经看过了.py文件Qt设计造成的,我不能找到它。

这种风格(无论它来自)似乎从相同的问题windows风格受苦。在上面的图像,存在在使用中没有代表。在第2行/列2中的单元被选择,并且背景显示。

但是,如果我添加一个代表显示在第2栏第一个的QPixmap,则背景不当选择了单元显示:

Qt Designer table with Delegate

(它的选择;需要我的话)。

我想也许这是事实,一旦你使用委托来显示图像,你可以不再获得所选单元格的背景。但是,你明明可以。它的工作原理在一种情况下,只是没有其他人。

如果任何人都可以在此予以澄清,我将不胜感激。 (我知道这是很长,感谢您与我坚持)。

pyqt5 qtableview
1个回答
0
投票

我一直在摆弄周围这个问题更多,我学到了我原来的问题一些事情。现在回想起来,我认为这是不明确的,因为它可能是(或者也许我只是明白这一切会好一点)。

对于初学者来说,我根本就不应该被称为细胞被“选中”。事实上,我甚至不具有任何在视图中的细胞的设置Qt.ItemIsSelectable标志。我真的一直在努力做的是控制细胞的背景时,其活跃(由于缺乏一个更好的词) - 这意味着它是在光标当前所在的单元格。

这可以通过在代表覆盖initStyleOption()来完成。我的原始测试代码被修改为如下所示:

from PyQt5 import QtCore, QtWidgets, QtGui
import sys


# ------------------------------------------------------------------------------
class TableModel(QtCore.QAbstractTableModel):

    def __init__(self, data = [[]], headers = None, parent = None):
        QtCore.QAbstractTableModel.__init__(self, parent)
        self.__data = data

    def rowCount(self, parent):
        return len(self.__data)

    def columnCount(self, parent):
        return len(self.__data[0])

    def data(self, index, role):
        row = index.row()
        column = index.column()
        if role == QtCore.Qt.DisplayRole:
            value = self.__data[row][column]
            return value
        if role == QtCore.Qt.BackgroundRole:
            return QtGui.QBrush(QtGui.QColor(255, 255, 255))

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


# ------------------------------------------------------------------------------
class TableView(QtWidgets.QTableView):

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


# ------------------------------------------------------------------------------
class Delegate(QtWidgets.QStyledItemDelegate):

    # <Modification>
    def initStyleOption(self, option, index):
        super().initStyleOption(option, index)
        if (
            index.row() == tableView.currentIndex().row() and
            index.column() == tableView.currentIndex().column()
        ):
            option.backgroundBrush = QtGui.QBrush(QtGui.QColor(232, 244, 252))

    def paint(self, painter, option, index):        
        if (index.column() == 0):

            # <Modification>
            if (
                index.row() == tableView.currentIndex().row() and
                index.column() == tableView.currentIndex().column()
            ):
                self.initStyleOption(option, index)
                painter.setPen(QtCore.Qt.NoPen)
                painter.setBrush(option.backgroundBrush)
                painter.drawRect(option.rect)

            image = QtGui.QImage('open.png')
            pixmap = QtGui.QPixmap.fromImage(image)
            x = option.rect.center().x() - pixmap.rect().width() / 2
            y = option.rect.center().y() - pixmap.rect().height() / 2
            painter.drawPixmap(x, y, pixmap)

        else:
            super().paint(painter, option, index)



# ------------------------------------------------------------------------------
if __name__ == '__main__':

    app = QtWidgets.QApplication(sys.argv)
    app.setStyle('fusion')

    tableView = TableView()
    tableView.resize(550, 160)
    tableView.setItemDelegate(Delegate())
    tableView.show()

    rowCount = 3
    columnCount = 4
    data = [
        [i for i in range(columnCount)]
        for j in range(rowCount)
    ]

    model = TableModel(data)
    tableView.setModel(model)

    sys.exit(app.exec_())

initStyleOption()设置了一个单元中的背景刷时,它是活动的(当前)。但正如我之前哀叹,这并不在第一列,这与一个显示像素图的自定义paint()方法的委托进行。所以paint()也必须承担时,他们主动设置背景在列单元格的责任。它使用backgroundBrush设置相同initStyleOption()

其结果是非常接近我正在拍摄的。在唯一美中不足的是,仍然有很明显的附加造型事情,影响中,除了那些与自定义委托1列视图中的所有细胞。因此,他们不看很一模一样活跃的时候:

Column with Delegate Column without Delegate

(这是微妙的,但有一个比特的梯度到该单元的第2列中的背景,这是在第1列的缺席)。

现在我知道,有风格的“工厂”应用于一个小部件宽的风格。由于我使用的融合,这显然是在额外造型的来源。

所以,现在我的问题是 - 那是哪里的造型定义的,我有过任何控制?如果我能看到它,我可以让我的自定义背景风格相匹配。更妙的是,如果我可以修改它,我可以让我的相匹配。

© www.soinside.com 2019 - 2024. All rights reserved.