PDA

View Full Version : Not Scaling QBrush style fro qgraphics view item



dan
1st June 2008, 05:44
Hello,

I am attempting to draw shapes qgraphics framework. I would like the brush style not to change as the viewport is zoomed. (ie I want the stippling pattern not to change)

Does anybody have any suggestions on how I can achieve this?

-Dan

Brandybuck
1st June 2008, 17:48
You'll have to scale the brush down. The QStyleOptionGraphicsItem option passed in paint() will give you the transform being used, and you can set a matrix on a QBrush. Put the two together and you can scale the brush opposite of the item.


void Node::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *)
{
QBrush brush(Qt::red, Qt::DiagCrossPattern);
brush.setMatrix(option->matrix.inverted());
painter->setBrush(brush);

painter->drawEllipse(-50, -50, 100, 100);
}

dan
3rd June 2008, 03:35
Hi,

Thanks for you help but I cannot get your suggestion to work properly.
I overloaded the paint method for a class derived from qgraphicsitem as you showed but this does not work for me. It seems that the brush pattern matrix does not have any effect at all.

For example:


void Node::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *)
{
QBrush myBrush(Qt::red, Qt::DiagCrossPattern);
QMatrix myMatrix(99,0,99,0,0,0);
myBrush.setMatrix(myMatrix);
painter->setBrush(myBrush);
painter->drawEllipse(-50, -50, 100, 100);
}

produces a shape the looks the same as:


void Node::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *)
{
QBrush myBrush(Qt::red, Qt::DiagCrossPattern);
QMatrix myMatrix(1,0,1,0,0,0); //don't scale this time
myBrush.setMatrix(myMatrix);
painter->setBrush(myBrush);
painter->drawEllipse(-50, -50, 100, 100);
}

I am using QT4.3.
Am I doing anything wrong here?
I've tried both the Qt:DiagCrossPattern brush and also a custom brush made with a QImage.

Thanks!

Brandybuck
3rd June 2008, 17:08
Don't create your own matrix, use the one passed in option. That is the matrix the view uses. By taking the inverse matrix, you scale back down.

dan
3rd June 2008, 20:05
Hi,

Yes, I understand your solution but it does not work for me. I have traced the problem to the fact that brush transforms don't seem to work at all. That's what I was demonstrating in the previous code. Apparently this was a bug that was fixed in 4.3.1 (http://trolltech.com/developer/task-tracker/index_html?method=entry&id=129520).

I was using 4.3.4 and am now downloading 4.4.0. Has anybody else used a qBrush transform? What version were you using? Am I not doing something proper?

Thanks,
Dan

Brandybuck
4th June 2008, 20:31
I am using 4.3.5 and 4.4.0. Which is why I didn't see that bug.

navi1084
4th February 2010, 04:04
Is this bug is fixed??? I ma using QT 4.4 and facing same problem. Any idea to resolve this?

saics
1st October 2012, 20:04
You'll have to scale the brush down. The QStyleOptionGraphicsItem option passed in paint() will give you the transform being used, and you can set a matrix on a QBrush. Put the two together and you can scale the brush opposite of the item.


void Node::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *)
{
QBrush brush(Qt::red, Qt::DiagCrossPattern);
brush.setMatrix(option->matrix.inverted());
painter->setBrush(brush);

painter->drawEllipse(-50, -50, 100, 100);
}


there is no change after setting inverted matrix to brush? is there any other way?

bootchk
20th September 2013, 21:15
saics: you're not checking whether the matrix was inverted. If it is not invertible, the identity matrix is returned, which would give unexpected results.

I am just guessing, but it might be just the scaling that needs to be inverted? The matrix from option is the cumulative transform (includes the viewing transform and all parent to child transforms) and could be complex. You might try extracting the scale, and creating a new matrix that just inverts the scaling. I would be more definitive, but I am working through the same problem now.

saics: you're not checking whether the matrix was inverted. If it is not invertible, the identity matrix is returned, which would give unexpected results.

I am just guessing, but it might be just the scaling that needs to be inverted? The matrix from option is the cumulative transform (includes the viewing transform and all parent to child transforms) and could be complex. You might try extracting the scale, and creating a new matrix that just inverts the scaling. I would be more definitive, but I am working through the same problem now.

Added after 5 minutes:

saics: you're not checking whether the matrix was inverted. If it is not invertible, the identity matrix is returned, which would give unexpected results.

I am just guessing, but it might be just the scaling that needs to be inverted? The matrix from option is the cumulative transform (includes the viewing transform and all parent to child transforms) and could be complex. You might try extracting the scale, and creating a new matrix that just inverts the scaling. I would be more definitive, but I am working through the same problem now.

Added after 12 minutes:

More generally, in Qt, the pen and brush scale with an item. You must inverse scale them if you want the pen width to remain constant as you zoom the view. (For a brush, you must inverse scale them especially if you use a non-solid pattern, e.g. crosshatch or texture. Pattern solid seems to always work without inverse scaling?

In my app, I know how an item is scaled (I am not reimplementing paint, just setBrush() on the item). Items may not be scaled uniformly in x and y. But I take the minimum for the itemScale, to take the inverse and scale the brush to that. (You probably don't want a brush scaled non-uniformly.) Code snippets that seem to work for me:




if itemScale == 0.0:
# For a new, infinitesmal item, scale may be 0.0.
scaledWidthF = 9999999
else:
scaledWidthF = 1.0/itemScale * unscaledWidth
self.scaleInvertBrush(brush, scaledWidthF)

def scaleInvertBrush(self, brush, scale):
"""
Scale brush (both x and y scale) to given scale.
"""
transform=QTransform()
transform.scale(scale, scale)
brush.setTransform(transform)