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();
}
Related
I have created following dialog using QT designer form class
#ifndef DLG_GAMMA_H
#define DLG_GAMMA_H
#include <QDialog>
namespace Ui {
class Dlg_Gamma;
}
class Dlg_Gamma : public QDialog
{
Q_OBJECT
public:
explicit Dlg_Gamma(QWidget *parent = nullptr);
~Dlg_Gamma() override;
private slots:
void on_horizontalSlider_valueChanged(int value);
void on_saveButton_clicked();
void on_discardButton_clicked();
void on_resetButton_clicked();
signals:
void savechanges(QString filter);
void discardchanges();
void reset();
private:
Ui::Dlg_Gamma *ui;
bool eventFilter(QObject *target, QEvent *event) override;
void closeEvent(QCloseEvent *dlg) override;
bool close_X;
};
#endif // DLG_GAMMA_H
.cpp
bool Dlg_Gamma::eventFilter(QObject *target, QEvent *event)
{
qDebug() << event->type();
}
However, clicking on help button, does not trigger any event.
Has anybody faced this issue before ?
Does anybody know solution ?
bool MyDialog::event(QEvent *e)
{
// reimplement event processing
if(e->type()==QEvent::WhatsThisClicked)
{
QWhatsThisClickedEvent ce = static_cast<QWhatsThisClickedEvent>(e);
....
return true;
}
return QDialog::event(e);
}
This is the event catcher.
To use event filter you need to install it:
installEventFilter(this) in the constructor of the Dialog.
You need to install eventFilter on your 'help button' when using eventFilter.
You need to insert kind of code below in the constructor of the 'Dlg_Gamma'
ui->helpButton->installEventFilter(this)
For more information, Please refer to the information below.
https://doc.qt.io/qt-5/eventsandfilters.html
Using Qt to create an application that accepts a file drop. I have an area on my UI that I want to drop the file into, using a Qlabel. I have the function of dragging and dropping the file into the UI working, however I can drop it anywhere on the window, and not just into the Qlabel area.
I thought using
ui->label_drag->setAcceptDrops(true);
would work, however this just removed the functionality all together. What is the best way of handling this? if possible at all.
Thanks
The best way to do this is to override the QLabel class. In the dragEnterEvent be sure to call acceptProposedAction to process the move and leave events. If you don't do that, only the dragEnter event will fire.
Sample code follows. To use this in your project, add the source to your project and then right click on the label on the form and promote the item to QLabelDragDrop.
#ifndef QLABELDRAGDROP_H
#define QLABELDRAGDROP_H
#include <QLabel>
class QLabelDragDrop : public QLabel
{
Q_OBJECT
public:
explicit QLabelDragDrop(QWidget *parent = nullptr);
protected:
void dragEnterEvent(QDragEnterEvent *event);
void dragLeaveEvent(QDragLeaveEvent *event);
void dragMoveEvent(QDragMoveEvent *event);
signals:
public slots:
};
#endif // QLABELDRAGDROP_H
#include "qlabeldragdrop.h"
#include <QDebug>
#include <QDragEnterEvent>
#include <QDropEvent>
QLabelDragDrop::QLabelDragDrop(QWidget *parent) : QLabel(parent)
{
setAcceptDrops(true);
setMouseTracking(true);
}
void QLabelDragDrop::dragEnterEvent(QDragEnterEvent *event)
{
qDebug() << "dragEnterEvent";
event->acceptProposedAction();
}
void QLabelDragDrop::dragLeaveEvent(QDragLeaveEvent *event)
{
qDebug() << "dragLeaveEvent";
releaseMouse();
}
void QLabelDragDrop::dragMoveEvent(QDragMoveEvent *event)
{
qDebug() << "dragMoveEvent";
}
void QLabelDragDrop::dropEvent(QDropEvent *event)
{
qDebug() << "dropEvent";
}
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 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.
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);
}
}