Get a notification/event/signal when a Qt widget gets focus - qt

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.

Related

Qt QMouseEvent class

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";
}

Ignore keyboard presses on Qt inside OSG

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!

Close Widget Window if mouse clicked outside of it

This is sort of a chicken and egg problem. I'd like my widget window to be closed when the mouse clicks outside. As I understand it, there will be no mouse events for my widget for a click occurring outside of it. There is a SetFocus slot, but where is its counterpart or focus loss? "focusOutEvent" doesn't get called for my class.
My widget window is a child window of a widget always shown on my main window and it's a "Qt::ToolTip", so I assume some problems could arise from that fact. Any way around that?
My Goal: I have a custom toolbar widget where buttons on it may have “drop down” widgets. These drop down widgets have no standard windows frame. I don’t want them to “steal” caption focus from the main window and I want them to disappear as soon as the user clicks ANYWHERE on the screen outside of their region. I have having serious difficulties finding a strategy that’s not compromise on Qt to get this done.
Am I missing something? (bet I am).
I used:
setWindowFlags(Qt::FramelessWindowHint | Qt::Popup);
This seems to work well on OSX and Windows. My window appears correctly, does not steal the focus from my main window's caption, and the focus loss event is called correctly as soon as I click outside of it.
If your widget could have focus, and 'steal' the caption focus of some of your other widgets, it would have been easier. Something like this could work:
class ToolBarWidget : public QWidget
{
Q_OBJECT
public:
explicit ToolBarWidget(QWidget * parent = 0)
{
setFocusPolicy(Qt::ClickFocus);
}
protected:
void focusOutEvent(QFocusEvent * event)
{
close();
}
}
And when you create any of your widgets you'd do:
ToolBarWidget * pWidget = new ToolBarWidget(this);
pWidget->show();
pWidget->setFocus();
Done! Well, I guess not quiet. first, you don't want the ToolBarWidget to get any focus in the first place. And second, you want for the user to be able to click anywhere and the ToolBarWidget to be hidden.
So, you may keep track of every ToolBarWidget that you create. For example, in a 'QList ttWidgets' member variable. Then, whenever you create a new ToolBarWidget, you'd do this:
ToolBarWidget * pWidget = new ToolBarWidget(this);
pWidget->installEventFilter(this);
pWidget->show();
and in your main widget class, implement the eventFilter() function. Something like:
bool MainWidget::eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::FocusOut ||
event->type() == QEvent::KeyPress ||
event->type() == QEvent::MouseButtonPress)
{
while (!ttWidgets.isEmpty()) {
ToolBarWidget * p = ttWidgets->takeFirst();
p->close();
p->deleteLater();
}
}
return MainWidget::eventFilter(obj, event);
}
And that will work. Because this way, even though your ToolTabWidgets aren't getting focus, some other widget in your main widget has focus. And once that changes (whether the user clicked out of your window, or on another control inside it, or in this case, a key or mouse button is pressed, the control will reach that eventFilter() function and close all your tab widgets.
BTW, in order to capture the MouseButtonPress, KeyPress etc. from the other widgets, you would either need to installEventFilter on them too, or just reimplement the QWidget::event(QEvent * event) function in your main widget, and look for those events there.
you can do this by using QDesktopWidget.h like this
void MainWindow::on_actionAbout_triggered()
{
AboutDialog aboutDialog;
//Set location of player in center of display
aboutDialog.move(QApplication::desktop()->screen()->rect().center() -aboutDialog.rect().center());
// Adding popup flags so that dialog closes when it losses focus
aboutDialog.setWindowFlags(Qt::Popup);
//finally opening dialog
aboutDialog.exec();
}
This is what worked for me in order to not steel the focus from the main application:
.h
bool eventFilter(QObject *obj, QEvent *event) override;
.cpp
bool Notification::eventFilter(QObject *obj, QEvent *event)
{
if(event->type() == QEvent::MouseButtonPress)
deleteLater();
return QObject::eventFilter(obj, event);
}
...
// somewhere else (i.e. constructor, main window,...)
qApp->installEventFilter(this);
OP's own answer is great for Qt versions below 4.8, but as they mention in their answer, it does not work for versions above that. The Qt::Popup widget will not disappear when the mouse is clicked outside of the widget, and it will sink all of the input that would normally close it.
Upon further investigation, this is only an issue for non-dialog widgets. A QDialog using Qt::Popup will properly close when the user clicks outside of it, but any other QWidget, like a QFrame, will not. So in order to work around this behavior change in Qt 4.8, all that is necessary is to wrap the widget in a QDialog.

How to implement Click event in QGraphicsWidget?

i used QT Example : appchooser . i plan to implement the Toolbar with that. i modified it's working fine.
i have problem to catch the click event. i tried but i didn't get the solution. please help me to fix the problem.
for clicking the item i need to call the ItemClicked() method
the project source code.
http://www.4shared.com/file/Xutwi3DR/test4anime.html
Please help to find the solution..
You must subclass it since virtual void grabMouseEvent ( QEvent * event ) (in fact all mouse events) is(are) protected and there are no signals for click events for this widget.
class MyGraphicsWidget : public QGraphicsWidget{
Q_OBJECT
//Implement the constructors as you wish, if you need help with this check a Qt tutorial out.
//to get the mouse events implement the needed functions
//there are many others so just check the docs [1]
virtual void mouseReleaseEvent ( QGraphicsSceneMouseEvent * event ){
//do whatever you need here. Emit SIGNALS, show menus, etc
}
};
http://doc.qt.io/archives/qt-4.7/qgraphicswidget-members.html [1]

How to install and handle the event filter to Qt graphicsview

I have a graphicsview and a graphicsscen, but I don't know how to install and handle the event filter for getting the keyboard events. Can anyone help me with that?
Thanks in advance.
If you have created custom QGraphicsScene class you can just override QWidget's "QWidget::keyPressEvent()" and "QWidget::keyReleaseEvent()" methods.
class MyGraphicsScene : QGraphicsScene
{
void keyPressEvent(QKeyEvent *event);
}
//in cpp
void MyGraphicsScene::keyPressEvent(QKeyEvent *event)
{
// do sth with event
}
If you are just using an istance of QGraphicsScene, you can use parent's keyPressEvent. Whether or not you must give more details
You have two options to do that:
1) Create your own class based on QGraphicsView and override keyPressEvent(). That only has sense if you going to change a lot of other things.
2) Install event filter, using installEventFilter(..) method and pass there filter object which will receive everything you might need

Resources