I wants to hide a QLabel widget when the mouse is released on it. Everything works fine, except that the leaveEvent is not called when I call QLabel::hide(), inside mouseReleaseEvent.
The method is called properly when I leave the label normally (while it is shown), but not when I call the hide() method. I tried to call hide() outside the mouseReleaseEvent (using a QTimer), but leaveEvent is still not called.
The result is that when I display the label again, enterEvent is not called the first time the mouse enter the widget, and I have to move outside (to call leaveEvent), and then inside again.
So my question is why leaveEvent is not called when I hide the label (the mouse is still over the widget), and is there a way to force the call of leaveEvent whenever I want.
I hope my explanations are not too confused. Thanks.
Edit:
Here is a simple example that doesn't work for me:
struct Label : public QLabel
{
Label(QGraphicsScene *scene)
{
item.setWidget(this);
setText("Text");
scene->addItem(&item);
setMinimumWidth(200);
setMinimumHeight(200);
show();
}
~Label()
{
item.setWidget(NULL);
}
void mousePressEvent(QMouseEvent *)
{
}
void mouseReleaseEvent(QMouseEvent *)
{
std::cout << "mouseReleaseEvent" << std::endl;
hide();
}
void enterEvent(QEvent *)
{
std::cout << "Enter" << std::endl;
}
void leaveEvent(QEvent *)
{
std::cout << "Leave" << std::endl;
}
QGraphicsProxyWidget item;
};
Related
Ok, so I implemented the function following function:
CommandInput is a class which inherits the class QComboBox.
void CommandInput::dragEnterEvent(QDragEnterEvent *event)
{
qDebug() << "Proposed drop " << event->mimeData()->formats();
event->acceptProposedAction();
}
and it is working fine.
But the problem is my following function is not working , in fact when I click mouse button, nothing gets printed, Why is that?
void CommandInput::mousePressEvent(QMouseEvent *e)
{
qDebug()<<"X IS"<<e->pos().x();
}
I grabGesture()ed one of my buttons:
buttons[0]->grabGesture(Qt::TapAndHoldGesture);
in the constructor, and declared:
bool event(QEvent *event);
in protected slots, and implemented it like this:
bool MyClass::event(QEvent *event)
{
if (event->type() == QEvent::Gesture){
QGestureEvent *gestevent = static_cast<QGestureEvent *>(event);
if (QGesture *gest = gestevent->gesture(Qt::TapAndHoldGesture)){
QTapAndHoldGesture *tapgest = static_cast<QTapAndHoldGesture *>(gestevent->gesture(Qt::TapAndHoldGesture));
cout << "grabbed a gesture event" << endl;
}
return true;
}
cout << "not a gesture event" << endl;
return QWidget::event(event);
}
and I keep getting "not a gesture event" printed to screen however I press (normal press / long press / ... )
What I'm trying to do is a long key press (from the keyboard)
It's said in the Qt Documentation:
A gesture could be a particular movement of a mouse, a touch screen
action, or a series of events from some other source. The nature of
the input, the interpretation of the gesture and the action taken are
the choice of the developer.
So I suppose also a keyboard can trigger QGesture events.
If the class handling the grap (MyClass) event is not the class where the gesture is detected on (QPushButton assuming buttons[0] is a QPushButton), then you need and event filter:
buttons[0]->grabGesture(Qt::TapAndHoldGesture);
buttons[0]->installEventFilter( myClass ); // myClass being a MyClass instance
Now, myClass object will be forwarded all events from buttons[0], this is done using QObject::eventFilter virtual function:
bool MyClass::eventFilter(QObject *obj, QEvent *event)
{
if ( event->type() == QEvent::Gesture && obj == buttons[0] )
{
QGestureEvent *gestevent = static_cast<QGestureEvent *>(event);
if (QGesture *gest = gestevent->gesture(Qt::TapAndHoldGesture)){
QTapAndHoldGesture *tapgest = static_cast<QTapAndHoldGesture *>(gestevent->gesture(Qt::TapAndHoldGesture));
cout << "grabbed a gesture event" << endl;
return true;
}
}
// standard event processing
return Parent::eventFilter(obj, event); // Parent being MyClass parent type, maybe QDialog or QWidget
}
To warn before closing a window that inherits from QMainWindow, I reimplemented its closeEvent, which works fine when I emit close() manually. However, clicking the "x" button does not trigger this; it just exits.
It does emit aboutToQuit() for the application, which I can use to "recover" the window after it already closes. But I want to the warning to precede the initial closing.
I'm not sure where the issue is. The window is top-level and there are no running threads. Have I misunderstood what signal is actually connected to the button click...? It is close(), right?
In your mainwindow class header( the closeEvent must be virtual ):
public:
/*!
* \brief closeEvent
* \param event
*/
virtual void closeEvent ( QCloseEvent * event );
Then in the cpp
void MainWindow::closeEvent( QCloseEvent *event )
{
//! Ignore the event by default.. otherwise the window will be closed always.
event->ignore();
if(!EntitiesSaverObserver::Instance()->isAllSaved())
{
QMessageBox msgBox;
msgBox.setWindowIcon(QIcon(":/Resources/Icons/warning.png"));
msgBox.setIconPixmap(QPixmap(":/Resources/Icons/warning.png"));
QString strToShow = QString("Some Entities has been created or modified...");
msgBox.setText(strToShow);
msgBox.setInformativeText("Do you want to save your changes?");
msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
msgBox.setDefaultButton(QMessageBox::Save);
int ret = msgBox.exec();
switch (ret) {
case QMessageBox::Save:
{
// Save was clicked
qDebug() << "SAVE";
//! Do your stuff here
// ....
event->accept();
break;
}
case QMessageBox::Discard:
{
// Don't Save was clicked
qDebug() << "DISCARD";
event->accept();
break;
}
case QMessageBox::Cancel:
{
// Cancel was clicked
qDebug() << "CANCEL";
break;
}
default:
// should never be reached
break;
}
} else {
event->accept(); // Do not need to save nothing... accept the event and close the app
}
}
Moreover, if you want to put a button in your toolbar as a QAction, you could connect the signal and then:
void MainWindow::on_actionExit_triggered()
{
close();
}
This would call the close event of your main window. I hope this helps you.
just create a signal-slot QObject::connect(yourButton, SIGNAL(clicked()), this, SLOT(close()));
I am using VTK and Qt, and I need to know, when which mouse-button is pressed or released.
That for I created a new class, which inherits QObject and vtkInteractorStyleTrackballCamera:
class CModelMouseInteractorStyle :
public vtkInteractorStyleTrackballCamera,
public QObject
{
public:
CModelMouseInteractorStyle();
virtual void OnLeftButtonDown()
{
std::cout << "Pressed left mouse button." << std::endl;
// Forward events
vtkInteractorStyleTrackballCamera::OnLeftButtonDown();
// emit signal
emit leftButtonDown();
}
virtual void OnLeftButtonUp()
{
std::cout << "Released left mouse button." << std::endl;
// Forward events
vtkInteractorStyleTrackballCamera::OnLeftButtonUp();
// emit signal
emit leftButtonUp();
}
// I have similar functions for right and middle mouse-button
...
signals:
void leftButtonDown();
void leftButtonUp();
// and similar signals, too
...
};
I get the right couts whenever a button is pressed/released and I can interact with my scene as I want to, but only as long as I don't emit any signals.
As soon as I emit a signal in on of the functions, I get a symbol lookup error and the whole program crashes.
Am I doing something wrong? Do I have forgotten any thing?
I am using Qt4.7.4 and Vtk5.8.
I've seen similar questions but no answers that fit what I need. I want an invisible widget that lives on top of my whole application (no problems here). I want this widget to catch events so that I can print stuff about them, record them, whatever. I currently have an event filter hooked up that does this just fine. Then I want it to let the event go through to whatever is behind the widget. So for instance, if I try to push a button, the invisible widget should notice that a press happened on that spot, and then the button should actually be pressed. Can this be done in a simple way, or am I going to have to write code to simulate all the events beneath the invisible widget?
From all the information you disclosed in the comments, I suggest you filter the event as previously discussed, and then use QCoreApplication::sendEvent to forward the desired events to the invisible widget. It will then propagate the event accordingly to its children.
EDIT: OK, here is quick example that includes a QObject based event filter, that will filter the events for a widget, if the event is mouse event, it will be left for the widget to handle and print the output, if the event is a key event, it will be filtered and not forwarded back to the widget:
The event filter class:
class EventInfo : public QObject {
Q_OBJECT
public:
explicit EventInfo(QObject *parent = 0) : QObject(parent) {}
bool eventFilter(QObject *, QEvent *e) {
if (e->type() == QEvent::MouseButtonRelease){
qDebug() << "click event not filtered";
return false;
}
if (e->type() == QEvent::KeyRelease) {
QKeyEvent *event = static_cast<QKeyEvent *>(e);
if (event) qDebug() << "key" << event->key() << "filtered";
return true;
}
return false;
}
};
The widget:
class Widget : public QWidget {
Q_OBJECT
public:
Widget(QWidget *parent = 0) : QWidget(parent) {}
protected:
void mouseReleaseEvent(QMouseEvent *e) {
qDebug() << "widget clicked at position" << e->pos();
}
void keyReleaseEvent(QKeyEvent *e) {
qDebug() << "pressed key" << e->key();
}
};
main.cpp:
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
Widget w;
EventInfo info;
w.installEventFilter(&info);
w.show();
return a.exec();
}
Testing output to show that keyboard events are filtered and mouse press events are forwarded to the widget:
click event not filtered
widget clicked at position QPoint(352,230)
key 70 filtered
click event not filtered
widget clicked at position QPoint(405,163)
key 87 filtered