How to handle right mouse click event for QGraphicsItem? - qt

I have a class derived from QGraphicsItem, which is basically like this:
class MyRect: public QObject, public QGraphicsItem
{
Q_OBJECT
Q_INTERFACES(QGraphicsItem)
public:
explicit MyRect(QObject *parent = 0);
MyRect(QColor fillColor, float val, QString txt = "", bool isLeaf = false);
int width, height;
protected:
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
virtual void mousePressEvent(QGraphicsSceneMouseEvent *event);
virtual QRectF boundingRect() const;
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
};
The problem is the mouseReleaseEvent and mousePressEvent only accept QGraphicsSceneMouseEvent argument which cannot detect right button click. I know there is a mousePressEvent(QMouseEvent *event) version that I can use, but it seems not work for QGraphicsItem....Just cannot get stuck here...I appreciate your answer.

Try re-implementing QGraphicsItem::contextMenuEvent and checking the QGraphicsSceneContextMenuEvent::Reason for if the event was caused by a mouse click.

Related

How not inherit class QGraphicsTextItem and implement class UTextItem?

How not inherit class QGraphicsTextItem and implement class UTextItem ,in Qt.
I don't need code similar to below
#include <QGraphicsTextItem>
class UTextItem: public QGraphicsTextItem
{
public:
UTextItem(QGraphicsItem *parent = nullptr);
}
I need code similar to below,I need code similar to below, and not the text drawn by the drawText function, because the drawn string will lose detail when scaled.
#include <QGraphicsItem>
class UTextItem: public QGraphicsItem
{
public:
UTextItem(QGraphicsItem *parent = nullptr);
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
}
Because my current requirement is to have a TextItem that can be deformed, flipped horizontally and vertically, and the scaling of drawText will be distorted, so I can't use this method.
By reading the source code, I found the scaling problem solution myself.
void UTextItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
QFont font;
font.setPixelSize(0.75 * qMin(boundingRect().width(), boundingRect().height()));
painter->save();
painter->setFont(font);
painter->drawText(boundingRect(), Qt::AlignCenter, "hello world");
painter->restore();
}

Resize a QQuickPaintedItem in QML

I use a custom QQuickPaintedItem to display a Qimage in QML.
I registered it using:
main.cpp
qmlRegisterType<ImageItem>("myextension", 1, 0, "ImageItem");
ImageItem.h
class ImageItem : public QQuickPaintedItem
{
Q_OBJECT
Q_PROPERTY(QImage image READ image WRITE setImage NOTIFY imageChanged)
public:
ImageItem(QQuickItem *parent = nullptr);
Q_INVOKABLE void setImage(const QImage &image);
Q_INVOKABLE void resize(const int& width);
void paint(QPainter *painter);
QImage image() const;
signals:
void imageChanged();
private:
QImage current_image;
};
How can I resize QImage in QML for displaying purposes?
Didnt expect it would be that simple.
ImageItem {
image: sqlImageData
id: myIcon
width: 50 //resizing
height:50 //resizing
}

How to map from MainWindow to a QGraphicsItem?

I am attempting to spawn a custom QGraphicsItem inside my scene, but am unsure of how exactly to map the point from its origin to the Item. My location comes from a dropEvent in my MainWindow:
void MainWindow::dropEvent(QDropEvent *event)
{
QPointF dropPos = ui->GraphicsView->mapFrom(this, event->pos());
vModule *module = new vModule(dropPos);
ui->GraphicsView->scene->addItem(module);
}
This is my vModule.cpp:
vModule::vModule(QPointF dropPos)
{
QPointF pos = mapFromScene(dropPos);
setX(pos.x());
setY(pos.y());
// ...
}
// Event handler implementation, shouldn't be relevant
And my vModule.h:
class vModule : public QObject, public QGraphicsItem
{
public:
explicit vModule(QPointF dropPos);
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
QRectF boundingRect() const;
protected:
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
void mousePressEvent(QGraphicsSceneMouseEvent *event);
}
This is the closest to what I logically thought the conversion would be, but it is quite wrong in practice, more wrong than simply passing the position from the event as-is (which is a constant difference in position from the main window?). Can anyone correct my error?
In the constructor of vModule, you're calling mapFromScene before the widget has even been added to the scene.
Add the Widget first then set its position. Also, if you think about it, you're going from global (screen) coordinates to local widget coordinates. This function may be of use, assuming the drop event coordinates are in screen space: -
QPoint QWidget::mapFromGlobal(const QPoint & pos) const
which Qt help defines as: -
Translates the global screen coordinate pos to widget coordinates.

