Invoke copy paste for QgraphicsTextItem - qt

How can the cut, copy paste slots be invoked for QgraphicsTextItem. Though the the text editor has default slots for cut, copy and paste, but I don't know how to invoke them.
I have class that is inherited from QgraphicsTextItem. The use of this class is to add a text in GraphicsView. Now I want the cut, paste and copy functality for it. How can I go for that?
drawText.h
#include <QGraphicsTextItem>
#include <QPen>
QT_BEGIN_NAMESPACE
class QFocusEvent;
class QGraphicsItem;
class QGraphicsScene;
class QGraphicsSceneMouseEvent;
QT_END_NAMESPACE
class mText : public QGraphicsTextItem
{
Q_OBJECT
public:
mText( int, QGraphicsItem *parent=0 );
enum { Type = UserType + 5 };
int type() const;
int id;
signals:
void lostFocus(mText *item);
void selectedChange(QGraphicsItem *item);
protected:
QVariant itemChange(GraphicsItemChange change, const QVariant &value);
void focusOutEvent(QFocusEvent *event);
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);
};
.cpp
#include "mtext.h"
mText::mText( int i, QGraphicsItem *parent)
: QGraphicsTextItem(parent )
{
//assigns id
id = i;
}
int mText::type() const
{
// Enable the use of qgraphicsitem_cast with text item.
return Type;
}
QVariant mText::itemChange(GraphicsItemChange change,
const QVariant &value)
{
if (change == QGraphicsItem::ItemSelectedHasChanged)
emit selectedChange(this);
return value;
}
void mText::focusOutEvent(QFocusEvent *event)
{
setTextInteractionFlags(Qt::NoTextInteraction);
emit lostFocus(this);
QGraphicsTextItem::focusOutEvent(event);
}
void mText::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
{
if (textInteractionFlags() == Qt::NoTextInteraction)
setTextInteractionFlags(Qt::TextEditorInteraction);
QGraphicsTextItem::mouseDoubleClickEvent(event);
}

Related

How to update changes in SingleTon type custom QAbstractListModel on QML ListView?

