Send Signal From Child To Parent On Mouse Click Qt - c++

I have a MainWindow, a DockWidget and a QGLWidget inside it. I am drawing circles inside the QGLWidget. I want to print the x and y coordinates of the place that I am clicking to the labels inside DockWidget.
I would be glad if someone could show me the way?

Override the QWidget::mousePressEvent(QMouseEvent *) or QWidget::mouseReleaseEvent(QMouseEvent *) of the QGLWidget and create a signal for sending the x and y. It means you have to create own class inherithing from QGLWidget.
It could look like this:
void MyGLWidget::mouseReleaseEvent(QMouseEvent *event)
{
emit printXY(event->pos());
}
and in the MyGLWidget.h:
signals:
void printXY(const QPointF& clickedPos);
then create a slot in the DockWidget:
public slots:
void onPrintXY(const QPointF& clickedPos);
and connect it in the place where you create the MyGLWidget. I suppose in some function of the DockWidget like:
void DockWidget::createGLWidget()
{
MyGLWidget widget = new MyGLWidget;
connect(widget, &MyGLWidget::printXY, this, &DockWidget::onPrintXY);
}

Related

Using Qt Undo Framework With QPainter

I am creating a drawing application with Qt and want to include undo and redo commands for whatever is drawn on a QImage. For this, I want to at least try and incorporate the Qt undo framework, since manually doing it will probably be above my skill level.
I have a MainWindow class where the main work is done and where I have the menu with undo and redo QActions.
The painting is done in a QWidget class called DrawingArea like this (PenShape is an enum of shapes):
void DrawingArea::drawLine(const QPoint &endPoint) {
QPainter painter(&image);
//some pen config code
switch (currentShape){
case PenShape::Polygon:
painter.drawPolygon(&endPoint, 5, Qt::OddEvenFill);
break;
case PenShape::Line:
painter.drawLine(lastPoint, endPoint);
break;
//other shapes and their draw methods..
}
update()
}
So as can be seen, the painter can draw in multiple shapes. I know I would have to somehow transfer this to a QUndoCommand class, but how? The drawline method is called only in DrawingArea's mouse event methods like this:
void DrawingArea::mousePressEvent(QMouseEvent *event){
if (event->button() == Qt::LeftButton) {
lastPoint = event->pos();
}
}
The QtUndoStack is located in MainWindow and the QActions are also there, but somehow I would have to connect the drawLine QtUndoCommand class and the mousePressEvent and mainWindow QAction with its connected slot method all together. This is what I don't know how to do.
Any help is appreciated!
Edit, here's the menu button actions:
m_undo = undoStack->createUndoAction(this, tr("&Undo"));
m_undo->setShortcuts(QKeySequence::Undo);
m_redo = undoStack->createRedoAction(this, tr("&Redo"));
m_redo->setShortcuts(QKeySequence::Redo);
I have no QUndoCommand classes because I'm unsure of how to create them yet.
In my MainWindow, I have a undoStack declared like this:
undoStack = new QUndoStack(this);

Qt : catched mouseMoseEvent dont interact with QWebView html page element

I catch the mouseMoveEvent of my QWebView for restarting a timer of a screensaver. The problem is that now the mouseMoveEvent isnt distribued to the HTML elements so its impossible for example to move a sliding bar on the page.
I use connect to bind mouseMoveEvent to the restart slot :
QObject::connect(_view, SIGNAL(mouseMoveEvent(QMouseEvent*)), _mediaPlayer, SLOT(stop()));
WebView class :
class WebView : public QWebView
{
Q_OBJECT
public:
WebView(QString menu) : _menuDesc(menu) {};
WebView(){};
void setMenuDesc(QString menu) {_menuDesc = menu;};
QString getMenuDesc() {return _menuDesc;};
void setCurrPage(QString page) {_currPage = page;};
QString getCurrPage() {return _currPage;};
void setCurrCategory(QString page) {_currPage = page;};
QString getCurrCategory() {return _currPage;};
void mouseMoveEvent(QMouseEvent *)
{
emit mouseMoved();
};
signals :
void mouseMoved();
private:
QString _menuDesc = 0;
QString _currPage;
QString _currCategory = 0;
};
Is there a solution to still catch the signal and pass it to the HTML page?
mouseMoveEvent is not a signal but an event handler. You can reimplement this event handler and let it emit a signal you can connect to if you need that.
Like this:
MyWebView::mouseMoveEvent(QMouseEvent * e) {
emit mouseMoved(); // this would be signal you could connect to.
}
Seems you misunderstand event handler and signal usages.
mouseMoveEvent is a member method of QWidget, is not a signal so you cannot connect to it. You can override it in you subclass and emit your own signal.
And if a QWidget's mouse tracking is switched off, mouse move events only occur if a mouse button is pressed while the mouse is being moved. Maybe you need to call setMouseTracking too.

