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
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 need to call a method after the ui has been shown,so i want to connect
the frame with itself,in particular using the show signal.
I've created a new form with auto generated code by qtcreator.This is the auto generated header.
#define STARTWINDOW_H
#include <QMainWindow>
namespace Ui {
class StartWindow;
}
class StartWindow : public QMainWindow
{
Q_OBJECT
public:
explicit StartWindow(QWidget *parent = 0);
~StartWindow();
private:
Ui::StartWindow *ui;
public slots:
void doSomething();
};
#endif // STARTWINDOW_H
in the cpp file no one of the following codes work
connect(ui,SIGNAL(QEvent::Show),this,SLOT(doSomething()));
connect(*ui,SIGNAL(QEvent::Show),this,SLOT(doSomething()));
connect(this->ui,SIGNAL(QEvent::Show),this,SLOT(doSomething()));
What's the right way to do it?
That signal does not exist by default, we must create it, we can override the showEvent() method:
.h
protected:
void showEvent(QShowEvent *event);
signals:
void showSignal();
.cpp
connect(this, &StartWindow::showSignal, this, &StartWindow::doSomething);
void StartWindow::showEvent(QShowEvent *event)
{
emit showSignal();
QMainWindow::showEvent(event);
}
void StartWindow::doSomething()
{
qDebug()<<"show";
}
Or you can override the eventFilter method.
.h
protected:
bool eventFilter(QObject *watched, QEvent *event);
signals:
void showSignal();
.cpp
installEventFilter(this);
connect(this, &StartWindow::showSignal, this, &StartWindow::doSomething);
bool StartWindow::eventFilter(QObject *watched, QEvent *event)
{
if(watched==this && event->type() == QEvent::Show)
emit showSignal();
return QMainWindow::eventFilter(watched, event);
}
There are a few things wrong here:
There is no show() signal and
Even if there were, you aren't using connect correctly.
First, if your class were defined like this:
namespace Ui { class MainWindow; }
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
signals:
void someSignal();
public slots:
void doSomething() {}
private:
Ui::MainWindow *ui;
};
The appropriate call to connect in the constructor would be:
QWidget::connect(this, SIGNAL(someSignal()), this, SLOT(doSomething()));
Even if there were a show signal, you wouldn't get it from ui, you would get it from this. The UI classes are just dumb containers for widgets that you add through the designer.
To perform some action when your class is shown, you can either override
virtual void showEvent(QShowEvent *); (more robust, but slightly more complex)
or simply define your own show() slot that does what you want and calls QWidget::show() at the end of it. I prefer the latter, so I will show you that.
Start by defining your show slot like this:
namespace Ui { class MainWindow; }
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
void doSomething() {}
void show();
private:
Ui::MainWindow *ui;
};
Then, in your implementation file, do this:
void MainWindow::show()
{
doSomething();
QWidget::show();
}
I have worked with the Qt framework for quite some time now, and I have never needed to override the show event; it is simply not worth it for most use cases. If you really want a show signal that others can connect to, just add a custom signal for it and emit in in MainWindow::show(). Only resort to overriding event handlers if you can't make this work for what you are doing(very rarely necessary).
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);
}
}