I'm very new to QML, so having a struggle about how to propagate the changes in a custom QAbstractListModel to QML List View.
I have the following HackNewsModel.
The header file
#ifndef HACKNEWSMODEL_H
#define HACKNEWSMODEL_H
#include "Singleton.hpp"
#include <QAbstractListModel>
#include <QJsonObject>
#include <QDateTime>
struct HackNews
{
QString m_id;
bool m_deleted;
QString m_type;
QString m_by;
QDateTime m_time;
QString m_text;
bool m_dead;
QString m_parentId;
QString m_pollId;
QStringList m_kidsIdList;
QString m_url;
QString m_score;
QString m_title;
QStringList m_partsIdList;
QString m_descendantCount;
};
class HackNewsModel : public QAbstractListModel, public Singleton<HackNewsModel>
{
Q_OBJECT
public:
void addHackNews(QJsonObject &hackNews);
enum Roles {
IdRole = Qt::UserRole + 1
};
QHash<int, QByteArray> roleNames() const override;
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
QVariant data(const QModelIndex& index, int role/* = Qt::DisplayRole*/) const override;
friend class Singleton<HackNewsModel>;
explicit HackNewsModel(QObject * parent = nullptr);
~HackNewsModel() override;
private:
QList<HackNews> m_hackNewsList;
QHash<int, QByteArray> m_roles;
};
#endif // HACKNEWSMODEL_H
The Cpp file.
#include "HackNewsModel.h"
#include <QJsonArray>
#include <QDebug>
HackNewsModel::HackNewsModel(QObject *parent) : QAbstractListModel(parent)
{
m_roles[0] = "id";
QString id = "Demo id";
bool deleted = false;
QString type;
QString by;
QDateTime time;
QString text;
bool dead = false;
QString parentId;
QString pollId;
QStringList kidsIdList;
QString url;
QString score;
QString title;
QStringList partsIdList;
QString descendantCount;
m_hackNewsList.append(HackNews{id+"1", deleted, type, by, time, text, dead, parentId, pollId, kidsIdList, url, score, title, partsIdList, descendantCount});
m_hackNewsList.append(HackNews{id+"2", deleted, type, by, time, text, dead, parentId, pollId, kidsIdList, url, score, title, partsIdList, descendantCount});
m_hackNewsList.append(HackNews{id+"3", deleted, type, by, time, text, dead, parentId, pollId, kidsIdList, url, score, title, partsIdList, descendantCount});
m_hackNewsList.append(HackNews{id+"4", deleted, type, by, time, text, dead, parentId, pollId, kidsIdList, url, score, title, partsIdList, descendantCount});
m_hackNewsList.append(HackNews{id+"5", deleted, type, by, time, text, dead, parentId, pollId, kidsIdList, url, score, title, partsIdList, descendantCount});
}
HackNewsModel::~HackNewsModel()
{
}
void HackNewsModel::addHackNews(QJsonObject &hackNews)
{
QString id = "Demo id";
bool deleted = false;
QString type;
QString by;
QDateTime time;
QString text;
bool dead = false;
QString parentId;
QString pollId;
QStringList kidsIdList;
QString url;
QString score;
QString title;
QStringList partsIdList;
QString descendantCount;
if(hackNews.contains("id"))
{
id = hackNews["id"].toString();
}
if(hackNews.contains("deleted"))
{
deleted = hackNews["deleted"].toBool();
}
if(hackNews.contains("type"))
{
type = hackNews["type"].toString();
}
if(hackNews.contains("by"))
{
by = hackNews["by"].toString();
}
if(hackNews.contains("time"))
{
time = QDateTime::fromTime_t(static_cast<unsigned int>(hackNews["time"].toInt()));
}
if(hackNews.contains("text"))
{
text = hackNews["text"].toString();
}
if(hackNews.contains("dead"))
{
dead = hackNews["dead"].toBool();
}
if(hackNews.contains("parent"))
{
parentId = hackNews["parent"].toString();
}
if(hackNews.contains("poll"))
{
pollId = hackNews["poll"].toString();
}
if(hackNews.contains("kids"))
{
foreach (QVariant value, hackNews["kids"].toArray().toVariantList()) {
kidsIdList.append(value.toString());
}
}
if(hackNews.contains("url"))
{
url = hackNews["url"].toString();
}
if(hackNews.contains("title"))
{
title = hackNews["title"].toString();
}
if(hackNews.contains("parts"))
{
foreach (QVariant value, hackNews["parts"].toArray().toVariantList()) {
partsIdList.append(value.toString());
}
}
if(hackNews.contains("descendents"))
{
descendantCount = hackNews["descendents"].toString();
}
m_hackNewsList.append(HackNews{id, deleted, type, by, time, text, dead, parentId, pollId, kidsIdList, url, score, title, partsIdList, descendantCount});
}
QHash<int, QByteArray> HackNewsModel::roleNames() const
{
return m_roles;
}
int HackNewsModel::rowCount(const QModelIndex &parent) const
{
if (parent.isValid())
return 0;
return m_hackNewsList.size();
}
QVariant HackNewsModel::data(const QModelIndex &index, int /*role*/) const
{
// if (!hasIndex(index.row(), index.column(), index.parent()))
if(!index.isValid())
return QVariant();
const HackNews &news = m_hackNewsList.at(index.row());
// if(role == IdRole){
// qDebug() << "Seeking id";
return news.m_id;
// }
// return QVariant();
}
However, this data model gets updated through NetworkRequestMaker that makes some request to a network and updates the model.
Header file of NetworkRequestMaker.
#ifndef NETWORKREQUESTMAKER_H
#define NETWORKREQUESTMAKER_H
#include <QObject>
#include <QNetworkAccessManager>
class QNetworkReply;
class NetworkRequestMaker : public QObject
{
Q_OBJECT
public:
explicit NetworkRequestMaker(QObject *parent = nullptr);
void startRequest(const QUrl &requestedUrl);
void httpReadyRead();
void httpFinished();
private:
QUrl url;
QNetworkAccessManager m_qnam;
QNetworkReply *m_reply;
};
#endif // NETWORKREQUESTMAKER_H
Cpp file.
#include "NetworkRequestMaker.h"
#include <QNetworkReply>
#include <QDebug>
#include <QJsonDocument>
#include <QJsonArray>
#include <QJsonObject>
#include <QDateTime>
#include "HackNewsModel.h"
NetworkRequestMaker::NetworkRequestMaker(QObject *parent)
: QObject(parent),
m_reply(nullptr)
{
startRequest(QUrl("https://hacker-news.firebaseio.com/v0/item/8863.json?print=pretty"));
startRequest(QUrl("https://hacker-news.firebaseio.com/v0/item/2921983.json?print=pretty"));
startRequest(QUrl("https://hacker-news.firebaseio.com/v0/item/121003.json?print=pretty"));
startRequest(QUrl("https://hacker-news.firebaseio.com/v0/item/192327.json?print=pretty"));
startRequest(QUrl("https://hacker-news.firebaseio.com/v0/item/126809.json?print=pretty"));
startRequest(QUrl("https://hacker-news.firebaseio.com/v0/item/160705.json?print=pretty"));
}
void NetworkRequestMaker::startRequest(const QUrl &requestedUrl)
{
url = requestedUrl;
m_reply = m_qnam.get(QNetworkRequest(url));
connect(m_reply, &QNetworkReply::finished, this, &NetworkRequestMaker::httpFinished);
connect(m_reply, &QIODevice::readyRead, this, &NetworkRequestMaker::httpReadyRead);
}
void NetworkRequestMaker::httpReadyRead()
{
QString strReply = QString(m_reply->readAll());
QJsonDocument jsonResponse = QJsonDocument::fromJson(strReply.toUtf8());
QJsonObject jsonObj = jsonResponse.object();
HackNewsModel::getInstance().addHackNews(jsonObj);
}
void NetworkRequestMaker::httpFinished()
{
if (m_reply->error()) {
qDebug()<<tr("Download failed:\n%1.").arg(m_reply->errorString());
}
}
The singleton class is as the following.
#ifndef SINGLETON_HPP
#define SINGLETON_HPP
template <typename T>
class Singleton
{
public:
/*!*************************************************************************
\brief Constructs the singleton (if necessary) and returns the pointer.
****************************************************************************/
static T& getInstance()
{
static T _singleton; //!< Unique instance of class T
return _singleton;
}
protected:
/*!*************************************************************************
\brief Constructor.
\note protected to avoid misuses.
****************************************************************************/
Singleton() {}
/*!*************************************************************************
\brief Destructor.
\note protected to avoid misuses.
****************************************************************************/
virtual ~Singleton() {}
/*!*************************************************************************
\brief Copy constructor.
\note protected to avoid misuses.
****************************************************************************/
Singleton(const Singleton&);
/*!*************************************************************************
\brief Assignment operator.
\note protected to avoid misuses.
****************************************************************************/
Singleton& operator=(const Singleton&);
};
#endif // SINGLETON_HPP
Main cpp file is as below.
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "NetworkRequestMaker.h"
#include "HackNewsModel.h"
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
NetworkRequestMaker testRequestMaker;
qmlRegisterType<HackNewsModel>("Hacknews", 1, 0, "HackNewsModel");
QQmlApplicationEngine engine;
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
return app.exec();
}
My QML file is as below.
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
import Hacknews 1.0
Frame {
width: 640
height: 480
ListView {
id: listView
anchors.fill: parent
model: HackNewsModel {}
delegate: Text {
text: model.id
}
}
}
Despite the model being a singleton, qmnl listview doesn't show the updated entires. How do I enable it to show the updated entries?
Thanks.
Part one: QAbstractListModel interface
First of all, your HackNewsModel needs to signal that a row has been added. Add the following to your void addHackNews method
void HackNewsModel::addHackNews(QJsonObject &hackNews)
{
...
beginInsertRows(QModelIndex(), rowCount(), rowCount());
m_hackNewsList.append(HackNews{id, deleted, type, by, time, text, dead, parentId, pollId, kidsIdList, url, score, title, partsIdList, descendantCount});
endInsertRows();
}
The beginInsertRows method expects the following:
parent model index. In your case this is an invalid index, the list is flat.
start index of added. Set this to the size of the list (which is 1 higher than the zero-based index of the last item)
end inded of added. Set this to the start index, since you are only adding one item.
If you will be adding more functionality to your HackNewsModel make sure you implement the other begin* and end* pairs as well.
See docs: https://doc.qt.io/qt-5/qabstractitemmodel.html#beginInsertRows
Part two: QML singleton
Secondly, the way you have implemented the Singleton pattern doesn't mean anything to the QML Engine. You need to tell the engine that the class is singleton:
qmlRegisterSingletonType<HackNewsModel>("HackNews", 1, 0, "HackNewsModel",
[](QQmlEngine *eng, QJSEngine *js) -> QObject *
{
eng->setObjectOwnership(&HackNewsModel::getInstance(),
QQmlEngine::ObjectOwnership::CppOwnership);
return &HackNewsModel::getInstance();
});
Note: setting the ownership might not be obligatory
This then also means you cannot instantiate the HackNewsModel as you do in your QML, if I'm correct, the following should work:
ListView {
id: listView
model: HackNewsModel
...
}

