0

By modifying Qt's Diagram Scene sample, I want my window to display an overlay object when a user clicks on a region that's described by GraphicalScene (original sample shows instead QPolygon). In the following code I'm using QPixmap. However nothing appears when the region is clicked. mousePressEvent passes reasonable positions where clicked. Appreciate your help.

diagramScene.cpp:

#include <iostream>
#include <QtGui>
#include <QPixmap>

#include "pkg/diagramscene.h"
#include "pkg/arrow.h"

DiagramScene::DiagramScene(QMenu *itemMenu, QObject *parent)
    : QGraphicsScene(parent)
{
    myItemMenu = itemMenu;
    myMode = MoveItem;
    myItemType = DiagramOverlayPixmapItem::Overlay;
}

void DiagramScene::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
    if (mouseEvent->button() != Qt::LeftButton) return;
    DiagramOverlayPixmapItem *item;
    switch (this->myMode) {
        case InsertItem: {
            const std::string tmpImgPathBase = "~/images/";
            std::string overlayObj = tmpImgPathBase + "overlayObj.png";
            QPixmap *img = new QPixmap(QString(overlayObj.c_str()));

            item = new DiagramOverlayPixmapItem(myItemType, myItemMenu, img);
            item->setPos(mouseEvent->scenePos());
            this->addPixmap(item->pixmap());  // QGraphicsScene::addPixmap.
            this->update();     // Expecting these parts would do the work..
        }
            break;
        default:
            ;
    }
    QGraphicsScene::mousePressEvent(mouseEvent);
}

diagramOverlayPixmapItem.cpp:

#include <iostream>
#include <QtGui>    
#include "pkg/arrow.h"
#include "pkg/diagramOverlayPixmapItem.h"

DiagramOverlayPixmapItem::DiagramOverlayPixmapItem(DiagramType diagramType, QMenu *contextMenu, QPixmap *img, QGraphicsItem *parent, QGraphicsScene *scene)
    : QGraphicsPixmapItem(*img, parent)
{
    myDiagramType = diagramType;
    myContextMenu = contextMenu;
    setFlag(QGraphicsItem::ItemIsMovable, true);
    setFlag(QGraphicsItem::ItemIsSelectable, true);
    setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
}

void DiagramOverlayPixmapItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
{
    scene()->clearSelection();
    setSelected(true);
    myContextMenu->exec(event->screenPos());
}

QVariant DiagramOverlayPixmapItem::itemChange(GraphicsItemChange change,
                                              const QVariant &value)
{
    if (change == QGraphicsItem::ItemPositionChange) {
        foreach (Arrow *arrow, arrows) {
            arrow->updatePosition();
        }
    }
    return value;
}

This thread is similar (though it's in python) but not giving me an idea.

Community
  • 1
  • 1
IsaacS
  • 3,551
  • 6
  • 39
  • 61
  • Did u check if file is opened successfully? – Blood Jul 17 '12 at 21:49
  • @Blood if you mean 'opened' as 'compile' or 'run', yes. It runs, opens window, a region shown by `QGraphicsScene` is clickable and returns the clicked position. – IsaacS Jul 17 '12 at 21:51
  • No, i ment your QPixmap - QPixmap *img = new QPixmap(QString(overlayObj.c_str())); – Blood Jul 17 '12 at 21:56
  • @Blood path of the file is correct (I copy&pasted from another .cpp code that works), but I'm not sure this particular program successfully opens the given file since I'm not seeing it on my GUI (anyway to verify that QPixmap is successfully opening it?). – IsaacS Jul 17 '12 at 21:59
  • if img != NULL then pixmap was loaded successfully – Blood Jul 17 '12 at 22:07
  • Thx and yes a QPixmap is instantiated. – IsaacS Jul 17 '12 at 22:10
  • 1
    @Blood You mean: `!img->isNull()`, because `img` can't be NULL after a new operation. – leemes Jul 17 '12 at 23:32
  • Actually, yes it can, if it won't get space in memory by new it will be set to byll. – Blood Jul 18 '12 at 09:40

1 Answers1

2

"~" isn't a valid path. This is a shell expansion. Replace it with:

QDir::homePath()

which returns a QString of the current user's home directory. The documentation says:

Under non-Windows operating systems the HOME environment variable is used if it exists [...]


By the way, why are you using std::string? You should use QString in Qt applications.

You could also use the QDir path building mechanism by saying:

QDir tmpImgPathBase = QDir::home(); //home() returns a QDir, homePath() a QString
tmoImgPathBase.cd("images"); //navigate to relative directory
QString overlayObj = tmoImgPathBase.filePath("overlayObj.png"); //file in direct.
QPixmap *img = new QPixmap(overlayObj);

Note that you also should not overuse pointers in C++. The pixmap doesn't need to be a pointer (which you never delete here, causing memory leaks!):

QPixmap img = QPixmap(overlayObj);
item = new DiagramOverlayPixmapItem(myItemType, myItemMenu, img);

and

// I removed the asterisk at both the argument img and the
// forwarding to the constructor of QGraphicsPixmapItem.
DiagramOverlayPixmapItem::DiagramOverlayPixmapItem(DiagramType diagramType, QMenu *contextMenu, QPixmap img, QGraphicsItem *parent, QGraphicsScene *scene)
    : QGraphicsPixmapItem(img, parent)
{
    ...
}
leemes
  • 44,967
  • 21
  • 135
  • 183
  • Applying all your suggestions (i.e. using `QDir`, replacing std::string with `QString`, removing unnecessary pointer) solved. Maybe using "~" as path was the wrongdoer as you suggested. Thanks! – IsaacS Jul 18 '12 at 00:05
  • 1
    Sure, using "~" was the error, the rest is only "style" (but the memory leak like this can be dangerous in most situations, though) – leemes Jul 18 '12 at 01:38