Paint over top of label, not behind it in Qt

I am creating a simple gauge in Qt 4.7.4, and everything is working wonderfully. Except for the fact that, for the life of me, I cannot get the dial shape to paint over the text labels when it passes over them. It always paints it behind the label. I am just using a simple drawpolygon() method.
I'm thinking this has something to do about paint events? I am drawing everything inside a QFrame inside a MainWindow. I am using QFrame's paintEvent.
Edit:
The QLabels are created on start up with new QLabel(this). They are only created once, and never touched again ( Similar to manually adding them on the Ui with Designer). The drawpolygon() is in the QFrame's Paint event.
"myclass.h"
class gauge : public QFrame
{
Q_OBJECT
public:
explicit gauge(QWidget *parent = 0);
~gauge();
void setValues(int req, int Limit, bool extra=false);
private:
void drawDial();
protected:
void paintEvent(QPaintEvent *e);
};
"myclass.cpp"
void gauge::paintEvent(QPaintEvent *e)
{
Q_UNUSED(e);
drawDial();
return;
}
void gauge::drawDial()
{
QPainter Needle(this);
Needle.save();
Needle.setRenderHint(Needle.Antialiasing, true); // Needle was Staggered looking, This will make it smooth
Needle.translate(centrePt); // Center of Widget
Needle.drawEllipse(QPoint(0,0),10,10);
Needle.restore();
Needle.end();
}
If the gauge widget and the QLabels are siblings, then you can move the gauge widget to the front by calling its raise() method.
If the QLabels are children of the gauge widget, on the other hand, then they will always display in front of it. In that case you can either reorganize your widget hierarchy so that they are siblings instead, or you can get rid of the QLabels and simply call drawText() from your paintEvent() method instead (after drawDial() returns)

Propagate events to both QGraphicsView and QGraphicsScene

I have a Qt app with a QGraphicsView and QGraphicsScene. I subclassed them both and want to handle mouseevents in both. I can do this for both classes separately, using
virtual void mousePressEvent(QMouseEvent* event);
But when I handle the events in the GraphicsView, I don't receive them anymore in the GraphicsScene. How do I fix this, i.e. pass the event from the grapchicsview to the graphicsscene?
Just forward mousePressEvent to your GraphicsView's parent, this will then call scene's mousePressEvent :
void MyGraphicsView::mousePressEvent(QMouseEvent * e)
{
// forward to scene (via default view behaviour)
QGraphicsView::mousePressEvent(e) ;
// ...
}
BTW, QGraphicsScene::mousePressEvent has a different kind (class) of event : QGraphicsSceneMouseEvent
Call the base implementation at the end of your overriden function, eg:
void MyView::mousePressEvent(QMouseEvent* event)
{
// do something
QGraphicsView::mousePressEvent(event);
}

problem with QMouseEvent in QRect

OS::win_xp_sp3
Qt::4.6
Is it possible to use QMouseEvent inside QRect?
I have parent widget and inside is some QLabel with text "status unchanged".
Also , inside parent widget is MyRect which is derived from QRect.
Now I want to MouseEvent act only inside this MyRect. For example , if I act on MyRect , text in parent widget need to be changed.
For example:
class MyRect : public QRect {
public:
MyRect(int x, int y, int w, int h, ParentWidget* parent)
: QRect(x,y,w,h)
{
itsParent = parent;
}
~MyRect() {}
protected:
void mouseMoveEvent(QMouseEvent* event)
private:
ParentWidget* itsParent
};
void MyRect::mouseMoveEvent(QMouseEvent* event)
{
if(event->buttons() == Qt::LeftButton)
{
itsparent->label->setText("status changed");
}
}
nothing happens
question:: is it possible to use QMouseEvent like this (only on QRect)?
A QRect is neither a QObject nor a QWidget, so it doesn't receive events.
It's just four numbers describing a rectangle (and it doesn't make sense to derive from it).
You can check if a point is the given rect in the mouse event handler of your widget. Like:
void MyLabel::mouseMoveEvent( QMouseEvent* e ) {
if ( !rect.contains( e->pos() ) )
return;
//... handle mouse move
}
An alternative to subclassing is using an event filter.
is it possible to use QMouseEvent like this (only on QRect)?
No, at least not how you do it. QRect is not a QWidget and therefore doesn't have any mouseEvent handlers and such. It is just an entity with four coordinates.
You can do what you want by adding a handler to a real QWidget (either by subclassing, or using installEventFilter) and in the handler check for clicking in your rectangle using QRect::contains(QPoint).