QtRemoteObjects replicas being called for every single replica signal

I built a minimal source/replica direct connection QtRo system:
https://codeshare.io/29xj4V
What I would like to achieve is uniquely identify the message coming from the source to be a reply to the one sent from each of the replicas.
If rep1 sends "hello source, I'm rep1", I'd like the source to reply back "hello rep1 this is source". I would like to achieve the same with 3 replicas running at a very high and different rate. The issue is on every signal to the source the source replies back to all 3 replicas; the way i'm filtering this is by sending the "id" of the replica in text format then append that id back with the message to check for it inside the replica itself, if it's a match then it accepts the message, otherwise it discards it. Although this seems to be working, there's a big overhead here. My question would be: is there a better way to handle that instead of sending an identifier back and forth? thanks
The replicas receive the same signals, there is no way to filter that data from the source side. So the filtering must be done on the client's side, for this you can use an attribute that is the identifier and send that data as a new parameter in the signal instead of sending it within the message. So although there is a lot of calls the cost will be minimal since the if statement does not consume much time.
remoteminimal.rep
class RemoteMinimal
{
SIGNAL(sendData(const QString &, const QString &));
SLOT(void printData(const QString &));
SLOT(void process(const QString &, const QString &));
SLOT(void triggerSendData());
};
minimalsource.h
#ifndef MINIMALSOURCE_H
#define MINIMALSOURCE_H
#include "rep_remoteminimal_source.h"
#include <QObject>
class MinimalSource : public RemoteMinimalSource
{
Q_OBJECT
public:
MinimalSource(QObject *parent = nullptr);
~MinimalSource() override;
public slots:
void printData(const QString& data) override;
void process(const QString& data, const QString & id) override;
void triggerSendData() override;
private:
int m_global_server;
};
#endif // MINIMALSOURCE_H
minimalsource.cpp
#include "minimalsource.h"
MinimalSource::MinimalSource(QObject* parent):
RemoteMinimalSource (parent), m_global_server(0)
{
}
MinimalSource::~MinimalSource(){}
void MinimalSource::printData(const QString& data)
{
Q_UNUSED(data);
}
void MinimalSource::process(const QString& data, const QString &id)
{
m_global_server++;
emit sendData(data+":"+QString::number(m_global_server), id);
}
void MinimalSource::triggerSendData()
{
}
objects.h
#ifndef OBJECTS_H
#define OBJECTS_H
#include <QObject>
#include "rep_remoteminimal_replica.h"
class QTimer;
class Objects: public QObject
{
Q_OBJECT
Q_PROPERTY(QString id READ id WRITE setId)
Q_PROPERTY(double rate READ rate WRITE setRate)
public:
explicit Objects(QSharedPointer<RemoteMinimalReplica> ptr);
~Objects();
double rate() const;
void setRate(double rate);
QString id() const;
void setId(const QString &id);
signals:
void sendData(const QString&, const QString &);
public slots:
void printData(const QString&, const QString &);
void process(const QString&);
void triggerSendData();
void run();
private:
int m_global_server;
QTimer *m_loop;
double m_rate;
QString m_id;
QSharedPointer<RemoteMinimalReplica> reptr;
};
#endif // OBJECTS_H
objects.cpp
#include "objects.h"
#include <QTimer>
#include <QDebug>
Objects::Objects(QSharedPointer<RemoteMinimalReplica> ptr): QObject (Q_NULLPTR),
m_global_server(0), reptr(ptr)
{
m_loop = new QTimer(this);
}
Objects::~Objects(){}
void Objects::printData(const QString& data, const QString& id)
{
if(id == m_id)
qDebug() << "[" << m_id << "]:" << data;
}
void Objects::process(const QString& data)
{
emit sendData(data+":processed", m_id);
}
void Objects::run()
{
connect(m_loop, &QTimer::timeout, this, &Objects::triggerSendData);
m_loop->setInterval(static_cast<int>(1000/m_rate));
m_loop->start();
}
QString Objects::id() const
{
return m_id;
}
void Objects::setId(const QString &id)
{
m_id = id;
}
double Objects::rate() const
{
return m_rate;
}
void Objects::setRate(double rate)
{
m_rate = rate;
}
void Objects::triggerSendData()
{
m_global_server++;
emit sendData(QString("test:%1:%2").arg(m_id).arg(m_global_server), m_id);
}
The complete example you find here

