QBrush - масштабировать стандартный шаблон штриховки заливки?

В PyQt у меня есть QGraphicsScene, к которому я добавляю прямоугольник с одним из стандартных шаблонов заливки QBrush, в данном случае Qt.Dense7Pattern. Это проявляется, как и ожидалось, когда сцена отображается в исходном масштабе 1:1: "точки", составляющие Dense7Pattern, находятся на некотором расстоянии друг от друга, скажем, на 5 пикселей, чтобы выбрать число. Также предположим, что исходный прямоугольник имеет ширину 50 пикселей и высоту 50 пикселей.

Когда я увеличиваю эту сцену, скажем, в 2 раза, чтобы закрашенный прямоугольник теперь отображался размером 100x100 пикселей, я бы хотел, чтобы точки шаблона заливки по-прежнему отображались на расстоянии 5 пикселей, но Qt увеличивает статическую заливку шаблон, чтобы точки заливки отображались на расстоянии 10 пикселей.

Этот вопрос выглядит похоже. Очевидно, вы можете применить преобразование (включая масштаб) к шаблону заливки растрового изображения кисти, но, похоже, оно не применяется к "стандартному" шаблону заливки кисти. Я сделал подкласс и изменил преобразование кисти в методе рисования, но не повезло:

Весь подкласс (надеюсь, я сделал все, что нужно):

class customFillPolygonItem(QGraphicsPolygonItem):
    def paint(self,painter,option,widget=None):
        # from here, painter.setBrush affects shapes drawn directly in this function;
        #  self.setBrush affects the call to super().paint
        newBrush=QBrush(painter.brush())
        newBrush.setTransform(QTransform(painter.worldTransform().inverted()[0]))
        self.setBrush(newBrush)
        painter.setBrush(newBrush)
        painter.drawRect(QRectF(0,0,50,50)) # draw a reality-check object
        super(customFillPolygonItem,self).paint(painter,option,widget)

Тогда я просто делаю экземпляр этого сверху, используя

myItem=customFillPolygonItem(QPolygonF(...
myItem.setBrush(QBrush(Qt.Dense7Pattern))
myScene.addItem(myItem)

Итак, возможно ли применить масштаб к стандартному шаблону заливки кисти? Это было бы похоже на QBrush.setFlag(ItemIgnoresTransformations), но такой вещи не существует... вы можете установить этот флаг только для всего элемента (в данном случае прямоугольник).

Обходные пути могут включать в себя: - использовать ItemIgnoresTransformations и вручную преобразовывать фактические вершины прямоугольника по мере необходимости - сделать qpixmap из каждого стандартного шаблона заливки, затем использовать это растровое изображение в качестве кисти, в этом случае оно должно масштабироваться, как в вопросе, упомянутом выше

Но, конечно, было бы неплохо найти самое простое решение.

ОБНОВЛЕНИЕ: Schollii отвечает на вопрос, который был задан; его предложение рассмотреть альфа-значения также привело к решению более крупной проблемы, с которой я столкнулся в данном конкретном случае, - создать различные оттенки серого, изложенные в решении, которое я разместил, что на самом деле не является решением вопроса, который я задал. В любом случае, спасибо!

2 ответа

Решение

Я полагаю, что цель не достижима с помощью преобразования: шаблон заполнения генерируется в пространстве "сцены", а затем к нему применяется преобразование на основе масштабного коэффициента вида, очевидно, что это увеличит расстояние между точками, никакое преобразование не может предотвратить это., только другой рисунок шаблона.

Чтобы получить желаемый эффект, кисть должна иметь параметр для управления расстоянием между точками в координатах сцены; затем в методе paint() прямоугольника вы можете установить значение этого параметра на основе коэффициента масштабирования текущего представления (через аргумент style для метода paint()).

Поскольку я не думаю, что QBrush предоставляет такой параметр, вы должны нарисовать точки самостоятельно, используя расстояние, вычисленное, как описано в предыдущем параграфе. Сделано из Python, это может быть довольно медленно, если есть множество точек, но опять же PyQt5 имеет довольно впечатляющую производительность в целом.

Не то чтобы вам нужно было выбирать точку начала для точек (угол или центр были бы типичными вариантами выбора), и когда вы увеличиваете масштаб, вы увидите, что точки "скользят" к точке начала, так как больше точек "добавляются" к противоположные концы / края. Я думаю, что есть хороший шанс, что вам не понравится эффект, и, поскольку его не так просто реализовать, вы можете рассмотреть другой визуальный эффект, который не будет основан на точках, например градиент или альфа-значение. Могут быть и другие подходы, такие как setDashPattern() или рисование покоя в координатах вида, но, вероятно, не стоит затраченных усилий.

Спасибо Schollii за лидерство: установка значения альфа обеспечивает быстрое решение. Я пошел с черным, с различными значениями альфа, чтобы представить различные оттенки серого.

Если у вас есть n различных элементов, которые будут затенены по-разному, вы можете просто пройтись по списку элементов:

myItem.setBrush(QBrush(QColor(0,0,0,35*n)))

Где 35 выбирается в зависимости от того, что выглядит хорошо, так что вы можете получить желаемое количество уровней разделения серого от одного элемента к другому.

Это гораздо менее запутанно, чем создание подклассов и преобразований!

Другие вопросы по тегам