Reputation: 4777
Is there a way to get 2 different fill colors for a single QGraphicsPathItem
object?
For example:
# 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)
Right now it's just using the last brush color for the rectangle and text. I'd like to color them differently though, but still as the same QGraphicsPathItem
. Or better yet, a way to give the text a background so it's easier to select.
Update
Here's an example. I want a white text with a red background, but I only get the last used brush color.
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()
Upvotes: 0
Views: 1594
Reputation: 3477
The problem is that your first self.setPath
and self.setBrush
calls are just over-ridden by the second ones. These properties of the QGraphicsPathItem
are not used until you get to the paint event. So the first settings do nothing and the values left in these properties after the initialisation are the ones used to paint the item.
It's not too difficult to do what you want but you have quite a lot of options, and you need to choose based on other aspects of your design.
The simplest option would be to just create a QGraphicsRectItem
and then give it a QGraphicsSimpleTextItem
child. This is particularly simple in that you wouldn't even need to create a subclass of your own: simply create the instances, set their Paths and Brushes and use them directly. I strongly recommend this approach if it does what you neeed.
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)
Another simple option would be just create the two items and then add them into a QGraphicsItemGroup
. This makes sense if you might want to separate the items or work with them separately.
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 )
If you need to create a class of your own for other reasons then you have quite a few options. The most general will be to subclass QGraphicsItem
. You can create a MyTextItem
with, for example, two Paths and two Brushes, and use them both when you paint the Item. You will have to implement boundingRect
and paint
but in this case both will be quite easy. This is probably a good way to go if you foresee adding lots of additional functionality to the item.
Other options would be to subclass QRectItem
and add a text path to it. Again you will need to re-implement paint
, but that might be all that was needed. Or you could subclass QSimpleTextItem
and add a rect to it.
Upvotes: 1