Paste operation in QGraphicsView

I am implenting copy paste operation in QGraphicsView to different entites like circle, point, ellipse etc. Applied copy operation but unable to get how to apply paste operation for it. Please help me out solve the problem. My slot for copy appears as follows:
cadgraphicsscene.cpp
void CadGraphicsScene::copy()
{
selectItems();
}
void CadGraphicsScene::selectItems()
{
// refresh record of selected items and their starting positions
selectedItems.clear();
foreach (QGraphicsItem *item, itemList)
{
if (item->isSelected())
{
if (dynamic_cast<QGraphicsItem *>(item))
{
selectedItems.append(qMakePair(
dynamic_cast<QGraphicsItem *>(item),
item->scenePos()));
}
}
}
}
cadgraphicsscene.h
#ifndef CADGRAPHICSSCENE_H
#define CADGRAPHICSSCENE_H
#include <QGraphicsScene>
#include <QXmlStreamWriter>
#include <QUndoStack>
#include "cadcommandadd.h"
#include "cadcommanddelete.h"
#include "cadcommandmove.h"
class CadGraphicsScene : public QGraphicsScene
{
Q_OBJECT
public:
explicit CadGraphicsScene(QObject *parent, QUndoStack *);
enum Mode { NoMode, PointMode, LineMode, CircleMode, EllipseMode, TextMode };
QFont font() const
{
return myFont;
}
QColor textColor() const
{
return myTextColor;
}
void setTextColor(const QColor &color);
void setFont(const QFont &font);
void deleteItems();
void copy();
void writeStream(QXmlStreamWriter *stream);
void readStream(QXmlStreamReader *stream);
public slots:
void setMode(Mode mode);
void selectItems();
void editorLostFocus(mText *item);
protected:
void mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent);
void mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent);
void setFlags();
void areItemsSelectable(bool);
signals:
void textInserted(QGraphicsTextItem *item);
void itemSelected(QGraphicsItem *item);
private:
Mode entityMode;
QUndoStack *mUndoStack;
bool mFirstClick;
bool mSecondClick;
bool mThirdClick;
bool mPaintFlag;
QVector<QPointF> stuff;
QPointF start_p, mid_p, end_p, move_p, check_p;
QPen paintpen, linePen;
QList<QGraphicsItem *> itemList;
Point *pointItem;
Line *lineItem;
Circle *circleItem;
Ellipse *ellipseItem;
mText *textItem;
QColor myTextColor;
QFont myFont;
typedef QPair<QGraphicsItem *, QPointF> itemPos;
QList<itemPos> selectedItems;
};
#endif // CADGRAPHICSSCENE_H

