Directing keyboard input to a widget when using Qt - qt

I am creating a GUI using Qt. Basically it is an interactive map that shows robots moving in an arena in real time and allows the user to interact with the robots(tell them to go/stop) by using the mouse and keyboard keys. I used opengl to create the map itself and everything is working perfectly, I can see the robots moving on the map and I can press different keys on the keyboard and send the actual robots commands.
Now, I need to take this map and make it become a part of a bigger GUI that holds this map along with other objects as well,not all objects are necessarily using opengl. So, by using the Qt creator (designer) I have some dragged/dropped tabs in my GUI and I have also added a "dockwidget" in my GUI. The dockwidget holds in it the interactive map that I had created earlier. Now, however I can no longer send commands using my keyboard to my map. I can still click on different robots on my map and I can see that they get selected and change colors (as I coded it to do) but pressing keys have no corresponding actions(as it has been coded).
This is what the map by itself looks like. http://dl.dropbox.com/u/46437808/collision3.png
This is the map as a docked widget. (Inside the widge,I was able to click on one robot and make it turn yellow) https://www.dropbox.com/s/lpo43rl6z4268im/argHRI.png
So, my question is how do we direct keyboard input to a specific widget in a window when using Qt. From what I read that it might have to do with setting focus policy. So, I tried to set the focuspolicy of my dockwidget to "StrongFocus" (so that it can take keyboard input) in the constructor but that did not help.
Here is the code in which I'm setting my map as the dockwidget and I'm trying to set the focus as well.
#include "ui_arghri.h"
argHRI::argHRI(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::argHRI)
{
ui->setupUi(this);
ui->dockMap->activateWindow();
//ui->dockMap->keyboardGrabber();
//ui->dockMap->grabKeyboard();
ui->dockMap->setFocus();
ui->dockMap->setFocusPolicy(Qt::StrongFocus);
}
argHRI::~argHRI()
{
delete ui;
}
void argHRI::addMap(Map * map)
{
qDebug()<<"argHRI::in AddMap test is "<<map->test;
//ui->dockMap->show();
ui->dockMap->setWidget(map);
}

Add an event filter that handles KeyPress events to your class. There are examples here: http://doc.qt.io/archives/qt-4.7/eventsandfilters.html
Just don't forget to add:
installEventFilter(this);
to the constructor or it won't work otherwise.

Related

How to handle Stylus/Pen input in QML

I am creating a simple drawing application and would like my app handle pen (stylus like Apple Pencil) input. The app is written in Qml/Qt Quick. I know that when using QWidgets you can handle tablet events using QTabletEvent (example), but how I can handle pen input in QML (using MouseArea does not work and I had no luck with PointHandler either). Does anyone know if it is possible to handle Pen input in Qt Quick?
Try using QML TapHandler: https://doc.qt.io/qt-5/qml-qtquick-taphandler.html
acceptedDevices: PointerDevice.Mouse | PointerDevice.Stylus
Looking at the example linked by #Albertino80 , I subclassed QQuickWindow which inherits QWindow and hence is able to receive tablet events (void tabletEvent(QTabletEvent* event). These events can then be used to emit appropriate signals that can be propapated to other QObjects. This method works ok, but it has the problem that event coordinates are not local to the item where they are consumed, instead one has to manually recalculate the position of each event by mapping the coordinates to the custom window.

Docking with QWinWidget: Adding DockWidgetAreas to QWidgets

