Using the mdi example I added mouse events to mainwindow as:
protected:
I can receive right and middle button down but no left button or mouse move or button up events.
Help please.
void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
void MainWindow::mousePressEvent(QMouseEvent *event)
{
printf("mouse down\n");
fflush(stdout);
}
void MainWindow::mouseMoveEvent(QMouseEvent *event)
{
printf("mouse\n");
fflush(stdout);
}
void MainWindow::mouseReleaseEvent(QMouseEvent *event)
{
printf("mouse up\n");
fflush(stdout);``
}
Related
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.
OK, this should be easy.
I tried to handle drop event onto a QGraphicsView widget. Incoming data dragged from a QTreeView widget. For that, I re-implemented these methods:
void QGraphicsScene::dragEnterEvent(QGraphicsSceneDragDropEvent *event)
{
event.accept();
}
void QGraphicsScene::dragMoveEvent(QGraphicsSceneDragDropEvent *event)
{
event.accept();
}
void QGraphicsScene::dropEvent(QGraphicsSceneDragDropEvent *event)
{
event.accept();
}
void QGraphicsView::dropEvent(QDropEvent *event)
{
QPixmap pixmap(event->mimedata()->urls()[0].toString().remove(0,8));
this.scene()->addPixmap(pixmap);
}
This works fine; but how can I change another graphicsview scene within this widget's drop event? That is:
void QGraphicsView::dropEvent(QDropEvent *event)
{
QPixmap pixmap(event->mimedata()->urls()[0].toString().remove(0,8));
// I cannot access ui; and cannot access my widgets...:
ui->anotherview->scene()->addPixmap(pixmap);
}
What about making a custom signal in your QGraphicsView like void showPixmap(QPixmap p) and connecting it to a slot in your main gui class where you can access ui elements. You can then call emit showPixamp(pixmap) in the dropEvent.
Subclassing QGraphicsView
//header file
class CustomView : public QGraphicsView
{
public:
CustomView(QGraphicsScene*, QWidget*=NULL);
~CustomView();
signals:
void showPixmap(QPixmap p);
protected:
virtual void dropEvent(QDropEvent *event);
};
//cpp file
CustomView::CustomView(QGraphicsScene *scene, QWidget* parent)
:QGraphicsView(scene, parent)
{
//if you need to initialize variables, etc.
}
void CustomView::dropEvent(QDropEvent *event)
{
//handle the drop event
QPixmap mPixmap;
emit showPixmap(mPixmap);
}
Using event filters in your main GUI class
void GUI::GUI()
{
ui->mGraphicsView->installEventFilter(this);
}
bool GUI::eventFilter(QObject *object, QEvent *event)
{
if (object == ui->mGraphicsView && event->type() == QEvent::DropEnter) {
QDropEvent *dropEvent = static_cast<QDropEvent*>(event);
//handle the drop event
return true;
}
else
return false;
}
I'm using Qt Creator to create a gui for a mineseeper game.
How can I know a QpushButton clicked with rightclick? for flag in the game.
In other word, which signal used for rightclick?
Create your own button with filter at mousePressEvent slot.
qrightclickbutton.h
#ifndef QRIGHTCLICKBUTTON_H
#define QRIGHTCLICKBUTTON_H
#include <QPushButton>
#include <QMouseEvent>
class QRightClickButton : public QPushButton
{
Q_OBJECT
public:
explicit QRightClickButton(QWidget *parent = 0);
private slots:
void mousePressEvent(QMouseEvent *e);
signals:
void rightClicked();
public slots:
};
#endif // QRIGHTCLICKBUTTON_H
qrightclickbutton.cpp
#include "qrightclickbutton.h"
QRightClickButton::QRightClickButton(QWidget *parent) :
QPushButton(parent)
{
}
void QRightClickButton::mousePressEvent(QMouseEvent *e)
{
if(e->button()==Qt::RightButton)
emit rightClicked();
}
Now connect like this
QRightClickButton *button = new QRightClickButton(this);
ui->gridLayout->addWidget(button);
connect(button, SIGNAL(rightClicked()), this, SLOT(onRightClicked()));
Create a slot in MainWindow.cpp.
void MainWindow::onRightClicked()
{
qDebug() << "User right clicked me";
}
It works for me!
I think QPushButton is internally implemented to listen to left mouse clicks only. But you can easily extend QPushButton and re-implement let's say the mouse release event and do your thing if the right mouse button was pressed, e.g. emit a custom rightClicked() signal for example:
signals:
void rightClicked();
protected:
void mouseReleaseEvent(QMouseEvent *e) {
if (e->button() == Qt::RightButton) emit rightClicked();
else if (e->button() == Qt::LeftButton) emit clicked();
}
... or you can create an overload of the clicked signal that forwards the mouseEvent pointer so you can do the same check outside of the button.
signals:
void clicked(QMouseEvent *);
protected:
void mouseReleaseEvent(QMouseEvent *e) {
emit clicked(e);
}
Then you do the check in the slot you connect the button's clicked(QMouseEvent *) signal to and proceed accordingly.
I just wrote this little helper adapter to make any existing button right-clickable with no need to subclass it:
class CRightClickEnabler : public QObject
{
public:
CRightClickEnabler(QAbstractButton * button): QObject(button), _button(button) {
button->installEventFilter(this);
};
protected:
inline bool eventFilter(QObject *watched, QEvent *event) override {
if (event->type() == QEvent::MouseButtonPress)
{
auto mouseEvent = (QMouseEvent*)event;
if (mouseEvent->button() == Qt::RightButton)
_button->click();
}
return false;
}
private:
QAbstractButton* _button;
};
Usage:
connect(ui->pushButton, &QPushButton::clicked, [](){qDebug() << "Button clicked";});
new CRightClickEnabler(ui->pushButton);
From now on, the clicked signal will be triggered by the right click as well as left click. There's no need to delete this object - it uses ui->pushButton as parent and will be auto-deleted by Qt when the parent is destroyed.
Obviously, you can write 2 lines of code (literally) to declare a new signal here and emit that signal upon right click instead of clicked, if desired.
I'd like to suggest this option as well, without need for event filter/other stuffs...
self.button.released.connect(self.doStuff)
self.button.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
self.button.customContextMenuRequested.connect(partial(self.doStuff, False))
def doStuff(self,state=True,p=QPoint()):
print("True for left, False for right!",state)
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();
}
In my program I override the dragEnterEvent but it never called, So that I want to know about when it's called?
UPDATE
Here the code
class RealBoard:public QGraphicsScene
{
public:
RealBoard();
void dragEnterEvent(QGraphicsSceneDragDropEvent *event);
void dragLeaveEvent(QGraphicsSceneDragDropEvent *event);
//void dragMoveEvent(QGraphicsSceneDragDropEvent *event);
// void mousePressEvent(QGraphicsSceneMouseEvent *event);
};
RealBoard::RealBoard():QGraphicsScene()
{
setSceneRect(-10,-10,620,620);
}
void RealBoard::dragEnterEvent(QGraphicsSceneDragDropEvent *event)
{
exit(0);
// addItem(temp);
}
void RealBoard::dragLeaveEvent(QGraphicsSceneDragDropEvent *event)
{
/*
QGraphicsScene::dragLeaveEvent(event);
tempCoin->setZValue(0);
delete temp;
temp=NULL;
*/
exit(0);
}
/*
void RealBoard::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
QGraphicsScene::mousePressEvent(event);
QPointF click=event->buttonDownScenePos(Qt::LeftButton);
if(itemAt(click)!=boardP)
{
itemAt(click)->setZValue(1);
tempCoin=dynamic_cast<QGraphicsPixmapItem *>(itemAt(click));
// exit(0);
temp=new QGraphicsPixmapItem((static_cast<QGraphicsPixmapItem *>(itemAt(click))->pixmap()));
temp->setPos(itemAt(click)->pos());
temp->setZValue(0);
addItem(temp);
update(temp->pos().x(),temp->pos().y(),75,75);
}
}
*/
For me the problem is that you have not accepted drops.
I'm not sure if QGraphicsScene() accepts drops but you should do it in your constructor.
So call setAcceptDrops(true) and dragEnterEvent handler will be called.
From Qt 4.5.3 documentation,
The QDragEnterEvent class provides an event which is sent to a widget when a drag and drop action enters it. More about QDragEnterEvent here