Join The GUI Generation: QTCreator

More and more projects require a software component these days. With everything being networked, it is getting harder to avoid having to provide software for a desktop or phone environment as well as the code in your embedded device.

If you’ve done a lot of embedded systems work, you probably already know C and C++. If so, it is pretty easy to grab up a C compiler and write a command-line application that does what you want. The problem is that today’s users have varying degrees of fear about the command line ranging from discomfort to sheer terror. On a mobile device, they probably don’t even know how to get to a command line. I’ve been waiting for years for the WIMP (Windows/Icon/Mouse/Pointer) fad to fade away, but even I have to admit that it is probably here for the foreseeable future.

qtrigolSo what’s the alternative? There are actually quite a few. However, I wanted to talk about one that is free, has a wide range of deployment options, uses C++, and is easy to pick up: Qt. Specifically, creating programs with QtCreator (see right). Yes, there are other options, and you can develop Qt programs in a number of ways.

You might think Qt isn’t free. There was a time that it was free for open source projects, but not for commercial projects. However, recent licensing changes (as of version 4.5) have made it more like using gcc. You can elect to use the LGPL which means it is easy to use the Qt shared libraries with closed software. You might also think that a lot of strange constructs that “extend” C++ in unusual ways. The truth is, it does, but with QtCreator, you probably won’t need to know anything about that since the tool will set up most, if not all, of that for you.

Background

If you ever used Visual Basic or something similar, you will feel right at home with QtCreator. You can place buttons and text edit boxes and other widgets on a form and then back them up with code. Buttons create signals when you push them. There are lots of signals like text changed or widgets (controls) being created or destroyed.

To handle a signal, an object provides a slot. There is a meta-compiler that preprocesses your C++ code to get all the signal and slot stuff converted into regular C++. Here’s the good news: you don’t really care. In QtCreator you can write code to handle a button push and exactly how that happens isn’t really much of a worry.

QtCreator has kits that can target different platforms and — in general — the code is reasonably portable between platforms. If you do want to do mobile development for Android or iOS, be sure that you understand the limitations before you start so you can avoid future pitfalls.

You Need Class

Like many similar frameworks, Qt uses an application class (QtApplication) that represents a do-nothing application. Your job is to customize a subclass and have it do what you want. You add widgets and you can even add more screens, if you like. You can connect signals to existing slots or new slots.

There are many classes available, and the online documentation is quite good. Depending on which version of Qt you are using, you’ll need to find the right page (or ask QtCreator to find it for you). However, just to whet your appetite, here’s the Qt5 reference page. From there you can find classes for GUI widgets, strings, network sockets, database queries, and even serial ports.

I could do an entire tutorial on using QtCreator, but it would be a duplication of effort. There’s already a great getting started one provided. You’ll find there is plenty of documentation.

Portability

How do you enumerate serial ports? It depends on the platform, right? In Qt, the platform-specific part is hidden from you. For example, here’s a bit of code that fills in a combo box with the available serial port:

MainWindow::MainWindow(QWidget *parent) :
 QMainWindow(parent),
 ui(new Ui::MainWindow)
{
 ui->setupUi(this);
// initialize list of serial ports
 ports = QSerialPortInfo::availablePorts();
// fill in combo box
 for (int i=0; i<ports.length(); i++) 
 {
   ui->comport->addItem(ports[i].portName(), QVariant(i));
 }
}

The QSerialPortInfo object provides an array of serial port objects. The ui->comport is a combo box and the addItem method lets me put a display string and a data item in for each selection. In this case, the display is the portName of the port and the extra data is just the index in the array (as a variant, which could be different types of data, not just a number). When you select a port, the index lets the program look up the port to, for example, open it.

When the combo box changes, a currentIndexChanged signal will occur. Here’s the slot handler for that:

void MainWindow::on_comport_currentIndexChanged(int index)
{
 QString out;
 // get selected index
 int sel=ui->comport->currentData().toInt();
// build up HTML info string in out
 out="<h1>Serial Port Info</h1>";
 ui->output->clear();
 out += ports[sel].portName() + " " + ports[sel].description() + "
";
 out += ports[sel].systemLocation() + "
";
 if (ports[sel].hasVendorIdentifier() && ports[sel].hasProductIdentifier())
 out += ports[sel].manufacturer() + " ("+ QString::number(ports[sel].vendorIdentifier(),16) + ":" + QString::number(ports[sel].productIdentifier(),16) + ")";
 // and put it on the screen
 ui->output->setText(out);
}

In this case, the result is information about the serial port. You can see the resulting output, below. The QString is Qt’s string class and, obviously, the text display widget understands some HTML.

qtserial

Not Just for GUIs

You can develop console applications using Qt, but then many of the provided classes don’t make sense. There’s even a Qt for Embedded (essentially Linux with no GUI). You can find guides for Raspberry Pi and BeagleBoard.

On the mobile side, you can target Android, iOS, and even Blackberry, along with others. Like anything, it probably won’t just be “push a button” and a ported application will fall out. But it still should cut down on development time and cost compared to rewriting a mobile app from scratch.

And the Winner Is…

I’m sure if you want some alternatives, our comment section is about to fill up with recommendations. Some of them are probably good. But it strikes me that not everyone has the same needs and background. The best tool for you might not work as well for me. I find Qt useful and productive.

Even if Qt isn’t your tool of choice, it still can be handy to have in your tool bag. You never know when you will need a quick and dirty cross-platform application.

