I'm kind of new to the Qt Framework and was trying to program a game and realised there is no signal for "rightclick()". I read through the documentation and found out I had to use the "QMouseEvent" class but I just can't figure out how it works.. Somebody help me.
Use Qt::MouseButtons QMouseEvent::buttons() const.
It returns, according to Qt documentation:
Returns the button state when the event was generated. The button state is a combination of Qt::LeftButton, Qt::RightButton, Qt::MidButton using the OR operator
So All you need to do is:
void mouseMoveEvent(QMouseEvent *e) {
if(e->buttons() == Qt::RightButton)
qDebug() << "The right button was clicked";
}
Related
I am using Qt but have run into a problem.
I want to register when the mouse is pressed and released on a QTableWidget. There are signals only for pressed, not released. Therefore I use mousePressEvent and mouseReleaseEvent instead.
MyWidget.h
protected:
void mousePressEvent(QMouseEvent * event);
void mouseReleaseEvent(QMouseEvent * event);
MyWidget.cpp
void MyWidget::mousePressEvent(QMouseEvent *event)
{
qDebug() << "Pressed";
}
void MyWidget::mouseReleaseEvent(QMouseEvent *event)
{
qDebug() << "Released";
}
It prints "Released" when the left, right or middle mouse button is released over the table. However, it prints "Pressed" only when the right or middle button is pressed.
What could be wrong? How can I register when the left button is pressed?
The cell widget probably consumes the mousePressEvent on the left mouse button, so you (the parent widget) are not receiving it.
In the documentation of QMouseEvent, it is said that:
A mouse event contains a special accept flag that indicates whether the receiver wants the event. You should call ignore() if the mouse event is not handled by your widget. A mouse event is propagated up the parent widget chain until a widget accepts it with accept(), or an event filter consumes it.
Because of that, we can suppose that probably the events you mentioned are consumed by some other actors.
It would help knowing who are those actors.
I found the solution (with help from the other answers):
There was a QFrame on top of the widget that consumed the event. I didn't think of that since it worked for the other buttons. It was solved by:
ui->frame->setAttribute(Qt::WA_TransparentForMouseEvents, true);
I’m newbie with Qt, and experiencing one problem I cannot deal with for, like, a month. The situation is like this:
I’ve OpenSceneGraph project (which is OpenGL) and trying to make Qt interface inside the 3d scene. I think its not necessary how I deal with that, but if someone wants to know more here is thread with more info on OSG forum (though I didnt get solution there). The problem is, when any key on keyboard is clicked, Qt controls jump around the screen and dont react on any (mouse or keyboard) events anymore. The entire program continues to work, though.
To summarize, my question is like: is there a way to make Qt widgets ignore all keypresses?
I’ve searched a lot, but couldnt find any working solution.
Thanks in advance!
Read a bit about events in Qt. There is a section about event filtering (but please don't jump straight to it :P).
SHORT ANSWER :
void Qwidget::setEnabled ( bool );
The drawback is that it disable also mouse events, change the widget style and that's a bummer.
LONG ANSWER : FILTER EVENTS
One possibility is to filter all events on the Qt application. I suppose the function which launch your Qt code looks like this (if different post here):
int main(int argc, char* argv[]){
QApplication app(argc, argv);
QWidget toplevelwidget1;
toplevelwidget1.show()
//stufff
return app.exec();
}
//doesnt have to exactly like this.
you can to set an event filter on app variable. It is the more elegant solution but it is too complicated because it filters native events and will require some work...
What you can do instead is filter only your top level widgets or windows (the one without parents). You define an event filter (which is a QObject) like :
class KeyboardFilter: public QObject
{
Q_OBJECT
...
protected:
bool eventFilter(QObject *obj, QEvent *event);
};
bool KeyboardFilter::eventFilter(QObject *obj, QEvent *event)
{
//for all events from keyboard, do nothing
if (event->type() == QEvent::KeyPress ||
event->type() == QEvent::KeyRelease ||
event->type() == QEvent::ShortcutOverride ||
) {
return true;
} else {
// for other, do as usual (standard event processing)
return QObject::eventFilter(obj, event);
}
}
Then you set the filter on the desired widgets using:
myDesiredWidgetorObject->installEventFilter(new KeyboardFilter(parent));
And that's it!
I would simply like to catch the mouseRelease event when a user drags an item from a QTableView and releases the left button.
I want to highlight possible dropping zones in my app, like changing the background of a widget.
I start by detecting the drag-start by re-implementing:
void LibraryTableView::startDrag( Qt::DropActions supportedActions )
{
m_dragReleased = false;
emit dragStart();
QTableView::startDrag(supportedActions);
}
and emitting my own signal.
Now that the dropzone has changed, I need to catch the release event to redraw the dropzone as before whether the drag and drop succeded or not !
I tried different models, reimplementing the 4 mouse events and eventFilter, but the Mouse Release Event is never catched.
Here is my code:
void LibraryTableView::mouseDoubleClickEvent( QMouseEvent* event )
{
QTableView::mouseDoubleClickEvent(event);
}
void LibraryTableView::mouseMoveEvent( QMouseEvent* event )
{
qDebug() << "move";
QTableView::mouseMoveEvent(event);
}
void LibraryTableView::mousePressEvent( QMouseEvent* event )
{
qDebug() << "press";
QTableView::mousePressEvent(event);
}
void LibraryTableView::mouseReleaseEvent( QMouseEvent* event )
{
qDebug() << "real"; // Never called when drag ends ...
QTableView::mouseReleaseEvent(event);
}
So, it is a bug ?
If you know a trick, it would help me a lot.
Thanks !
Edit: I cannot reimplement dropEvent for every widget in my application, if the user drags and drop an element in another application, I still want to catch the release event ...
As said above it's been 3 years but thank to the last answer I found an even easier solution for this problem.
void LibraryTableView::startDrag( Qt::DropActions supportedActions )
{
m_dragReleased = false;
emit dragStart();
QTableView::startDrag(supportedActions);
//CODE HERE WILL BE EXECUTED ONLY WHEN THE MOUSE BUTTON HAS
//BEEN RELEASED SO YOU CAN DO THE FOLLOWING
emit dragStop();
}
Three years since this question was asked and this Qt problem still exists in Qt 5.4. Lately I had the same problem: Drops outside the application and no MouseReleaseEvent. The solution is simple and not really a trick:
The mousePressEvent, which starts the drag&drop looks like this (simplified):
void DragNDropListView::mousePressEvent(QMouseEvent *event){
....
QDrag *drag = new QDrag(this);
QMimeData *mimeData = new QMimeData;
mimeData->setData("application/x-xxxxxx", QByteArray());
drag->setMimeData(mimeData);
drag->exec();
// The d&d ended here. Inside the widget where the drag
// started, a mouseReleaseEvent would have been fired.
// Outside this widget not.
// drag->mimeData() is here still available.
}
}
}
The trick is simple: drag->exec() starts its own event loop, which is exited when the mouse button is released. The mouse position after drag->exec(); can be determined with QCursor.
For QTableView you have to reimplement three function for dnd support:
void dragEnterEvent ( QDragEnterEvent * event ) - in this function the mouse enters the widget
void QAbstractItemView::dragMoveEvent ( QDragMoveEvent * event ) - in this function you can update your drop zone highlighting
void QAbstractItemView::dropEvent ( QDropEvent * event ) - in this function you decide whether to accept the event
I encountered a similar issue and was not happy to find out that the MouseReleaseEvent was not getting fired at the end of a drag.
I just used the DragLeaveEvent and toggled my variables off, as I would have done in the MouseReleaseEvent. If user dragged off the app, and then back on, those previously toggled off variables would get re-enabled in the DragMoveEvent (assuming it is accepted).
That was my trick, at least. Hope it helps.
In my program, I'd like to have mouseMoveEvent(QMouseEvent* event) called whenever the mouse moves (even when it's over another window).
Right now, in my mainwindow.cpp file, I have:
void MainWindow::mouseMoveEvent(QMouseEvent* event) {
qDebug() << QString::number(event->pos().x());
qDebug() << QString::number(event->pos().y());
}
But this seems to only be called when I click and drag the mouse while over the window of the program itself. I've tried calling
setMouseTracking(true);
in MainWindow's constructor, but this doesn't seem to do anything differently (mouseMoveEvent still is only called when I hold a mouse button down, regardless of where it is). What's the easiest way to track the mouse position globally?
You can use an event filter on the application.
Define and implement bool MainWindow::eventFilter(QObject*, QEvent*). For example
bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::MouseMove)
{
QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
statusBar()->showMessage(QString("Mouse move (%1,%2)").arg(mouseEvent->pos().x()).arg(mouseEvent->pos().y()));
}
return false;
}
Install the event filter when the MainWindows is constructed (or somewhere else). For example
MainWindow::MainWindow(...)
{
...
qApp->installEventFilter(this);
...
}
I had the same problem, further exacerbated by the fact that I was trying to call this->update() to repaint the window on a mouse move and nothing would happen.
You can avoid having to create the event filter by calling setMouseTracking(true) as #Kyberias noted. However, this must be done on the viewport, not your main window itself. (Same goes for update).
So in your constructor you can add a line this->viewport()->setMouseTracking(true) and then override mouseMoveEvent rather than creating this filter and installing it.
In Qt, when a widget receives focus, how can get a notification about it, so I can execute some custom code? Is there a signal or an event for that?
You can add en event filter.
This is an example of an application written with QtCreator. This form has a QComboBox named combobox.
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->comboBox->installEventFilter(this);
.
.
.
}
bool MainWindow::eventFilter(QObject *object, QEvent *event)
{
if (event->type() == QEvent::FocusOut)
{
if (object == ui->comboBox)
{
qWarning(object->objectName().toLatin1().data());
}
}
return false;
}
There is a "focusChanged" signal sent when the focus changes, introduced in Qt 4.1.
It has two arguments, he widget losing focus and the one gaining focus:
void QApplication::focusChanged(QWidget * old, QWidget * now)
Qt Designer isn't designed for this level of WYSIWYG programming.
Do it in C++:
class LineEdit : public QLineEdit
{
virtual void focusInEvent( QFocusEvent* )
{}
};
The simplest way is to connect a slot to the QApplication::focusChanged signal.
I'd have to play with it, but just looking at the QT Documentation, there is a "focusInEvent". This is an event handler.
Here's how you find information about.... Open up "QT Assistant". Go to the Index. Put in a "QLineEdit". There is a really useful link called "List of all members, including inherited members" on all the Widget pages. This list is great, because it even has the inherited stuff.
I did a quick search for "Focus" and found all the stuff related to focus for this Widget.
You have hit on of the weird splits in QT, if you look at the documentation focusInEvent is not a slot it is a protected function, you can override it if you are implementing a subclass of your widget. If you you just want to catch the event coming into your widget you can use QObject::installEventFilter it let's you catch any kind of events.
For some odd reason the developers of Trolltech decided to propagate UI events via two avenues, signals/slots and QEvent
Just in case anybody looking for two QMainWindow focus change .
You can use
if(e->type() == QEvent::WindowActivate)
{
//qDebug() << "Focus IN " << obj << e ;
}
QWidget::setFocus() is slot, not signal. You can check if QLineEdit is in focus with focus property. QLineEdit emits signals when text is changed or edited, see documentation.