Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Can't get QGraphicsSimpleTextItems placed where I want them in QGraphicsScene.

Can't get QGraphicsSimpleTextItems placed where I want them in QGraphicsScene.

Scheduled Pinned Locked Moved Unsolved General and Desktop
2 Posts 1 Posters 1.1k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • S Offline
    S Offline
    Scopes
    wrote on last edited by Scopes
    #1

    I am baffled as to how to place a text label properly in a QGraphicsScene. I can create a rect and place it where I want to. I can create lines, ellipses, etc., and place them where I want to. I can't get control over QGraphicsSimpleTextItem's position. To place correctly, I need to find the width and height of the string and transform them to scene coordinates. I can't seem to get that done! Help!

    This is basically what I want to do:
    alt text

    GrTestMain::GrTestMain(QWidget *parent)
        : QMainWindow(parent)
    {
        scene = new QGraphicsScene();
    
        // Scene with coordinate system about the center
        scene->setSceneRect(-50.0, -50.0, 100.0, 100.0);
    
        view = new QGraphicsView(this);
        view->setScene(scene);
    
        setCentralWidget(view);
    
    }
    
    void GrTestMain::updateScene()
    {
        QPen outlinePen(Qt::black);
        outlinePen.setCosmetic(true);
    
        // Box
        QGraphicsRectItem *rect = scene->addRect(-20, -20, 40, 40, outlinePen, QBrush(QColor(Qt::cyan)));
    
        // Line through the center
        scene->addLine(-20, 0, 20, 0, outlinePen);
    
        // Make a label to place to the left of the box, centered vertically at 0.0
        QGraphicsSimpleTextItem *text = new QGraphicsSimpleTextItem("A Label");
        text->setFlag(QGraphicsItem::ItemIgnoresTransformations);
        scene->addItem(text);
    
        // Get the bounding rect as a "measurement" of the text string item
        // and so we can look at them in the debugger
        QRectF br = text->sceneBoundingRect();
        QRectF brScene = text->mapRectToScene(br); // Shouldn't this be "transformed"?
    
        qreal xOff = 0.0;
        qreal yOff = 0.0;
    
        // Want to be able to position the text to the left of the box and centered vertically!
        // br and brScene are apparently in pixels (w=53 h=18)
        // How can I transform text width/height to scene coordinates so I can:
        // xOff = br->width();
        // yOff = br->height()/2.0;
        // ?
        //
    
        text->setPos(-20.0 - xOff, 0.0 - yOff);
    
        view->fitInView(scene->itemsBoundingRect(), Qt::KeepAspectRatio);
    }
    
    #include "grtestmain.h"
    #include <QApplication>
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        GrTestMain w;
        w.show();
        w.updateScene();
        return a.exec();
    }
    #ifndef GRTESTMAIN_H
    #define GRTESTMAIN_H
    
    #include <QMainWindow>
    #include <QGraphicsView>
    #include <QGraphicsScene>
    #include <QGraphicsRectItem>
    #include <QGraphicsSimpleTextItem>
    #include <QGraphicsLineItem>
    
    class GrTestMain : public QMainWindow
    {
        Q_OBJECT
    
    public:
        GrTestMain(QWidget *parent = 0);
        void updateScene();
    
    private:
        QGraphicsScene *scene;
        QGraphicsView *view;
    };
    
    #endif // GRTESTMAIN_H
    
    
    
    1 Reply Last reply
    0
    • S Offline
      S Offline
      Scopes
      wrote on last edited by
      #2

      I don't really care for my solution, since I think it should be easier, but what I've found in order to exactly place text items where I want them in the scene is to measure them (boundingRect() or sceneBoundingRect() of the QGraphicsTextItem is always in pixels as far as I can tell), then convert the width and height to scene coordinates by using the View's viewportTransform's m11() and m22() (horizontal and vertical scale factors). If these factors have been established (like by using view's fitInView() method), it seems to work.

      Here's my updated code:

      #include "grtestmain.h"
      
      GrTestMain::GrTestMain(QWidget *parent)
          : QMainWindow(parent)
      {
          scene = new QGraphicsScene();
      
          // Scene with coordinate system about the center
          scene->setSceneRect(-50.0, -50.0, 100.0, 100.0);
      
          view = new QGraphicsView(this);
          view->setScene(scene);
      
          setCentralWidget(view);
      
      }
      
      void GrTestMain::updateScene()
      {
          view->fitInView(scene->sceneRect(), Qt::KeepAspectRatio);
      
          QPen outlinePen(Qt::black);
          outlinePen.setCosmetic(true);
      
          // Box
          scene->addRect(-20, -20, 40, 40, outlinePen, QBrush(QColor(Qt::cyan)));
      
          // Line through the center
          scene->addLine(-20, 0, 20, 0, outlinePen);
      
          // Make a label to place to the left of the box, centered vertically at 0.0
          QGraphicsSimpleTextItem *text = new QGraphicsSimpleTextItem("A Label");
          text->setFlag(QGraphicsItem::ItemIgnoresTransformations);
          scene->addItem(text);
      
          // Get the bounding rect as a "measurement" of the text string item
          // and so we can look at them in the debugger
          QRectF br = text->sceneBoundingRect();
      
          // Want to be able to position the text to the left of the box and centered vertically...
      
          // text item width + 10 pixels in scene coordinates
          qreal xOff = scaleFromPixels(view, (int)(br.width() + 10),   true); 
      
          // get the text item height in scene coordinates
          qreal yOff = scaleFromPixels(view, br.height(),  false); 
      
          text->setPos(-20 - xOff, 0.0 - yOff / 2.0);
      
      }
      
      double GrTestMain::scaleFromPixels(QGraphicsView *theView, int pixelDimension, bool isHorizontal)
      {
          double length = 0.0;
      
          if(isHorizontal)
          {
              length = pixelDimension / qAbs(theView->viewportTransform().m11());
          }
          else
          {
              length = pixelDimension / qAbs(theView->viewportTransform().m22());
          }
      
          return length;
      }
      
      #include "grtestmain.h"
      #include <QApplication>
      
      int main(int argc, char *argv[])
      {
          QApplication a(argc, argv);
          GrTestMain w;
      
          w.show();
          w.updateScene();
          return a.exec();
      }
      
      #ifndef GRTESTMAIN_H
      #define GRTESTMAIN_H
      
      #include <QMainWindow>
      #include <QGraphicsView>
      #include <QGraphicsScene>
      #include <QGraphicsRectItem>
      #include <QGraphicsSimpleTextItem>
      #include <QGraphicsLineItem>
      
      class GrTestMain : public QMainWindow
      {
          Q_OBJECT
      
      public:
          GrTestMain(QWidget *parent = 0);
          void updateScene();
      
      private:
          QGraphicsScene *scene;
          QGraphicsView *view;
          double scaleFromPixels(QGraphicsView *theView, int pixelDimension, bool isHorizontal);
      };
      
      #endif // GRTESTMAIN_H
      
      
      
      1 Reply Last reply
      1

      • Login

      • Login or register to search.
      • First post
        Last post
      0
      • Categories
      • Recent
      • Tags
      • Popular
      • Users
      • Groups
      • Search
      • Get Qt Extensions
      • Unsolved