I have an application utilizing QWinWidget in a Win32 window. I'd like to add DockWidgets and the associated behaviour to it. There don't seem to be any exposed APIs for adding custom DockAreas, and the latest docs are sparse beyond adding DockWidgets to a QMainWindow. Older docs imply there once was a public QDockArea class.
So far, my best option appears to be adding a neutered QMainWindow (no top-level status, no frame, etc.) to the QWinWidget and going from there (second source).
I was hoping there was a way to add DockAreas to any container, but it doesn't appear that way. As a side note, QWinWidget is used to have window manager control with our custom frame requirement, but if there's a pure QMainWindow/QWidget way to have the same result (with Qt::FramelessWindowHint), I'd be happy to switch over.
As I said in the comments, I've added within my QWinWidget in my Win32 window a QMainWindow field. That is:
class QWinWidget : public QWidget
{
...
QMainWidget* mainWidget;
}
QWinWidget::QWinWidget()
{
mainWidget = new QMainWindow(this);
mainWidget->setWindowFlags(Qt::Widget); //1
}
Note that while the docs and some forum posts (from this post) indicate you need to set window flags explicitly due to the QMainWindow constructor setting Qt::Window, I tested it without the setWindowFlags() line (marked with //1 above) without noticing anything wrong.
So, this gives me the nice QWinWidget window I spent so much time making, inside a frameless Win32 window, with a QMainWindow child and all the features that brings along with it. Docking, menu bar, status bar, etc.

How to get qtoolbars order

I need to save and restore position of QToolbars in my application.
When toolbars are docked to different area, i am able to save the area and assign it in function QMainWindow::addToolBar. But when several toolbars are docked to the same area, i don't know in what order they are currently on the screen.
I tried
QList<QToolBar*> toolbars = findChildren<QToolBar*>();
But this seems to return toolbars in order of creation and not how there are currently arranges on the screen (user can move them).
There is an easy and straightforward way of doing what you want in Qt. QMainWindow has a method saveState() that
saves the current state of this mainwindow's toolbars and dockwidgets.
and a method restoreState() that does the opposite.
Further information can be found here.
To save and restore the QMainWindow's geometry itself you can still use QWidget::saveGeometry() and QWidget::restoreGeometry().
An example of both combined that can also be found in saveState()'s documentation:
To save the geometry when the window closes, you can implement a close
event like this:
void MyMainWindow::closeEvent(QCloseEvent *event)
{
QSettings settings("MyCompany", "MyApp");
settings.setValue("geometry", saveGeometry());
settings.setValue("windowState", saveState());
QMainWindow::closeEvent(event);
}

How to make app looks nice in Qt?

I want to know is it possible to make application fully skinned/styled in Qt I mean by that not only controls inside the application window but the mainwindow itself! like close button/maximize button/minimize button and the bar, and the mainwindow border!, is it possible to do that in Qt? and how to?
Yes it is possible. The best method in Qt is to use Qt style sheets. The Qt documentation has plenty of examples and you can style all the widgets, either by specifying a whole class such as QPushButton, or a single, named widget.
As for the items on the title bar, I'm not sure if that's possible directly, but you could certainly turn off the main tool bar that contains the minimise / maximise buttons and then implement and style your own widgets while replicating their functionality.
The second argument to the QWidget constructor is Qt::WindowFlags. You can use the flags to control the properties of a window. For example, pass the flag Qt::FramelessWindowHint to create a borderless window.
There are a few ways to do this in code. You can use the setWindowsFlag method from within your widgets constructor:
setWindowFlags(Qt::FramelessWindowHint);
If you are creating a custom widget, you can pass the flag to QWidget's constructor:
YourWidget::YourWidget(QWidget *parent) : QWidget(parent, Qt::FramelessWindowHint)
{
// ....
}
Or you can pass the flag when you create a widget:
QWidget *your_widget = new QWidget(parent, Qt::FramelessWindowHint);
There are also flags for the minimize button (Qt::WindowMinimizeButtonHint), maximize button (Qt::WindowMaximizeButtonHint), close button (Qt::WindowCloseButtonHint), and title bar (Qt::WindowTitleHint). With these flags, you must also set Qt::CustomizeWindowHint to disable the defaults as described in the documentation.
See the flags documentation for a full list and additional details.
As #Merlin069 stated, style sheets allow you to control the look and feel of the widgets within your application.

Qt : keyboard focus

I am writing a program in Qt that looks like this:
The main window is my class Window : QWidget, it has a QGridLayout containing four other widgets (Input_Menu : QWidget and Output_Menu : QWidget, and then two Canvas : QWidget)
I would like to trigger certain events when the user strikes a key. The problem is, the Window sometimes loses focus (it goes, say to Input_Menu, or maybe a button in Input_Menu...)
I have tried the following solutions, but they seem unsatisfactory (and dirty):
Give Window the focus whenever it loses it.
Tell each widget who could have the focus to trigger Window's KeyPressEvent function (or a clone of it) whenever it receives a keyboard event.
Ideally, I would like that if a widget receives an event (say a keyboard event) and doesn't know what to do with it, it should automatically call its parent's event handler. I would have hoped this to be a default feature of Qt but it doesn't look like it. On the other hand I am really confused about the whole focus thing, I don't really get what's going on. Can someone explain this to me: I have included a std::cout << "key pressed" << std::endl; in my Window::KeyPressEvent function. When I first run my program, it seems the focus is on the top QComboBox in Input_Menu: if I hit the Up/Down keys, I navigate in that box and no "key pressed" is showed in my console. If I hit most letters, nothing happens. But if I hit Left/Right keys, I do get a "key pressed" in my console!?
Thanks a lot in advance for your insights.
You can install an event filter on QApplication to filter the relevant QEvent::KeyPress events globally. From the Qt documentation:
It is also possible to filter all events for the entire application,
by installing an event filter on the QApplication or QCoreApplication
object. Such global event filters are called before the
object-specific filters. This is very powerful, but it also slows down
event delivery of every single event in the entire application; the
other techniques discussed should generally be used instead.
Besides the performance considerations, remember to check if your window currently has the focus before you filter the key event, or you might break popup dialogs or input into other windows.
Actually, I found that for keys that are modifiers (such as Shift, Control), Qt supports finding out whether they are pressed.
Eg : if(QApplication::keyboardModifiers() == Qt::ShiftModifier) ...
This is good enough.

Resources