QLineEdit mouseEnter() and mouseExit() events

I want to subclass QLineEdit to add it some signals like mouseEnter() and mouseExit() to become informed when the mouse courser is over the widget and when leaves it.
I could write mouseEnter() like below.
class MyLineEdit:public QLineEdit{
//
// ..
//
protected:
void mouseMoveEvent(QMouseEvent *e);
signals:
void mouseEnter();
}
void MyLineEdit::mouseMoveEvent(QMouseEvent *e)
{
emit mouseEnter();
QLineEdit::mouseMoveEvent(e);
}
It works correctly.
How can I write mouseExit()?
leaveEvent is not a very good name!
#include <QtGui>
#include <QEvent>
class Editor : public QLineEdit
{
Q_OBJECT
public:
void leaveEvent(QEvent *);
signals:
void mouseLeave();
};
void Editor::leaveEvent(QEvent *e);
{
qDebug() << "Mouse has left the building..";
emit mouseLeave();
}

How do I connect slot to user defined variable in Qt?

Sorry if I'm missing something obvious, but I can't seem to find an answer to my question. Any help would be appreciated.
I am trying to use a QSlider to manipulate data in a class I created.
In the main window constructor I have the following:
connect(ui->horizontalSlider, SIGNAL(valueChanged(int)), this, SLOT(setValue(int)));
With a slot defined in the same class:
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
AFrame *frame;
Ui::MainWindow *ui;
public slots:
void setValue(int val)
{
frame->setMphValue(val);
}
};
My frame class is a promoted widget to allow for drawing over the image I have set and is defined as follows:
class AFrame : public QLabel
{
Q_OBJECT
public:
AFrame( QWidget *parent );
void setMphValue(int val) { m_mph = val; }
protected:
void paintEvent( QPaintEvent *event );
private:
int m_mph;
};
The problem is that when I try assigning the m_mph value in the paintEvent function of the AFrame class, the integer value is lost.
Is there something obvious that I'm missing? Is there a better way to approach this problem?
And my paintEvent code:
void AFrame::paintEvent(QPaintEvent *event)
{
QLabel::paintEvent(event);
QPainter painter(this);
QPen pen("#FF0099");
pen.setWidth(8);
painter.setPen(pen);
//rpm
painter.drawLine(250,275,165,165);
//oil
painter.drawLine(450,100,400,75);
//fuel
painter.drawLine(650,95,600,65);
//mph
QRect rec(0,0,125,3);
int velocity = m_mph;
int rpmStartVal = -225;
float mph = velocity * 1.68;
painter.translate(870,275);
painter.rotate(rpmStartVal + mph);
painter.drawRect(rec);
}
The integer value is not being lost. The widget has no magical insight into the fact that it should repaint when the mph value is updated. Your setMphValue should look like below. That's all there's to it.
void setMphValue(int val) {
m_mph = val;
update();
}
To add to Kuba's reply:
You should also check whether val is the same value as previous, in order to avoid avoid repainting when it's not actually necessary - and side-effect infinite loops should anything called by update() later touch setMphValue().
In full:
void setMphValue(int val) {
if (val == m_mph) return;
m_mph = val;
update();
}

Resources