2015-09-02 9 views
0

Есть ли способ получить 2 разных цвета заливки для одного объекта QGraphicsPathItem?QGraphicsPathItem разные цвета

Например:

# Try to get a white text onto a grey rectangle 
    itemPath = QtGui.QPainterPath() 
    itemPath.setFillRule(QtCore.Qt.WindingFill) 

    self.setBrush(QtGui.QColor(100, 100, 100)) 
    itemPath.addRect(-10, -60, 150, 70) 
    itemFont = QtGui.QFont() 
    itemFont.setPointSize(50) 
    self.setBrush(QtGui.QColor(255, 255, 255)) 
    itemPath.addText(0, 0, itemFont, txt) 

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

Update

Вот пример. Я хочу белый текст с красным фоном, но я получаю только последний использованный цвет кисти.

from PySide import QtGui, QtCore 

class TextItem(QtGui.QGraphicsPathItem): 
    def __init__(self): 
     super(TextItem, self).__init__() 

     itemPath = QtGui.QPainterPath() 
     itemPath.setFillRule(QtCore.Qt.WindingFill) 

     # Create rectangle with red color 
     self.setBrush(QtGui.QColor(255, 0, 0)) 
     itemPath.addRect(-10, -50, 130, 60) 
     self.setPath(itemPath) 

     # Create text with white color 
     itemFont = QtGui.QFont() 
     itemFont.setPointSize(40) 
     self.setBrush(QtGui.QColor(255, 255, 255)) 
     itemPath.addText(0, 0, itemFont, 'Test!') 
     self.setPath(itemPath) 

     self.moveBy(100, 100) 

class Window(QtGui.QWidget): 
    def __init__(self): 
     super(Window, self).__init__() 

     self.resize(500, 500) 
     self.view = QtGui.QGraphicsView(self) 
     self.view.setScene(QtGui.QGraphicsScene(self)) 
     self.view.setSceneRect(0, 0, 500, 500) 
     self.view.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) 
     self.view.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)   

     mainLayout = QtGui.QVBoxLayout() 
     mainLayout.addWidget(self.view) 
     self.setLayout(mainLayout) 

     newItem = TextItem() 
     self.view.scene().addItem(newItem) 

    def run(self): 
     self.show() 

win = Window() 
win.show() 
+0

Было бы полезно предоставить пример минимального запуска: поскольку для него требуется QGraphicsView и т. Д., И поэтому нет тривиальной настройки. Но можно сделать его достаточно маленьким, чтобы публиковать здесь. – strubbly

ответ

1

Проблема заключается в том, что ваши первые self.setPath и self.setBrush звонки только подавляться вторыми. Эти свойства QGraphicsPathItem не используются до тех пор, пока вы не попадете на событие рисования. Таким образом, первые настройки ничего не делают, и значения, оставшиеся в этих свойствах после инициализации, являются теми, которые были использованы для рисования элемента.

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

Простейшим вариантом было бы просто создать QGraphicsRectItem, а затем дать ему QGraphicsSimpleTextItem ребенка. Это особенно просто, потому что вам даже не нужно создавать собственный подкласс: просто создайте экземпляры, установите их «Контуры и кисти» и используйте их напрямую. Я настоятельно рекомендую этот подход, если он делает то, что вы делаете.

rectItem = QtGui.QGraphicsRectItem(0, 0, 130, 60) 
    rectItem.setBrush(QtGui.QColor(255, 0, 0)) 

    textItem = QtGui.QGraphicsSimpleTextItem("Test!",rectItem) 

    itemFont = QtGui.QFont() 
    itemFont.setPointSize(40) 
    textItem.setBrush(QtGui.QColor(200, 200, 200)) 
    textItem.setFont(itemFont) 
    textItem.setPos(10,0) 

    self.view.scene().addItem(rectItem) 

    rectItem.moveBy(100,100) 

Другой простой вариант будет просто создать два пункта, а затем добавить их в QGraphicsItemGroup. Это имеет смысл, если вы захотите разделить предметы или работать с ними отдельно.

rectItem = QtGui.QGraphicsRectItem(0, 0, 130, 60) 
    rectItem.setBrush(QtGui.QColor(255, 0, 0)) 
    self.view.scene().addItem(rectItem) 
    textItem = QtGui.QGraphicsSimpleTextItem("Test!") 
    itemFont = QtGui.QFont() 
    itemFont.setPointSize(40) 
    textItem.setBrush(QtGui.QColor(200, 200, 200)) 
    textItem.setFont(itemFont) 
    textItem.setPos(10,0) 
    self.view.scene().addItem(textItem) 
    group = QtGui.QGraphicsItemGroup() 
    group.addToGroup(rectItem) 
    group.addToGroup(textItem) 
    group.moveBy(100,100) 
    self.view.scene().addItem(group) 

Если вам нужно создать собственный класс по другим причинам, то у вас есть несколько вариантов. Наиболее общим будет подкласс QGraphicsItem. Вы можете создать MyTextItem, например, с двумя контурами и двумя кистями и использовать их при рисовании элемента. Вам нужно будет реализовать boundingRect и paint, но в этом случае оба будут довольно простыми. Это, вероятно, хороший способ пойти, если вы предвидите добавление большого количества дополнительных функций к элементу.

Другие варианты были бы в подклассе QRectItem и добавили бы к нему текстовый путь. Опять вам нужно будет переустановить paint, но это может быть все, что было необходимо. Или вы можете подкласса QSimpleTextItem и добавить к нему прямоугольник.

+0

Я надеялся придерживаться 'QGraphicsPathItem', чтобы держать все в одном классе, но это выглядит хорошо для меня. Спасибо за отличное объяснение! –

+0

QGraphicsPathItem делает свой рисунок на основе своего собственного пути и кисти. Таким образом, единственный способ сделать это - переопределить paint и boundingRect. Но тогда и другие другие методы будут довольно странными, например setPath. содержит, и так далее. Это просто не имеет смысла. – strubbly