48 thoughts on “Join The GUI Generation: QTCreator

  1. Qt and QtCreator are exactly why I chose Qt for my Raspberry Pi projects. It’s a shame how many people will look past it, just because it has a commercial license as an option. It’s a great toolkit and one of the most portable, as Al points out here. Well worth considering for any open source OR commercial product. (FYI, I wrote a tutorial on using Qt5/QtCreator with Python and the Pi: https://www.baldengineer.com/raspberry-pi-gui-tutorial.html)

    1. If the commercial license is no good, there’s LGPL… one of the most permissive variants of the GPL out there. Commercial license is mainly useful if you want to statically link Qt into your software and don’t want to have the fuss of providing the un-linked binary blob and source code (section 6 LGPL 2.1).

  2. Probably the biggest selling point of Qt from my end, is the signal-slot implementation of the “observer” pattern.

    You can define an object to emit a signal, connect objects up intended to receive that signal, and the object itself not care what those other objects are or how many of them exist. This is useful in all kinds of applications.

    That, and the library includes features for what is normally the domain of “managed languages” like C#/Java: smart pointers which will count references to objects, and automatically free the object when the reference count drops to 0.

    1. Signal/Slots are really a great feature, and I miss it when using plain C++. Anyway, the standard libraries since C++11 have been providing lots of functionality that was once only available in Boost / Qt (for example, the shared_ptr functionality you’ve mentioned). I still think that C++ syntax tends to be overly complicated for a few things, but it’s the language I’m most comfortable using.

      1. I was about to say the same thing. I’m using C++ for anything from ARM microcontrollers to PCs, and it’s both high-level enough to think about software design, and low level enough to optimize for performance. From C++11 onwards it is getting better and feels much more modern.
        I use Qt as well, when I need a GUI. It works well, but I don’t like the fact that they have their own container classes (QVector, QList, …) that do the same thing that the standard ones do, but in a different way.

  3. This sounds like a good package to use for a Raspberry Pi project of mine. I am looking to have a gui on a touch screen. The screen will show serial port text and the gui part will allow a finger touch on the screen to send a serial character. Does anyone know of or have something like this that I could learn from?

    Regards,
    Kevin

  4. I teach Qt in our User Design Interface class at a community college level Electronics Program. It is a great library and really makes C++ a joy to work with. The Qt libs are more than just for GUIs, they include threading, database support, video/audio playback, 2D drawing, openGL integration, OpenCV integration, networking and much more. The QtCreator IDE is a joy to work with. It has built-in Qt documentation, multiple panes, code highlighting, vim mode, built-in debugger, and much more. It also has a great visual form tool. It is also lightweight and startup-times are fast. I’d use it any day over Visual Studio.

    For those that are not fans of C++,Qt has Python extensions PyQt5 (free for developing open source apps only. Bust purchase license to develop commercial apps) and PySide/PySide2.

    Another really interesting C++ library is Wt (pronounced ‘witty’). It uses the same Qt philosophy/paradigm to build websites as opposed to a GUI running on a PC. It’s quite the piece of work…even if it doesn’t follow the traditional web development paradigm.

    https://www.webtoolkit.eu/wt

  5. Qt’s serial port library is the best cross-platform serial port interface I’ve encountered, bar none.

    Doing it in C/C++ directly is possible, but complicated and not exactly portable.

    You’d think Java would have a good cross-platform way to identify a USB serial port, right? Wrong. After all these years, the supposedly “write once, run everywhere” language still can only offer a poor, thin wrapper around libusb at best, if you can even find the jar files buried in the Java website.

    But Qt? Include qtserialport and qtserialportinfo and go. It’s great.

    1. QSerialPort is very helpful, but it is lacking, at least on Windows when using some multiplexed serial boards. It’s obviously no deal breaker, but it’s something to be aware of. This problem bit me in the bum while writing some control software.

  6. Also for those familiar with javascript or aren’t big fans of C++, lookup qml. It’s a ‘javascript-like’ language that gets you developing Qt apps very quickly.

  7. Okay, I have to confess.. This post will be a shameless plug. But I don’t want to leave this information out of people’s way for those who are interested.

    There is also an option to use Qt Creator for bare metal microcontroller development. It’s a crazy alternative for Eclipse, but it is out there and it’s completely functional with debugger included. I wrote a tutorial-like setup guide for using Qt Creator, QBS, ARM GCC, ARM GDB, OpenOCD and STM32 a little while back:

    https://github.com/nlhans/qt-baremetal

    I still use this workflow for my embedded STM32 and EFM32 projects, and I’m pretty happy with it. There are however 2 options missing: a soft-reset button in the UI and a “register pane” for MCU registers. The reset issue can be solved with a hardware reset button which works satisfactory on STM32, however on EFM32 (or other targets) YMMV. In my case, my mileage was that it cleared breakpoints on reset.

    1. Ahh I’ve done the same. Love Qt Creator to bits, so easy and nice to use.

      I wrote two tutorials but for nrf51822 ARM m0 uC. One where you use QBS and the other where you just use good old makefile.

      And I completely agree with you not having register pane or soft reset is a bit annoying. The soft-reset I normally solve by using OpenOCD and just typing the command “reset” through telnet.

      But compared to eclipse I found it much easier to setup an enviroment .

      Shamless self-promotion
      Here is the QBS tutorial
      http://morf.lv/modules.php?name=tutorials&lasit=35

      Here is for the Makefile
      http://morf.lv/modules.php?name=tutorials&lasit=37

    2. I use Qt4 for microcontroller stuff. It has the right balance between simplicity and functionality for me. The “microcontroller” part is just to call some makefile targets.

      About Resetting the uC: For AVR’s I made a target to read the fuses. This also resets the controller.

  8. It is mistaken to say that qt embedded ia designed for console applications- it is a version that can run graphical ones uaing its own framebuffer so it diesnt need x11. Also i think its discontinued.

  9. “There is a meta-compiler that preprocesses your C++ code to get all the signal and slot stuff converted into regular C++. Here’s the good news: you don’t really care. In QtCreator you can write code to handle a button push and exactly how that happens isn’t really much of a worry.”

    And here is the problem with Qt in general. Their stupid meta-object compiler needs to run through your C++ files. The entire thing is retarded to no end. No, I do not use a GUI to create my GUIs, thank you very much. I do not let some framework do code generation for me. Dirty sounds about right. As for GUI framework for embedded devices, I make my own when needed. It really is not that hard to do.

      1. It honestly is not hard at all. You provide some drawing functionality which you utilize to render your widgets; you provide a container for your widgets; you provide a way to navigate through them; you provide the means to attach callbacks to those widgets for the events you wish to track (function pointers are a way to accomplish this); and then you handle your input (this is platform specific and it is highly dependent on the available human interface devices).

        The most code intensive portion is usually the rendering part, which is also platform specific. It can range from writing directly to a framebuffer device to providing a the necessary hooks to whatever piece of hardware you are using.

        1. Not that hard? You must be far better than me at this stuff. A few years ago (2010?) I decided I needed to have a platform-independent development system that could develop applications to run under Windows, Linux, or MacOS X with minimum changes for each version. I looked at all the options I could find already out there, including SDL TCL/TK, GTK+, QT, FLTK, wxWidgets, Python with a GUI library, and a few others. At the time, all of these had serious drawbacks – SDL was nice and simple but couldn’t do multiple windows, and didn’t even have built-in support for rendering text, TK seemed to be stuck in the 1980s, most of the others seemed to work fine one one OS but not another, and so on. So I wrote my own. To me, it WAS that hard. Windows makes repaint calls directly to your window event handlers for each window, bypassing the message loop and making a mess of things. All OSs used different mechanisms for accessing the sound card. Each OS had a different way of implementing timers. Windows used BGRA pixel format instead of RGBA. Text was done differently in all three. All three have different ways of accessing a video device. Each had a different way of implementing multi-threading and inter-process communication. It was a mess, and I found that developing software took as much time updating my multi-platform library as it did developing the actual application, and I STILL don’t know why sometimes my event queue gets backed up and won’t process new events until I move the mouse around for a few seconds. This happened when I added timer support, but seems to happen even when I’m not using timers at all, and I was dreading having to work on it again.

          When I read this article, I decided to give Qt another try, and improvements since I last looked at it are numerous. This is a double-edged sword, in that Qt now has at least three fundamentally different ways of building a user interface, which means whenever you want to Google how to do something, you have to be careful that you’re not reading articles that use one of the “other” user interface paradigms. But I find that having certain things seamlessly integrated – most of the above mentioned things – is a big help, and lets me focus on the application rather than the operating system. I still don’t use Qt’s automatic layout widgets because I can’t get them to behave in a way I can predict, but that’s no problem because you don’t HAVE to use these. I can just include a little code in my app that resizes and repositions things when the user resizes a window or drags a bar, which isn’t that difficult and it means I can make it behave like I want.

          Anyway, TRON, I would suggest that you are a victim of not-invented-here syndrome. You might want to look at how much time you’re spending on parts of your applications that have already been covered, and covered well by others. And you might consider the possibility that generated code will JUST WORK, where human-generated (even TRON-generated) code is prone to errors. Sure, Qt acts as a pre-processor to C++’s pre-processor to C, but as with C++, it doesn’t monkey with code that you write that has noting to do with its extensions. I personally would rather stay away from C++ as far as that goes, but I’m willing to use C++ where necessary to talk to Qt and get the tedious stuff done automatically.

    1. Besides, you can also avoid the MOC altogether if you don’t fancy it:
      https://woboq.com/blog/verdigris-qt-without-moc.html

      And you don’t use any framework for code generation, why are you using C then? And “it’s not hard” is true only for small problems, some people have to tackle big problems as well. And why spend all the effort on solving the same small problems that has already been solved? There’s already to many wheels out there.

      1. Because sometimes those wheels come with years of extra baggage that is not needed, which leads to efforts like the one you linked. Let it also be on record that there are times where I code directly in assembly, if the situation calls for it (accessing the MSRs of a processor comes to mind right away). Also, by all means, please let me know when Qt runs on an MSP430, or a Cortex M0 core, which are platforms I target.

        On desktop applications, I use GTK2 (no, not GTK3), if you are curious. I believe it is a much saner alternative to Qt.

        1. I will let you know when QT runs on MSP430 and Cortex M0 the day when these devices ship with anything more than 1KB RAM. Next up Cortex M0 device running Tensorflow for object identification.

  10. Back in the good old days there was a lot of prejudice against QT from one section of the FOSS community, it boiled down to a GTK vs QT dick jousting thing. I’m glad all that is history because QT is a great option for many tasks.

  11. I like both Qt and GTK. But I feel Qt is currently better if you want decent and well supported cross platform apps that run on all OS’s. If you only use Linux GTK is excellent. (pyGobject – python introsepction GTK library is the best)

  12. QT is an excellent way of generating GUI apps on the raspberry pi. I used to develop win32/mfc apps before C# was popular and then moved on to just using C# for GUIs. I was never satisfied with porting C# code from windows to linux, as there was always something that didnt work properly. I love the way that QT pretty much just works on different platforms, and the way it almost feels like old fashioned windows programming, but on linux. next stop for me is to investigate QML on the pi… I kind of wish Id picked up on QT a long time ago.

  13. Linux still lacks anything that comes close to Microsoft’s visual studio. And it’s a real shame. I’ve been a game dev from over 20 years and have had to work on Linux systems as well as most of the consoles and Windows. And whenever a plugin from VS is developed so that we can move away from the Linux tools, that plugin becomes indispensable.

    Last night I was wrestling with codeblocks on my RPi 3. F10 is bolted to bring up the menu and although it is not because of codeblocks but because of GTK (so I am told on the forums) the dev refuses to implement the workaround. And as I have 20+ years of muscle memory of using F10 for step to next line it’s game over for me.

    I will check out QT again, have used it in the past but there were issues, time has allowed me to forget them so I may be presently surprised.

    The best alternative to VS, and I use ‘best’ loosely, is eclipse. And this brings me back to my original point, even the first Visual Studio, which I brought for Windows 3.1 is better than anything on offer for Linux today.

    Linux also seems to be wedded to make files. I want to bail on Windows as Linux is so much easier to do stuff with, the user space libusb is fantastic. (it sucks on windows) but I am just always left feeling disappointed with what the Linux world has created for development. It really is constraining the advancement of the all the Linux distros.

    And just don’t get me started on GDB…….. I had better debugging on the Amiga with DEVPACK!!!!

    1. I used Visual Studio for a long time. I am more a fan of lean development with emacs. However, you might look at KDevelop or NetBeans (I’d mention Eclipse, but you did). As for the debugger. There is help there too. For one thing, try gdb -w (but your gdb has to be built for this or you may find it as insight). Or try gdb -tui. However, there are tons of integrated front ends including for Eclipse and most of the other IDEs. I personally like ddd. See https://sourceware.org/gdb/wiki/GDB%20Front%20Ends

      There used to be a ppa for insight but it isn’t up to date. You might try this post if you are curious: http://www.dalfonso.co/blog/2016/04/23/setting-insight-debugger-on-ubuntu-16-04-lts/

  14. I always am astonished when HAD has an article on something I thought I missed. I started using Qt three weeks ago, and find its support, samples, online forum references clear and concise. However…many answers you may seek out on how to do things seem to be from people who either had typos in their source or didn’t include something their function requires…start with small projects and don’t become too ambitious at first and you will feel like a cross platform developer fast. Also remember to cast those keys you thought were integers when parsing xml sources to double

  15. Can anyone familiar with Qt on Windows answer this:

    If you create a small (*) Qt GUI application for Windows and pack it as an MSI installer, how small can you make the MSI file? The installer must be stand-alone and contain all required DLLs.

    Bonus question: Small (*) stand-alone OS X / macOS application DMG?

    (*) One main window with a menu (e.g. File -> Exit and Help -> About), multi-line rich text field and a couple of buttons, “About” dialog.

    1. No not really… QT has more high level widgets and is less portable. SDL is intended for drawing custom graphics portably… it also has portable Io companion libraries.

      Also, I personally think creator has a terrible UI.

  16. I’m sure to be bombarded for the switch of language, here, but the combination of [Free Pascal](http://freepascal.org/) and [Lazarus](http://www.lazarus-ide.org/) is a real appeal to make cross platform GUI applications.

    It’s moto of “write once, compile anywhere” builds on a wide range of cross-platforms, including the Raspberry Pi and Mobile.

    You can also have GTK or QT as your widgets of choice.

    But like I said, it’s a complete change of language and I’m probably starting a flame-war with the intention of giving more alternatives :)

Leave a Reply to EdwardCancel reply

Please be kind and respectful to help make the comments section excellent. (Comment Policy)

This site uses Akismet to reduce spam. Learn how your comment data is processed.