在 PyQt5 中创建自定义对角线 QBrush 平铺图案?

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

所以,一开始我想使用渐变背景来强调 QTableView 中的某些单元格/项目,但正如在 Stretchable QLinearGradient as BackgroundRole for resizeable QTableView cells in PyQt5? 中可以看到的那样,我无法完全理解工作。

然后我想也许我可以以某种方式使用 CSS 来定义渐变背景和 Qt 属性来控制它显示在哪些项目上,但问题是在 QTableView 中,单元格/项目是 QStyledItemDelegate,如 https 中所述: //forum.qt.io/topic/84304/qtreewidget-如何实现样式表的自定义属性 :

动态属性只能应用于QWidgets!

是否可以仅将属性应用于所选项目?

不,不是直接。除非您继承自定义 QStyledItemDelegate 并根据您的小部件的属性初始化绘制索引的 StyleOption。

然后看https://doc.qt.io/qt-5/qbrush.html我看到QBrush可以选择不同的图案,事实上我喜欢Qt.BDiagPattern对角线图案/阴影线- 但线条太细了,不适合我的口味。

所以,我想自定义 BDiagPattern 的线条粗细,我发现 我可以自定义自己的笔刷样式吗? 其中有一个示例如何绘制 QPixmap 并将其用作重复/平铺的纹理图案,但是,它不演示如何做对角线。

所以,我想出了这个例子:

import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import (Qt, QPointF, QEvent)
from PyQt5.QtGui import (QColor, QGradient, QLinearGradient, QBrush, QTransform)
from PyQt5.QtWidgets import QApplication
# starting point from https://www.pythonguis.com/tutorials/qtableview-modelviews-numpy-pandas/

class TableModel(QtCore.QAbstractTableModel):
    def __init__(self, data, parent):
        super(TableModel, self).__init__()
        self._data = data
        self.parent = parent
        self.bg_col1 = QColor("#A3A3FF")
        self.bg_col2 = QColor("#FFFFA3")
    #
    def create_texture(self): # https://stackoverflow.com/q/62799632
        pixmap = QtGui.QPixmap(QtCore.QSize(16, 16))
        pixmap.fill(QColor(0,0,0,0)) # without .fill, bg is black; can use transparent though
        painter = QtGui.QPainter()
        painter.begin(pixmap)
        painter.setBrush(QtGui.QBrush(QtGui.QColor("blue")))
        painter.setPen(QtGui.QPen(self.bg_col1, 5, Qt.SolidLine))
        painter.drawLine(pixmap.rect().bottomLeft(), pixmap.rect().topRight())
        painter.end()
        return pixmap
    def data(self, index, role):
        if role == Qt.DisplayRole:
            # See below for the nested-list data structure.
            # .row() indexes into the outer list,
            # .column() indexes into the sub-list
            return self._data[index.row()][index.column()]
        if role == Qt.BackgroundRole:
            if index.column() == 2:
                print( f"{self.parent.table.itemDelegate(index)=}" )
                brush = QBrush(self.create_texture())
                brush.setTransform(QTransform(QTransform.fromScale(4, 4))) # zoom / scale - https://stackoverflow.com/q/41538932; scales pixels themselves
                return brush
    #
    def rowCount(self, index):
        # The length of the outer list.
        return len(self._data)
    #
    def columnCount(self, index):
        # The following takes the first sub-list, and returns
        # the length (only works if all rows are an equal length)
        return len(self._data[0])

class MainWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        self.table = QtWidgets.QTableView()
        data = [
          [4, 9, 2, 2],
          [1, 0, 0, 0],
          [3, 5, 0, 0],
          [3, 3, 2, 2],
          [7, 8, 9, 9],
        ]
        self.model = TableModel(data, self)
        self.table.setModel(self.model)
        self.setCentralWidget(self.table)

app=QtWidgets.QApplication(sys.argv)
window=MainWindow()
window.show()
app.exec_()

...但是,正如您从输出屏幕截图中看到的:

table with custom brush background

...对角线并没有完全“流动”到彼此 - 换句话说,图案不会平铺。

那么,如何使用 QBrush 和 QPixmap 绘制一个可以很好地平铺并具有自定义线条粗细的对角线图案?

python pyqt5 qt5
1个回答
0
投票

只是想记录一下这一点,因为花了几个小时的挖掘才得到我认为有效的东西。嗯,这里有两件事:

  • 首先,从左下角到右上角的对角线需要偏移,这样它就可以沿着对角线很好地“居中”
  • 但是为了使图案作为一个整体很好地平铺/重复,我们还必须在像素图的左上角和右下角绘制类似的对角“线”(或线部分)

这是更正后的代码:

import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import (Qt, QPointF, QEvent)
from PyQt5.QtGui import (QColor, QGradient, QLinearGradient, QBrush, QTransform)
from PyQt5.QtWidgets import QApplication
# starting point from https://www.pythonguis.com/tutorials/qtableview-modelviews-numpy-pandas/

class TableModel(QtCore.QAbstractTableModel):
    def __init__(self, data, parent):
        super(TableModel, self).__init__()
        self._data = data
        self.parent = parent
        self.bg_col1 = QColor("#A3A3FF")
        self.bg_col2 = QColor("#FFFFA3")
    #
    def create_texture(self): # https://stackoverflow.com/q/62799632
        pixmap = QtGui.QPixmap(QtCore.QSize(16, 16))
        pixmap.fill(QColor(0,0,0,0)) # without .fill, bg is black; can use transparent though
        painter = QtGui.QPainter()
        painter.begin(pixmap)
        painter.setBrush(QtGui.QBrush(QtGui.QColor("blue")))
        painter.setPen(QtGui.QPen(self.bg_col1, 5, Qt.SolidLine))
        painter.drawLine(pixmap.rect().bottomLeft()+QPointF(1,0), pixmap.rect().topRight()+QPointF(1,0))
        painter.drawLine(pixmap.rect().bottomRight()+QPointF(-1+2,1), pixmap.rect().bottomRight()+QPointF(1+2,-1))
        painter.drawLine(pixmap.rect().topLeft()+QPointF(-1+0,1), pixmap.rect().topLeft()+QPointF(1+0,-1))
        painter.end()
        return pixmap
    def data(self, index, role):
        if role == Qt.DisplayRole:
            # See below for the nested-list data structure.
            # .row() indexes into the outer list,
            # .column() indexes into the sub-list
            return self._data[index.row()][index.column()]
        if role == Qt.BackgroundRole:
            if index.column() == 2:
                brush = QBrush(self.create_texture())
                brush.setTransform(QTransform(QTransform.fromScale(4, 4))) # zoom / scale - https://stackoverflow.com/q/41538932; scales pixels themselves
                return brush
    #
    def rowCount(self, index):
        # The length of the outer list.
        return len(self._data)
    #
    def columnCount(self, index):
        # The following takes the first sub-list, and returns
        # the length (only works if all rows are an equal length)
        return len(self._data[0])

class MainWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        self.table = QtWidgets.QTableView()
        data = [
          [4, 9, 2, 2],
          [1, 0, 0, 0],
          [3, 5, 0, 0],
          [3, 3, 2, 2],
          [7, 8, 9, 9],
        ]
        self.model = TableModel(data, self)
        self.table.setModel(self.model)
        self.setCentralWidget(self.table)

app=QtWidgets.QApplication(sys.argv)
window=MainWindow()
window.show()
app.exec_()

我有点暴力地查找了上面代码中的偏移量,但我发现最终结果还不错:

table with tiled hatch pattern screenshot

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