“text-overflow” for a QLabel’s text rendering in QT

I have got a QLabel element in a widget which can be resized. The text can overflow boundaries, so I need, for the application to look more elegant, some way to make the text generate an ellipsis (...) after the last totally visible word in the text.
Making layouts in HTML/CSS I used to use text-overflow: ellipsis; for this, but for QT classes I have not found any information on this.
It looks like on your label resize event you can create elided text using the new width of the widget and reset the text. Use QFontMetrics::elidedText method to get the elided version of the string.
QString text("some long text without elipsis");
QFontMetrics metrics(label->font());
QString elidedText = metrics.elidedText(text, Qt::ElideRight, label->width());
label->setText(elidedText);
hope this helps, regards
I've modified solution described above and created a function:
static void SetTextToLabel(QLabel *label, QString text)
{
QFontMetrics metrix(label->font());
int width = label->width() - 2;
QString clippedText = metrix.elidedText(text, Qt::ElideRight, width);
label->setText(clippedText);
}
Hope it will be useful.
Qt-5 includes an example of an elided label class which may be a useful reference when implementing your own.
From the example:
elidedlabel.h:
class ElidedLabel : public QFrame
{
Q_OBJECT
Q_PROPERTY(QString text READ text WRITE setText)
Q_PROPERTY(bool isElided READ isElided)
public:
explicit ElidedLabel(const QString &text, QWidget *parent = 0);
void setText(const QString &text);
const QString & text() const { return content; }
bool isElided() const { return elided; }
protected:
void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE;
signals:
void elisionChanged(bool elided);
private:
bool elided;
QString content;
};
elidedlabel.cpp:
ElidedLabel::ElidedLabel(const QString &text, QWidget *parent)
: QFrame(parent)
, elided(false)
, content(text)
{
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
}
void ElidedLabel::setText(const QString &newText)
{
content = newText;
update();
}
void ElidedLabel::paintEvent(QPaintEvent *event)
{
QFrame::paintEvent(event);
QPainter painter(this);
QFontMetrics fontMetrics = painter.fontMetrics();
bool didElide = false;
int lineSpacing = fontMetrics.lineSpacing();
int y = 0;
QTextLayout textLayout(content, painter.font());
textLayout.beginLayout();
forever {
QTextLine line = textLayout.createLine();
if (!line.isValid())
break;
line.setLineWidth(width());
int nextLineY = y + lineSpacing;
if (height() >= nextLineY + lineSpacing) {
line.draw(&painter, QPoint(0, y));
y = nextLineY;
//! [2]
//! [3]
} else {
QString lastLine = content.mid(line.textStart());
QString elidedLastLine = fontMetrics.elidedText(lastLine, Qt::ElideRight, width());
painter.drawText(QPoint(0, y + fontMetrics.ascent()), elidedLastLine);
line = textLayout.createLine();
didElide = line.isValid();
break;
}
}
textLayout.endLayout();
if (didElide != elided) {
elided = didElide;
emit elisionChanged(didElide);
}
}
This is how I achive. Behave just like regular QLabel yet with ellipsis.
class EllipsisLabel : public QLabel
{
Q_OBJECT
public:
explicit EllipsisLabel(QWidget *parent = nullptr);
explicit EllipsisLabel(QString text, QWidget *parent = nullptr);
void setText(QString);
protected:
void resizeEvent(QResizeEvent *);
private:
void updateText();
QString m_text;
};
EllipsisLabel::EllipsisLabel(QWidget *parent)
: EllipsisLabel("", parent)
{
}
EllipsisLabel::EllipsisLabel(QString text, QWidget *parent)
: QLabel(parent)
{
setText(text);
}
void EllipsisLabel::setText(QString text)
{
m_text = text;
updateText();
}
void EllipsisLabel::resizeEvent(QResizeEvent *event)
{
QLabel::resizeEvent(event);
updateText();
}
void EllipsisLabel::updateText()
{
QFontMetrics metrics(font());
QString elided = metrics.elidedText(m_text, Qt::ElideRight, width());
QLabel::setText(elided);
}

