[Qt-jambi-interest] QGraphicsView and coordinates system... (again)
Gunnar Sletta
gunnar at trolltech.com
Tue Jul 22 11:34:30 CEST 2008
moebius at altern.org wrote:
> Hello !
>
> I'm still working on my mathematical function plot program and I still
> have problems to make it work as expected.
>
> Thanks to Eskil, I found the ItemIgnoresTransformations flag that permit
> to make some items (especially text items) ignoring scale transformations.
> But item positioning is still a bit confusing for me. Especially when view
> is resized.
>
> I wrote a small snippet to explain my problem. The code below should
> display an ellipse and a rectangle fitting the view (thanks to fitInView()
> method). I'd also like to display a label displaying rectangle height at
> the top left corner outside the rectangle. To do this, once all my objects
> are created, I set the label position using :
>
> label.setPos(scene.sceneRect().left(), scene.sceneRect().top());
>
> This works fine except the label is displayed inside the rectangle. To
> display it outside the rectangle, I substract the width of the label from
> the x coordinate of its position. So the previous line becomes :
>
> label.setPos(scene.sceneRect().left()-label.boundingRect().width(),
> scene.sceneRect().top());
>
> My label is now positioned outside the rectangle, but when I resize the
> window, the distance between the top left corner of the rectangle and the
> label is varying. My problem is to make this distance constant. I'd like
> to be able to put my label at a constant position relatively to the scene
> bounding rectangle.
>
Hi,
The main problem here is that you are trying to stretch QGraphicsView
beyond its design goals ;-) QGraphicsView was written to suppport a
scene with nested transformation. The labels or tags you are using here
are not supported by this model. Using the ignores transformation flag
you can get some of this behaviour, but not quite as the anchors used to
position the non-transformed items are still transformed. Their x,y
position in the scene is still subject to the current scene
transformation...
This can be acheived, but it is a bit hackish... All of the labels in
your UI must have an anchor of some sort. In this case I used the
rectangle and its topleft corner. To avoid the transformation of the
labels x and y coordinates, I calculate the anchors position in VIEW
coordinates. Then I apply the offset adjustment, then transform this
VIEW position into scene space. By doing so and calling the
adjustLabelToAnchor for every time the anchor item is moved you will get
the.
QGraphicsView is not the solution to every problem. You might consider
implementing some functionality of your plotter using QPainter directly.
import com.trolltech.qt.core.*;
import com.trolltech.qt.gui.*;
public class GraphicsViewLabels extends QMainWindow {
private QGraphicsScene scene;
private MyGraphicsView view;
private QGraphicsSimpleTextItem label;
private QGraphicsItemInterface anchor;
public static void main(String[] args) {
QApplication.initialize(args);
GraphicsViewLabels test = new GraphicsViewLabels();
test.show();
QApplication.exec();
}
private void adjustLabelToAnchor() {
QPoint anchorPos =
view.mapFromScene(anchor.boundingRect().topLeft());
QPointF labelPos = view.mapToScene(anchorPos.x() - (int)
label.boundingRect().width(),
anchorPos.y());
label.setPos(labelPos);
}
public GraphicsViewLabels(){
scene = new QGraphicsScene(this);
QGraphicsEllipseItem ellipse = new QGraphicsEllipseItem(10.0,
20.0, 250.0, 150.0);
scene.addItem(ellipse);
QGraphicsRectItem rect = new QGraphicsRectItem(10.0, 20.0,
250.0, 150.0);
scene.addItem(rect);
anchor = rect;
label = new
QGraphicsSimpleTextItem(String.valueOf(-scene.sceneRect().top()));
/*
* With this line the label position relative to other items
change when
window is resized
*/
/*
* With this line the label position relative to other items doesn't
change when window is resized
*/
// label.setPos(scene.sceneRect().left(),
scene.sceneRect().top());
label.setFlag(QGraphicsItem.GraphicsItemFlag.ItemIgnoresTransformations,
true);
scene.addItem(label);
view = new MyGraphicsView(scene);
this.setCentralWidget(view);
this.resize(new QSize(400, 300).expandedTo(this.minimumSizeHint()));
}
class MyGraphicsView extends QGraphicsView {
public MyGraphicsView(QGraphicsScene scene) {
super(scene);
}
@Override
protected void resizeEvent(QResizeEvent event) {
super.resizeEvent(event);
fitInView(scene.sceneRect(),
Qt.AspectRatioMode.IgnoreAspectRatio);
scale(0.8, 0.8);
adjustLabelToAnchor();
}
}
}
More information about the Qt-jambi-interest
mailing list