Trusted Software Excellence across Desktop and Embedded
Take a glance at the areas of expertise where KDAB excels ranging from swift troubleshooting, ongoing consulting and training to multi-year, large-scale software development projects.
Find out why customers from innovative industries rely on our extensive expertise, including Medical, Biotech, Science, Renewable Energy, Transportation, Mobility, Aviation, Automation, Electronics, Agriculture and Defense.
High-quality Embedded Engineering across the Stack
To successfully develop an embedded device that meets your expectations regarding quality, budget and time to market, all parts of the project need to fit perfectly together.
Learn more about KDAB's expertise in embedded software development.
Where the capabilities of modern mobile devices or web browsers fall short, KDAB engineers help you expertly architect and build high-functioning desktop and workstation applications.
Extensible, Safety-compliant Software for the Medical Sector
Create intelligent, patient-focused medical software and devices and stay ahead with technology that adapts to your needs.
KDAB offers you expertise in developing a broad spectrum of clinical and home-healthcare devices, including but not limited to, internal imaging systems, robotic surgery devices, ventilators and non-invasive monitoring systems.
Building digital dashboards and cockpits with fluid animations and gesture-controlled touchscreens is a big challenge.
In over two decades of developing intricate UI solutions for cars, trucks, tractors, scooters, ships, airplanes and more, the KDAB team has gained market leading expertise in this realm.
Build on Advanced Expertise when creating Modern UIs
KDAB assists you in the creation of user-friendly interfaces designed specifically for industrial process control, manufacturing, and fabrication.
Our specialties encompass the custom design and development of HMIs, enabling product accessibility from embedded systems, remote desktops, and mobile devices on the move.
Legacy software is a growing but often ignored problem across all industries. KDAB helps you elevate your aging code base to meet the dynamic needs of the future.
Whether you want to migrate from an old to a modern GUI toolkit, update to a more recent version, or modernize your code base, you can rely on over 25 years of modernization experience.
KDAB offers a wide range of services to address your software needs including consulting, development, workshops and training tailored to your requirements.
Our expertise spans cross-platform desktop, embedded and 3D application development, using the proven technologies for the job.
When working with KDAB, the first-ever Qt consultancy, you benefit from a deep understanding of Qt internals, that allows us to provide effective solutions, irrespective of the depth or scale of your Qt project.
Qt Services include developing applications, building runtimes, mixing native and web technologies, solving performance issues, and porting problems.
KDAB helps create commercial, scientific or industrial desktop applications from scratch, or update its code or framework to benefit from modern features.
Discover clean, efficient solutions that precisely meet your requirements.
Boost your team's programming skills with in-depth, constantly updated, hands-on training courses delivered by active software engineers who love to teach and share their knowledge.
Our courses cover Modern C++, Qt/QML, Rust, 3D programming, Debugging, Profiling and more.
The collective expertise of KDAB's engineering team is at your disposal to help you choose the software stack for your project or master domain-specific challenges.
Our particular focus is on software technologies you use for cross-platform applications or for embedded devices.
Since 1999, KDAB has been the largest independent Qt consultancy worldwide and today is a Qt Platinum partner. Our experts can help you with any aspect of software development with Qt and QML.
KDAB specializes in Modern C++ development, with a focus on desktop applications, GUI, embedded software, and operating systems.
Our experts are industry-recognized contributors and trainers, leveraging C++'s power and relevance across these domains to deliver high-quality software solutions.
KDAB can guide you incorporating Rust into your project, from as overlapping element to your existing C++ codebase to a complete replacement of your legacy code.
Unique Expertise for Desktop and Embedded Platforms
Whether you are using Linux, Windows, MacOS, Android, iOS or real-time OS, KDAB helps you create performance optimized applications on your preferred platform.
If you are planning to create projects with Slint, a lightweight alternative to standard GUI frameworks especially on low-end hardware, you can rely on the expertise of KDAB being one of the earliest adopters and official service partner of Slint.
KDAB has deep expertise in embedded systems, which coupled with Flutter proficiency, allows us to provide comprehensive support throughout the software development lifecycle.
Our engineers are constantly contributing to the Flutter ecosystem, for example by developing flutter-pi, one of the most used embedders.
KDAB invests significant time in exploring new software technologies to maintain its position as software authority. Benefit from this research and incorporate it eventually into your own project.
Start here to browse infos on the KDAB website(s) and take advantage of useful developer resources like blogs, publications and videos about Qt, C++, Rust, 3D technologies like OpenGL and Vulkan, the KDAB developer tools and more.
The KDAB Youtube channel has become a go-to source for developers looking for high-quality tutorial and information material around software development with Qt/QML, C++, Rust and other technologies.
Click to navigate the all KDAB videos directly on this website.
In over 25 years KDAB has served hundreds of customers from various industries, many of them having become long-term customers who value our unique expertise and dedication.
Learn more about KDAB as a company, understand why we are considered a trusted partner by many and explore project examples in which we have proven to be the right supplier.
The KDAB Group is a globally recognized provider for software consulting, development and training, specializing in embedded devices and complex cross-platform desktop applications.
Read more about the history, the values, the team and the founder of the company.
When working with KDAB you can expect quality software and the desired business outcomes thanks to decades of experience gathered in hundreds of projects of different sizes in various industries.
Have a look at selected examples where KDAB has helped customers to succeed with their projects.
KDAB is committed to developing high-quality and high-performance software, and helping other developers deliver to the same high standards.
We create software with pride to improve your engineering and your business, making your products more resilient and maintainable with better performance.
KDAB has been the first certified Qt consulting and software development company in the world, and continues to deliver quality processes that meet or exceed the highest expectations.
In KDAB we value practical software development experience and skills higher than academic degrees. We strive to ensure equal treatment of all our employees regardless of age, ethnicity, gender, sexual orientation, nationality.
Interested? Read more about working at KDAB and how to apply for a job in software engineering or business administration.
In the last episode of this blog series we learned about the overall concepts of input methods in Qt, with a look behind the scenes to see how a key press event from the native windowing system travels through the Qt input stack until it appears on screen inside a QLineEdit. In that context, the input method was used to allow the user to modify the input (e.g. composing a Chinese character sequence from Latin1 input).
Today we want to shed some light on another use case of the input method system, namely how to implement an out-of-process virtual keyboard that can be used to feed text input to arbitrary Qt-based applications.
Why do we need a virtual keyboard?
Believe it or not, there are devices out there which do not have a hardware keyboard attached (you might be holding one in your hand right now, while reading these lines ;)): mobile phones, tablets, kiosk terminals, to name just a few of them. The virtual keyboard (or sometimes called on-screen keyboard), is an application that runs alongside the other applications on the device. Whenever the user wants to input some text for the other applications, the virtual keyboard pops up a window that imitates the keys of a hardware keyboard. The user can now click the key buttons and the virtual keyboard application will convert those to key events, which will be sent to the application window that currently has the input focus. The receiving application processes the events like normal key events, so whether a hardware keyboard or a virtual keyboard is used should be opaque to it.
How do we implement a virtual keyboard with Qt?
There are actually two ways to implement a virtual keyboard with Qt: in-process and out-of-process.
For the in-process approach, the virtual keyboard becomes just another QWidget or QtQuick Item that shows the keyboard buttons, reacts to user interaction and delivers the synthesized QKeyEvents to the application's event loop. The advantage of this approach is that it is very easy to implement, since no inter-process communication between the keyboard and the application is needed. The disadvantage, however, is that every application has to store its own instance of the virtual keyboard and the state of all these instances (visibility, activity etc.) might somehow need to be synchronized between applications.
The out-of-process approach, on the other hand, allows for a single instance of the virtual keyboard to be shared between all other applications, so no synchronization between multiple virtual keyboard instances is necessary. This requires you to come up with an inter-process communication mechanism between the global virtual keyboard instance and all the applications that want to use it.
In today's blog post, we'll go for the out-of-process approach and use DBus as the IPC mechanism, since it requires little code to integrate it with Qt applications and has already proved to work for other input method systems (IBus).
The keyboard application
Our keyboard application is based on Qt Widgets, to minimise the amount of code to write, but the concepts can be adopted to a QtQuick based UI wholesale. The actual UI is really basic, just a QGridLayout with a couple of buttons inside. There is one button for each number, one for each Latin character and a Backspace and Enter button. For simplicity we omit Shift and CapsLock keys (and therefore the functionality of entering upper case characters), implementing that is left as an exercise for the reader ;).
The source code of the main.cpp looks like that:
#include<QApplication>#include<QDBusConnection>#include"keyboard.h"intmain(int argc,char**argv){ QApplication app(argc, argv);if(!QDBusConnection::sessionBus().registerService("com.kdab.inputmethod")){qFatal("Unable to register at DBus");return1;} Keyboard keyboard;if(!QDBusConnection::sessionBus().registerObject("/VirtualKeyboard",&keyboard, QDBusConnection::ExportAllSignals | QDBusConnection::ExportAllSlots)){qFatal("Unable to register object at DBus");return1;}return app.exec();}
In the first three lines we include the headers for the classes we want to use: QApplication for the event loop, QDBusConnection to make this application accessible via DBus and keyboard.h, which provides the keyboard UI. In line 11 we try to register our application at the session bus, under the unique name 'com.kdab.inputmethod'. If that fails, then something is wrong with DBus, so there is no point in running the application, because it won't be reachable by other applications. In line 16 we create an instance of our keyboard UI, which is encapsulated inside the Keyboard class. Note that we don't call show() on the Keyboard object here, so after startup, the application won't show up any window. In line 18 we publish the Keyboard object under the path '/VirtualKeyboard' and make all its public slots and signals accessible. That is all that needs to be done in main.cpp, now let's have a look at keyboard.h:
Our Keyboard class inherits from QWidget, so that it can be shown as a window on the screen. Except from a constructor, where all the UI initialization is done, it provides three public slots to show up the keyboard UI, hide it again and query its current visibility. Additionally there are two signals keyClicked() and specialKeyClicked(), which are emitted whenever the user clicked a number or letter button (keyClicked()) or the Backspace or Enter button (specialKeyClicked()).
To ensure that interacting with the keyboard window does not take away the focus from the application window that uses the virtual keyboard, we have to set the Qt::WindowDoesNotAcceptFocus flag. From line 8 on we assemble the UI by creating the QGridLayout and filling it with the keyboard buttons. To avoid code duplication, we store the properties of the buttons (key code and label) in an array and iterate over it in the for-loop in line 16. For each entry we create a QPushButton with a fixed width and set the key label as button text. Since all button clicks should be handled in a central place, we use the QSignalMapper to invoke the private buttonClicked(int key) slot, whenever one of the QPushButtons is clicked. The 'key' parameter is the corresponding Qt::Key as defined in the 'keyboardLayout' array, which is defined as the following:
So every entry has the Qt::Key code and the label that should be used. Additionally there are some special marker entries with key code 'NEXT_ROW_MARKER', which just ensure that the following buttons will end up on the next line in our QGridLayout.
Now what happens if the user clicks on one of the QPushButtons? The buttonClicked() slot is invoked:
If the pressed key is Backspace or Enter, the specialKeyClicked() signal is emitted, otherwise the key code is mapped to a character and the keyClicked() signal is emitted with that character as parameter. To do the mapping, the helper method keyToCharacter() is invoked, which is defined as follows:
static QString keyToCharacter(int key){for(int i =0; i < layoutSize;++i){if(keyboardLayout[i].key == key)returnQString::fromLatin1(keyboardLayout[i].label);}returnQString();}
In this simple keyboard implementation, we just return the label of the button (so a lower-case character or a number). In a more advanced version, you would have to take pressed modifier keys into consideration to map to upper-case or other special characters.
The implementation for the remaining public slots is straightforward. They simply forward the requests to the corresponding methods in the QWidget base class.
To summarize: We now have a keyboard UI application that is accessible via DBus through the name "com.kdab.inputmethod/VirtualKeyboard". It provides methods to show it on screen, hide it from screen and ask for its current visibility. Additionally, that application emits the two signals specialKeyClicked() and keyClicked() (also via DBus) whenever the user clicks on one of the QPushButtons.
A simple test as to whether the keyboard UI works as expected, can be done by starting the application and then using qdbusviewer to inspect its DBus interface, invoke the exported slots and log the signal emissions.
Now that we have the virtual keyboard, let's have a look at the corresponding input method implementation...
The Qt Input Method plugin
In the previous post [add link] of this series we learned that the communication between the Qt text input components and the input method system is done through the public front end class QInputMethod and the private back end class QPlatformInputContext. If we want to provide our own input method, we have to do two things:
Implement a custom version of QPlatformInputContext subclass
We declare a new class QVkImPlatformInputContextPlugin which inherits from QPlatformInputContextPlugin and we reimplement the virtual method create(). The plugin meta data are stored in the external file 'vkim.json', which just contains the following lines:
{"Keys":["vkim"]}
The term 'vkim' is short for 'virtual keyboard input method' and is used as an identifier for our input method plugin. We will see later on where it is needed.
In the implementation of QVkImPlatformInputContextPlugin::create() we check if the requested object has that identifier and return a new instance of our custom class QVkImPlatformInputContext in this case. QVkImPlatformInputContext is our custom reimplementation of QPlatformInputContext with the following declaration:
It reimplements five virtual methods from QPlatformInputContext that have the following functionality:
isValid() is called by QPlatformInputContextFactory (the class that loads the plugin and invokes the create() method) to check if the input method is ready to use
setFocusObject() is called by QGuiApplication to inform the QPlatformInputContext about the object that currently has input focus
showInputPanel() is called by QInputMethod::show() to call up the keyboard UI if a text input field retrieves the focus
hideInputPanel() is called by QInputMethod::hide() to hide the keyboard UI if the current text input field loses focus
isInputPanelVisible() is called by QInputMethod::isVisible() to inform the application about the visibility state of the keyboard UI
Additionally there are the two private slots, keyboardSpecialKeyClicked() and keyboardKeyClicked(), which are invoked whenever we receive the corresponding signals from our keyboard UI application via DBus. The two member variables store a pointer to the DBus interface and a pointer to the current focus object in the application.
Now let's have a look at the implementation of that class, where all the magic happens:
Inside the constructor, the connection to the keyboard UI DBus interface is established. Here we have to specify the "com.kdab.inputmethod" application ID and "/VirtualKeyboard" path to point to the exported Keyboard object. Since our class needs to be informed about the buttons that the user clicked on the keyboard UI, we connect the two signals keyClicked() and specialKeyClicked() against the two private slots.
Inside the isValid() method we just return whether the DBus interface object is valid. If we couldn't connect to the keyboard UI application, then our input method wouldn't be of any use, so this test is sufficient.
In case the QGuiApplication informs us about a new focus object, we store the pointer to it in the member variable, since we need it later on (see below).
When QInputMethod::show() or QInputMethod::hide() is invoked by the text input widgets (e.g. QLineEdit or QTextEdit), the showInputPanel() and hideInputPanel() methods are called, which forward these requests via the DBus interface to the keyboard UI process:
The very same approach is taken for QInputMethod::isVisible(), which invokes isInputPanelVisible(). In that case we also invoke the remote function in the keyboard UI process via DBus, but this time, we have to process the return value as well:
Now we come to the part where our custom QPlatformInputContext forwards the key clicks, as received from the keyboard UI application, to the user application. For textual input that is done with the QInputMethodEvent. So if there is a text input widget that currently has the input focus (m_focusObject != null) we set the typed in characters as commit string on the event and send it to the object.
For every non-textual input, in our case the Backspace and Enter key, we synthesize QKeyEvents for the press and release event and post them to the focus object through the event loop. While using a QKeyEvent to deliver, the Enter key is required. The Backspace functionality (removing the character on the left side of the input cursor) could have been implemented with a QInputMethodEvent as well:
Since we are passing values unequal to 0 to the second and third parameter of setCommitString(), the QInputEvent won't append the given characters to the content of the input widget, but will replace 1 character (replaceLength in 3rd parameter) at position -1 (replaceFrom in 2nd parameter), which means 1 character left of the input cursor position, with an empty string (first parameter).
Bringing it all together
Now that we have the virtual keyboard and the input method plugin that communicates with it, let's have a look at how to use it with a real Qt application. By default, the used QPA plugin provides an input method for the system, so if we want to use our own one, we have to tell Qt about that explicitly, by setting the environment variable QT_IM_MODULE to the identifier of the input method. In our case that identifier is 'vkim', the very same value we stored inside vkim.json as meta data for the input method plugin.
To use Qt Designer with our virtual keyboard just execute the following commands on the Linux command line:
# start the keyboard UI application./server
# set the environment variableexportQT_IM_MODULE=vkim
# run any Qt applicationdesigner
Now as soon as you click in a text input field in Qt Designer, the keyboard UI will show up:
Further improvements
As mentioned before, this example implementation is really basic, to show you the concepts behind that technique without getting lost in details. For a real virtual keyboard that can be used in a production system, you might want to add the following functionality:
multiple keyboard layouts That basically means showing different labels on the keyboard buttons, depending on the configured layout, and returning these characters in the keyToCharacter() function
positioning of keyboard window In the current implementation, the position of the keyboard window on screen is selected by the window manager, which normally prevents windows from overlapping. For the virtual keyboard, however, we might want to open it near (below or above) the text input widget, so that we don't have to move the mouse cursor across the whole screen. With QWidget::mapToGlobal() we can determine the position of the focus widget on the screen and place the UI accordingly, by adding a new 'void setPosition(int x, int y)' method to the DBus interface of the Keyboard class.
Yes, widgets are still alive and kicking. In the many years we have worked with them, we have gathered quite a number of tips and tricks that we’d love to share with you.
I think you article is very interesting, and also important for me. I have heavy problems to be able to use a im_module inside Linux Mint for Qt5 programs. You use Qt5 for compile your program ? I tried it, and later i use a test program compiled with Qt5, with only one QLineEdit at center of a QWidget, but without success. A keyboard not appear after run "server" , export and set to vkim and then execute my program with QLineEdit. Have you some idea ? Have used also Qt ? Thanks for any help. Daniel
8 - Sept - 2015
Tobias Koenig
Hej Daniel,
yes, the linked code is supposed to be compiled with Qt5. Is your IM module installed in the right path? Have a look at http://doc.qt.io/qt-5/deployment-plugins.html#debugging-plugins for further ideas how to debug plugin loading (e.g. QT_DEBUG_PLUGINS), that should give you a hint if the plugin can be found/loaded at all.
9 - Sept - 2015
Daniel
Hi Tobias (sprichst Du Deutsch ?).
Thanks for your quick answer. What i do now is from a clean environment, install Qt (from VirtualBox) and see what will happen, because i have too many directories. Previous i use a release version and also check QT_PLUGIN_PATH, .. but without success. I am writing already from a virtual Ubuntu. Daniel
9 - Sept - 2015
Daniel
I tell you about the exactly steps what i do :
install Ubuntu
install Qt on /home/daniel/Qt
download virtual-keyboard-demo
install "build-essential" and "libgl1-mesa-dev"
now i can compile "plugin" and "server" from Qt Creator, which i do with release-mode
i check, plugin is released on folder /home/daniel/Qt/5.5/gcc_64/plugins/platforminputcontexts/
start "./server"
set environment variables. I see at begin, many environment variables are not set except QT_IM_MODULE which is set to ibus. I set :
Something is wrong, if i click on a QLineEdit, a keyboard not appear, i only can see it with
$QTDIR"bin/qdbusviewer" and playing with :
click on "com.kdab.inputmethod"
click on "Virtualkeyboard" at right
local.server.Keyboard
double click at Method:showKeyboard (keyboard appear)
Signal:keyClicked
and every signal is received pushing buttons of this keyboard
9 - Sept - 2015
Tobias Koenig
Hej Daniel,
you have been right, the code didn't work with latest Qt 5.5, because the IID for the plugin meta data has changed from "org.qt-project.Qt.QPlatformInputContextFactoryInterface" to "org.qt-project.Qt.QPlatformInputContextFactoryInterface.5.1".
I have fixed the code in the repository now, instead of hard-coding the string literal, it uses the QPlatformInputContextFactoryInterface_iid define now.
Thank you very much for spotting it! :)
9 - Sept - 2015
Daniel
Hi Tobias.
I am very happy, because now is working. This will give me hope to make working also "gcin" input method, which we always use.
Very much thanks for your help.
Daniel
17 - Sept - 2015
Simon
Thanks for the interesting article. I am in the process of converting a Qt4 application to run on Qt5 and now have everything working except the On-Screen-Keyboard. As our software runs on proprietary devices and is the only running application that has any user interaction via the screen, I am interested in the in-process approach which you say in your introduction "... is very easy to implement". I'm struggling to find documentation anywhere on how to do this and wondered if you could point me at any or explain how your implementation would be adapted? I already have the OSK from my Qt4 app so just being able to hook it up would be really good - especially as I was given 1 day to do the whole migration and I've already taken 2 (which, all things considered is not too bad considering it has over 400,000 lines of code) :-) The OSK is now the only stumbling block. Thanks again.
18 - Sept - 2015
Tobias Koenig
Hej Simon,
the in-process OSK can be implemented by just creating corresponding QKeyEvent objects, whenever the user presses/releases on one of the OSK button, and deliver them to the current focus object of the application, e.g. QGuiApplication::sendEvent(QGuiApplication::focusObject(), event). You just have to make sure that clicking the button on the OSK won't let it take the focus (see how it is done on the external OSK in the example in the git repo).
21 - Sept - 2015
Simon
Thanks Tobias - I hope you won't mind if I ask one more question: In my Qt4 application, after instantiating my own class which inherited from QInputContext all I had to do was call qApp->setInputContext and this ensured that when I touched a UI input element my OSK would pop-up. Is there something similar I can do in Qt5 with my QPlatformInputContext derived class or do I need to hook all of that up manually too?
Thanks again.
22 - Sept - 2015
Tobias Koenig
Hej Simon,
the QGuiApplication::setInputContext() method has been removed in Qt5. To use a custom input method, you have to implement and install your own input method plugin and make the application using it by setting the QT_IM_MODULE environment variable.
22 - Oct - 2015
cristina
Is there any way you can show how to do the virtual keyboard by doing the in process approach? I am confused how it would be different than the out of process approach.
26 - Oct - 2015
Tobias Koenig
Hej Christina,
for the in-process version, you'd simply put the virtual keyboard widget into the main application and let it communicate directly with the QVkImPlatformInputContext, so the separate server process and dbus communication is left out.
15 - Mar - 2017
YT
Hello
It's very valuable information for me. However I have an issue to build 'plugin' project.
When I try 'qmake' with Qt 5.7, it has totally no problem, but with Qt 5.8 I always get:
"Project ERROR: Could not find feature reduce_exports".
From some forums in the internet, I now know it was caused by "load(qt_plugin)", but I don't know how to fix it.
Do you have any idea on it?
Thank you.
15 - Mar - 2017
Tobias Koenig
Hej,
I just pushed a fix to the git repository, which fixes compilation with Qt 5.8, please re-pull.
16 - Mar - 2017
YT
Great thanks, it works.
BTW, I think there is a description about this kind of tricky issue.
I'm reading http://doc.qt.io/qt-5/plugins-howto.html and related, but I can't find it.
If I'm right, where could I find such document?
8 - May - 2017
rober
hi:
The virtualkeyboard run well,but When I transplat it to the platform of arm ,it has a vital problem as follows:
QObject::connect: No such signal QDBusAbstractInterface::keyClicked(QString)
Unable to register at DBus
Aborted
8 - May - 2017
Tobias Koenig
Hej,
the error message says it all: 'Unable to register at DBus', so your system seems to miss a running DBus daemon where the virtual keyboard could connect to.
4 - Oct - 2017
Steven Szczuka
Hi Tobias
Thanks so much for a very informative post.
I was able to make it work "in-process" by putting the keyboard class in the plug-in and it's been working so far. Is there any problem with instantiating widgets in a plug-in?
Thanks
Steve
5 - Oct - 2017
Tobias Koenig
Hej Steve,
instantiating a widget from a plug-in is perfectly fine (that's how QtCreator creates most of its UI for example), just make sure that do you not unload the plugin as long a such a widget instance is still around.
21 - Mar - 2018
KCJ
To get the server to build on Debian Stretch I had to install qtbase5-private-dev.
11 - May - 2022
Laszlo Papp
Hi, nice article. Thanks for sharing.
My only issue with the way you build the keyboard using QGridLayout is that it is fairly limiting to mimic a real keyboard virtually. This is because hardware keyboards do not seem to map well into a QGridLayout. They seem to be more freestyle with alignments.
Do you feel that setGeometry on the QPushButtons is a more practical way to go? That is how I implemented it at least and that resembles a real keyboard (or even other virtual keyboards) closer.
12 - May - 2022
Tobias Koenig
Hej Laszlo,
the article concentrated more about what happens behind the scenes, not so much about making a pretty UI :) So sure, in an actual product software the keyboard UI should adapt to real keyboard layouts and support switching between various ones.
Tobias Koenig
Senior Software Engineer
Senior software engineer at KDAB, Tobias has actively developed with Qt since 2001 and has been an active KDE contributor during this time. His contributions have been mainly to the KDE PIM project and the KDE libraries, but also to other open source projects. He holds an MSc in Computer Science.
Our hands-on Modern C++ training courses are designed to quickly familiarize newcomers with the language. They also update professional C++ developers on the latest changes in the language and standard library introduced in recent C++ editions.
22 Comments
7 - Sept - 2015
Daniel
I think you article is very interesting, and also important for me. I have heavy problems to be able to use a im_module inside Linux Mint for Qt5 programs. You use Qt5 for compile your program ? I tried it, and later i use a test program compiled with Qt5, with only one QLineEdit at center of a QWidget, but without success. A keyboard not appear after run "server" , export and set to vkim and then execute my program with QLineEdit. Have you some idea ? Have used also Qt ? Thanks for any help. Daniel
8 - Sept - 2015
Tobias Koenig
Hej Daniel,
yes, the linked code is supposed to be compiled with Qt5. Is your IM module installed in the right path? Have a look at http://doc.qt.io/qt-5/deployment-plugins.html#debugging-plugins for further ideas how to debug plugin loading (e.g. QT_DEBUG_PLUGINS), that should give you a hint if the plugin can be found/loaded at all.
9 - Sept - 2015
Daniel
Hi Tobias (sprichst Du Deutsch ?). Thanks for your quick answer. What i do now is from a clean environment, install Qt (from VirtualBox) and see what will happen, because i have too many directories. Previous i use a release version and also check QT_PLUGIN_PATH, .. but without success. I am writing already from a virtual Ubuntu. Daniel
9 - Sept - 2015
Daniel
I tell you about the exactly steps what i do :
set environment variables. I see at begin, many environment variables are not set except QT_IM_MODULE which is set to ibus. I set :
export QTDIR=/home/daniel/Qt/5.5/gcc_64/ export QT_PLUGIN_PATH=$QTDIR"plugins" (a echo return /home/daniel/Qt/5.5/gcc_64/plugins) export QT_IM_MODULE=vkim ("echo $QT_IM_MODULE" return "vkim")
i start designer with : $QTDIR"bin/designer"
Something is wrong, if i click on a QLineEdit, a keyboard not appear, i only can see it with $QTDIR"bin/qdbusviewer" and playing with :
and every signal is received pushing buttons of this keyboard
9 - Sept - 2015
Tobias Koenig
Hej Daniel,
you have been right, the code didn't work with latest Qt 5.5, because the IID for the plugin meta data has changed from "org.qt-project.Qt.QPlatformInputContextFactoryInterface" to "org.qt-project.Qt.QPlatformInputContextFactoryInterface.5.1".
I have fixed the code in the repository now, instead of hard-coding the string literal, it uses the QPlatformInputContextFactoryInterface_iid define now.
Thank you very much for spotting it! :)
9 - Sept - 2015
Daniel
Hi Tobias. I am very happy, because now is working. This will give me hope to make working also "gcin" input method, which we always use. Very much thanks for your help.
Daniel
17 - Sept - 2015
Simon
Thanks for the interesting article. I am in the process of converting a Qt4 application to run on Qt5 and now have everything working except the On-Screen-Keyboard. As our software runs on proprietary devices and is the only running application that has any user interaction via the screen, I am interested in the in-process approach which you say in your introduction "... is very easy to implement". I'm struggling to find documentation anywhere on how to do this and wondered if you could point me at any or explain how your implementation would be adapted? I already have the OSK from my Qt4 app so just being able to hook it up would be really good - especially as I was given 1 day to do the whole migration and I've already taken 2 (which, all things considered is not too bad considering it has over 400,000 lines of code) :-) The OSK is now the only stumbling block. Thanks again.
18 - Sept - 2015
Tobias Koenig
Hej Simon,
the in-process OSK can be implemented by just creating corresponding QKeyEvent objects, whenever the user presses/releases on one of the OSK button, and deliver them to the current focus object of the application, e.g. QGuiApplication::sendEvent(QGuiApplication::focusObject(), event). You just have to make sure that clicking the button on the OSK won't let it take the focus (see how it is done on the external OSK in the example in the git repo).
21 - Sept - 2015
Simon
Thanks Tobias - I hope you won't mind if I ask one more question: In my Qt4 application, after instantiating my own class which inherited from QInputContext all I had to do was call qApp->setInputContext and this ensured that when I touched a UI input element my OSK would pop-up. Is there something similar I can do in Qt5 with my QPlatformInputContext derived class or do I need to hook all of that up manually too? Thanks again.
22 - Sept - 2015
Tobias Koenig
Hej Simon,
the QGuiApplication::setInputContext() method has been removed in Qt5. To use a custom input method, you have to implement and install your own input method plugin and make the application using it by setting the QT_IM_MODULE environment variable.
22 - Oct - 2015
cristina
Is there any way you can show how to do the virtual keyboard by doing the in process approach? I am confused how it would be different than the out of process approach.
26 - Oct - 2015
Tobias Koenig
Hej Christina,
for the in-process version, you'd simply put the virtual keyboard widget into the main application and let it communicate directly with the QVkImPlatformInputContext, so the separate server process and dbus communication is left out.
15 - Mar - 2017
YT
Hello
It's very valuable information for me. However I have an issue to build 'plugin' project. When I try 'qmake' with Qt 5.7, it has totally no problem, but with Qt 5.8 I always get: "Project ERROR: Could not find feature reduce_exports".
From some forums in the internet, I now know it was caused by "load(qt_plugin)", but I don't know how to fix it.
Do you have any idea on it?
Thank you.
15 - Mar - 2017
Tobias Koenig
Hej,
I just pushed a fix to the git repository, which fixes compilation with Qt 5.8, please re-pull.
16 - Mar - 2017
YT
Great thanks, it works. BTW, I think there is a description about this kind of tricky issue. I'm reading http://doc.qt.io/qt-5/plugins-howto.html and related, but I can't find it. If I'm right, where could I find such document?
8 - May - 2017
rober
hi: The virtualkeyboard run well,but When I transplat it to the platform of arm ,it has a vital problem as follows: QObject::connect: No such signal QDBusAbstractInterface::keyClicked(QString) Unable to register at DBus Aborted
8 - May - 2017
Tobias Koenig
Hej,
the error message says it all: 'Unable to register at DBus', so your system seems to miss a running DBus daemon where the virtual keyboard could connect to.
4 - Oct - 2017
Steven Szczuka
Hi Tobias Thanks so much for a very informative post. I was able to make it work "in-process" by putting the keyboard class in the plug-in and it's been working so far. Is there any problem with instantiating widgets in a plug-in?
Thanks Steve
5 - Oct - 2017
Tobias Koenig
Hej Steve,
instantiating a widget from a plug-in is perfectly fine (that's how QtCreator creates most of its UI for example), just make sure that do you not unload the plugin as long a such a widget instance is still around.
21 - Mar - 2018
KCJ
To get the server to build on Debian Stretch I had to install
qtbase5-private-dev
.11 - May - 2022
Laszlo Papp
Hi, nice article. Thanks for sharing.
My only issue with the way you build the keyboard using QGridLayout is that it is fairly limiting to mimic a real keyboard virtually. This is because hardware keyboards do not seem to map well into a QGridLayout. They seem to be more freestyle with alignments.
Do you feel that setGeometry on the QPushButtons is a more practical way to go? That is how I implemented it at least and that resembles a real keyboard (or even other virtual keyboards) closer.
12 - May - 2022
Tobias Koenig
Hej Laszlo,
the article concentrated more about what happens behind the scenes, not so much about making a pretty UI :) So sure, in an actual product software the keyboard UI should adapt to real keyboard layouts and support switching between various ones.