Extending QGraphicsScene

I am extending QGraphicsItem to be added to a extended QGraphicsSene. when I added the extended item to the scene and the scene to the graphics view in the normal way it shows the image but when I added the image as follows it does not show. could some one please check this out and tell me the issue.
header
#ifndef IMAGEMAP_H
#define IMAGEMAP_H
#include <QGraphicsItem>
#include <QGraphicsScene>
class ScanImage : public QGraphicsItem
{
public:
ScanImage(const QString imgsrc);
~ScanImage();
void setImageSource(const QString is);
QString imageSource();
QRectF boundingRect() const;
void paint( QPainter *painter,
const QStyleOptionGraphicsItem *option,
QWidget *widget);
protected:
void mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent);
private:
QString imgsrc;
};
class ImageHolder : public QGraphicsScene
{
public:
ImageHolder();
~ImageHolder();
protected:
void mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent);
void mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent);
private:
QRectF selectedRect;
};
#endif //
source
#include "imagemap.h"
#include "QtGui"
ScanImage::ScanImage(const QString is)
{
imgsrc=is;
update();
}
ScanImage::~ScanImage()
{
}
ImageHolder::ImageHolder()
{
setSceneRect(0.0,0.0,512.0,512.0);
ScanImage im("2.jpg");
im.setZValue(1.0);
im.setVisible(true);
addItem(&im);
}
ImageHolder::~ImageHolder()
{
}
void ScanImage::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
qDebug() <<event->pos();
}
void ImageHolder::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
qDebug() <<event->scenePos().rx();
selectedRect.setTopLeft(event->scenePos());
}
void ImageHolder::mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
qDebug() <<mouseEvent->scenePos().ry();
selectedRect.setBottomRight(mouseEvent->scenePos());
addRect ( selectedRect);
}
QRectF ScanImage::boundingRect() const
{
return QRectF(0.0, 0.0, 512.0, 512.0);
}
void ScanImage::paint( QPainter* painter,
const QStyleOptionGraphicsItem*,
QWidget* )
{
QRectF target(0.0, 0.0, 512.0, 512.0);
QRectF source(0.0, 0.0, 512.0, 512.0);
painter->drawImage(target, QImage(imgsrc),source);
}
void ScanImage::setImageSource(QString is)
{
imgsrc = is;
}
QString ScanImage::imageSource()
{
return imgsrc;
}
main
int main(int argv, char* argc[])
{
QApplication app(argv,argc);
ImageHolder scene;
QGraphicsView view(&scene);
view.resize(512,512);
view.show();
return app.exec();
}
You are adding a QGraphicsItem allocated as a local variable on the QGraphicsScene constructor's stack. Once the constructor is finished, the objects on its stack are automatically deallocated (i.e. deleted) and in your case removed from the scene. Use new operator to create the item.

Resources