I have read this How to distinguish between mouseReleaseEvent and mousedoubleClickEvent on QGrapnhicsScene and this Distinguish between single and double click events in Qt in order to solve my problem. But they do not work. I created a class QLabel:
mouselabel.h
#ifndef MOUSELABEL_H
#define MOUSELABEL_H
#include <QLabel>
#include <QMouseEvent>
#include <QEvent>
#include <QDebug>
class MouseLabel : public QLabel
{
Q_OBJECT
public:
explicit MouseLabel(QWidget *parent = 0);
void mouseMoveEvent(QMouseEvent *event);
void mousePressEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
void mouseDoubleClickEvent(QMouseEvent *event);
void leaveEvent(QMouseEvent *);
int x, y;
signals:
void Mouse_Pressed();
void Mouse_Position();
void Mouse_Left();
void Mouse_Release();
void Mouse_DoubleClick();
public slots:
};
#endif // MOUSELABEL_H
mouselabel.cpp
#include "mouselabel.h"
MouseLabel::MouseLabel(QWidget *parent) :
QLabel(parent)
{
}
void MouseLabel::mouseMoveEvent(QMouseEvent *event) {
this->x = event->x();
this->y = event->y();
emit Mouse_Position();
}
void MouseLabel::mousePressEvent(QMouseEvent *event)
{
emit Mouse_Pressed();
}
void MouseLabel::mouseReleaseEvent(QMouseEvent *event)
{
emit Mouse_Release();
}
void MouseLabel::mouseDoubleClickEvent(QMouseEvent *event)
{
emit Mouse_DoubleClick();
}
void MouseLabel::leaveEvent(QMouseEvent *)
{
emit Mouse_Left();
}
As described in the two links, in order to distinguish between a click and a double click, I created a timer and it starts when a mouserelease event happens and it stops when there is a double click mouse. But, this does not work. Can you help me to solve the problem?
The lightest possible solution is using a QBasicTimer, just have those 2 methods overloaded and the timer in your widget:
void mouseReleaseEvent(QMouseEvent *) {
if (timer.isActive()) {
timer.stop();
qDebug() << "double click";
}
else {
timer.start(300, this);
}
}
void timerEvent(QTimerEvent *) {
timer.stop();
qDebug() << "single click";
}
QBasicTimer timer;
The downside is a timer approach delays the single click, which is kind of annoying, but you could mask that, for example for selecting objects, using the mousePressEvent for immediate response.
Related
A widget derived from QListWidget is the only widget on a window. Function "setAcceptDrops(true);" is used in its constructor, and "event->accept();" is called in its "dragEnterEvent". However, its "dropEvent" could not be triggered. Please check the whole source code (created using Qt 5.12.0) at
github.com/jianz-github/dropevent.
I have asked a question at Qt Drop event not firing. This situation is supposed to be the same, but it is not. Weird.
Thanks in advance for any help.
In this case, the solution is to overwrite the dragMoveEvent() method as well.
listbox.h
#ifndef LISTBOX_H
#define LISTBOX_H
#include <QListWidget>
#include <QDropEvent>
#include <QDragEnterEvent>
class ListBox : public QListWidget
{
public:
ListBox(QWidget *parent = nullptr);
protected:
void dropEvent(QDropEvent *event) override;
void dragEnterEvent(QDragEnterEvent *event) override;
void dragMoveEvent(QDragMoveEvent *event) override;
};
#endif // LISTBOX_H
listbox.cpp
#include "listbox.h"
#include <QDebug>
ListBox::ListBox(QWidget *parent) : QListWidget (parent)
{
setAcceptDrops(true);
}
void ListBox::dropEvent(QDropEvent *event)
{
qDebug() << "dropEvent"<<event;
}
void ListBox::dragEnterEvent(QDragEnterEvent *event)
{
event->acceptProposedAction();
}
void ListBox::dragMoveEvent(QDragMoveEvent *event)
{
event->acceptProposedAction();
}
I would like to emit a signal when hovering a QLabel with the mouse in QT.
Is it possible ?
If not, how can I do it ?
Thanks.
You can do hover handling without subclassing of QLabel. Try next code sample for it:
void LabelHoverHandler::attach(QLabel *label)
{
label->setAttribute(Qt::WA_Hover, true);
label->installEventFilter(this);
}
bool LabelHoverHandler::eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::HoverEnter)
{
emit signalMouseHover(dynamic_cast<QLabel*>(obj) );
qDebug() << "HoverEnter";
}
return false;
}
LabelHoverHandler header file:
class LabelHoverHandler : public QObject
{
Q_OBJECT
public:
LabelHoverHandler(QObject *parent);
virtual ~LabelHoverHandler() {};
void attach(QLabel *label);
protected:
bool eventFilter(QObject *obj, QEvent *event);
signals:
void signalMouseHover(QLabel*);
};
Simply create an instance of LabelHoverHandler and call method attach() with a needed label as a parameter.
A possible implementation:
// mylabel.h
#ifndef MYLABEL_H
#define MYLABEL_H
#include <QLabel>
class MyLabel : public QLabel
{
Q_OBJECT
public:
MyLabel();
~MyLabel();
protected:
virtual void enterEvent(QEvent *ev);
virtual void leaveEvent(QEvent *ev);
private:
bool hover;
};
#endif // MYLABEL_H
and:
// mylabel.cpp
#include "mylabel.h"
#include <QEvent>
MyLabel::MyLabel()
{
hover = false;
setAttribute(Qt::WA_Hover, true);
}
MyLabel::~MyLabel()
{
}
void MyLabel::enterEvent(QEvent *ev)
{
if (!hover){
hover = true;
setText("Send signal here");
}
QLabel::enterEvent(ev);
}
void MyLabel::leaveEvent(QEvent *ev)
{
if (hover){
hover = false;
setText("Mouse leave area");
}
QLabel::leaveEvent(ev);
}
I got simple class MyStackedWidget but looks like it doesn't fires drag and drop events - what am I doing wrong?
#ifndef MYSTACKEDWIDGET_H
#define MYSTACKEDWIDGET_H
#include <QStackedWidget>
class MyStackedWidget : public QStackedWidget
{
Q_OBJECT
public:
MyStackedWidget();
signals:
void dragEnterSignal(QDragEnterEvent *event);
void dropSignal(QDropEvent *event);
void dragMoveSignal(QDragMoveEvent *event);
void dragLeaveSignal(QDragLeaveEvent *event);
public slots:
void dragEnterEvent(QDragEnterEvent *event);
void dropEvent(QDropEvent *event);
void dragMoveEvent(QDragMoveEvent *event);
void dragLeaveEvent(QDragLeaveEvent *event);
};
#endif // MYSTACKEDWIDGET_H
#include "mystackedwidget.h"
#include <QMimeData>
#include <QDragEnterEvent>
MyStackedWidget::MyStackedWidget()
{
setMouseTracking(true);
}
void MyStackedWidget::dragEnterEvent(QDragEnterEvent *event)
{
const QMimeData *mimeData = event->mimeData();
if(mimeData->hasUrls() && mimeData->urls().size() == 1) {
event->acceptProposedAction();
}
emit dragEnterSignal(event);
}
void MyStackedWidget::dropEvent(QDropEvent *event)
{
emit dropSignal(event);
}
void MyStackedWidget::dragMoveEvent(QDragMoveEvent *event)
{
emit dragMoveSignal(event);
}
void MyStackedWidget::dragLeaveEvent(QDragLeaveEvent *event)
{
emit dragLeaveSignal(event);
}
I am implementing copy operation in graphicsView for different entities such as point, ellipse, circle etc. in qt but getting an error
error: invalid conversion from 'QGraphicsItem*' to 'QGraphicsItemGroup*
My code to copy operation in cadgraphicsview.cpp is:
void CadGraphicsScene::copy()
{
selectedItems.clear();
foreach(QGraphicsItemGroup *item, itemList){
QString str;
if (item->isSelected())
{
if(item->type() == Point::Type)
{
Point *pointItem = (Point *) item;
str = QString("Point %1 %2 ")
.arg(pointItem->scenePos().x())
.arg(pointItem->scenePos().y());
}
}
}
}
In cadgraphicsscene.h
#ifndef CADGRAPHICSSCENE_H
#define CADGRAPHICSSCENE_H
#include <QGraphicsScene>
#include <QXmlStreamWriter>
#include <QUndoStack>
#include <QLabel>
#include <QFrame>
#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 writeStream(QXmlStreamWriter *stream);
void readStream(QXmlStreamReader *stream);
public slots:
void setMode(Mode mode);
void selectItems();
void editorLostFocus(mText *item);
void cut();
void copy();
void paste();
void del();
protected:
void contentsContextMenuEvent(QContextMenuEvent *event);
void mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent);
void mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent);
void setFlags();
void areItemsSelectable(bool);
void dragEnterEvent(QDragEnterEvent *event);
void dropEvent(QDropEvent *event);
void mousePressEvent(QMouseEvent *event);
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;
private:
QAction *cutAct;
QAction *copyAct;
QAction *pasteAct;
};
#endif // CADGRAPHICSSCENE_H
Help me out to sought this :)
You define itemList as:
QList<QGraphicsItem *> itemList;
You are then trying to iterate it with:
foreach(QGraphicsItemGroup *item, itemList){
// ...
}
From the documentation you can see that QGraphicsItemGroup inherits from QGraphicsItem. So every QGraphicsItemGroup "is a" QGraphicsItem. But not every QGraphicsItem "is a" QGraphicsItemGroup.
If you want to iterate that itemList then item will have to be a QGraphicsItem, or itemList will have to be a QGraphicsItemGroup. It seems that since you are testing for specific classes then the former is probably what you want.
I was able to simulate the Right-Click event by subclassing the QTableWidget:
header file:
#ifndef QRIGHCLICKTABLE_H
#define QRIGHCLICKTABLE_H
#include <QTableWidget>
#include <QMouseEvent>
class QRightClickTable : public QTableWidget
{
Q_OBJECT
public:
explicit QRightClickTable(QWidget *parent = 0);
private slots:
void mousePressEvent(QMouseEvent *e);
signals:
void rightClicked();
public slots:
};
#endif // QRIGHCLICKTABLE_H
cpp file
QRightClickTable::QRightClickTable(QWidget *parent) :
QPushButton(parent)
{
}
void QRightClickTable::mousePressEvent(QMouseEvent *e)
{
if(e->button()==Qt::RightButton)
emit rightClicked();
}
QRightClickTable *button = new QRightClickTable(this);
ui->gridLayout->addWidget(button);
connect(button, SIGNAL(rightClicked()), this, SLOT(onRightClicked()));
void MainWindow::onRightClicked()
{
qDebug() << "User right clicked me";
}
Now, right-click works correctly, but there are other problems with QTableWidget: all other mouse events, such as the left click to select a cell, no longer work.
Can you help me? I know I need to call the base class implementation in my override of mousePressEvent, you could show me how with a little piece of code?
Change your event handler like this :
void QRightClickTable::mousePressEvent(QMouseEvent *e) {
if(e->button()==Qt::RightButton) {
emit rightClicked();
} else {
QTableWidget::mousePressEvent(e);
}
}