[Qt-jambi-interest] QGraphicsView and coordinates system... (again)

moebius at altern.org moebius at altern.org
Wed Jul 23 20:04:07 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();
>
>        }
>     }
> }
>
>

Thank you for your response.

Your solution seems actually a bit tricky. But it's still interesting to
see what a master-of-the-jambi-world can do.

For practical I directly used the QPainter to solve this problem.

Anyway, thank you very much again.







More information about the Qt-jambi-interest mailing list