Yet more Qt tips…

Two more for you!

Shared Data
Like Qt’s copy-on-write shared data semantics? Want to do the same for your own class? It’s easier than you think. Simply inherit from QSharedData, which provides the necessary reference-counting semantics. See here for more info.

Running a Slot on a Different Thread
Sometimes you want to schedule a single operation on a different thread; you can do this using QObject::moveToThread to move an object’s thread affinity to a different thread, and then trigger the slot as a queued connection. See here for a discussion of how Qt’s threads and Qt’s object system cooperate.

More Qt tips…

Following on the heels of last week’s post, here are a few more thoughts gleaned from the experience of attending last year’s Qt Developer Days. These are all old news, especially if you’ve been doing Qt for a while, but putting them here may be useful to you, and clears out a page of thoughts in my engineering notes!

QImage vs. QPixmap
Remember that QImage is the general-purpose class for image manipulation whose data lives in main memory, while QPixmap objects are usually backed by the GPU. This has some ramifications for your application:

  • QImage is optimized for I/O and direct pixel access.
  • QPixmap is optimized for direct screen display.
  • On constrained platforms like mobile devices, there may be relatively little GPU RAM available, so you should consider using QPixmap objects sparingly.

Regardless of which you choose, both classes use Qt’s copy-on-write (COW) semantics, so if you have multiple instances of the same image, you pay a small price penalty—basically the cost of the object overhead, not the memory footprint of the image itself.

QStandardItemModel and Performance
Qt’s support for model-view-controller is great, and one of the handiest things about it is that the QStandardItemModel class provides everything you need in a model to get going. It is, however, not necessarily the most efficient way to do so.

If you have your own model already—say you’re porting an existing application, or working with a library with its own data representation—it really is a good idea to implement your own model class from QAbstractItemModel. I’m not bad-mouthing QStandardItemModel, but it’s based on Qt’s collection classes, and odds are that you know better ways to store your data (especially if there’s a lot of it!) than Qt does.

Personally, my approach is that if I don’t have a data container and I’m only dealing with a handful of data items — say, up to a hundred or so objects with a half-dozen roles or so — I use QStandardItemModel and don’t look back. (Qt’s collection classes are, after all, quite good for general applications). But if I’ve already got a data model, or I know I’m going to be dealing with lots and lots of objects, it’s time for a custom model that leverages my knowledge of the data set I’m wrapping.

Use QtConcurrent for Parallel Computation
I’ve not tried this personally, but QtConcurrent looks really cool for doing any kind of concurrent map/reduce style programming. If you need to write code that leverages multiple cores for concurrent computation, it’s best to look here before trying to roll your own framework using QThread.

A grab bag of Qt tips…

So, last year I went to the Qt Developer conference here in S.F. It’s a great opportunity to meet up with Qt Developers from all over the world. One of the amazing things about Qt is how easy it is to get up and running and be productive; unfortunately, it’s easy to get stuck in a rut where you always do things the same way and don’t necessarily try new ways of doing the same things, or really look at performance in your code, and just generally be a fair-to-middling developer with Qt.

I attended a well-run session on Qt tips and tricks from the trenches, and ended up with two pages of longhand scrawl of good thoughts that I either hadn’t really explored in Qt, or realized I needed to learn more about. These got transcribed to a bullet list of items, some of which I’ve followed up on, and some I haven’t. Here are a few, with some of my observations about them, preserved for posterity and your use!

invokeMethod for Deferred Method Invocation
You often want to run some bit of code just after a method call; deferred initialization is a common case, where your constructor does the bare minimum to set something up, and then once everything’s up and running you want to do a bit more initialization. A single-shot timer is a good way to do this; you can use QTimer::singleShot with a short delay to trigger a slot in your class. You can also do the same thing using QMetaObject::invokeMethod, passing Qt::QueuedConnection as the connection type. When you do this, Qt sends a QEvent and the method is invoked as soon as the application enters the main event loop, which is probably what you were trying to accomplish with the timer anyway.

Implementing << and >> for QVariant Serialization
This is a “well, duh” if you’ve read Qt’s serialization documentation, but you can implement << and >> for your class using QDataStream to support serialization.

I like to take the time and do a human-readable string for QDebug::operator<< at the same time, too, so I can log complex data types to the debug console when doing printf-style debugging.

Use const References with foreach
This should go without saying, but a lot of people forget. If you're iterating across a Qt collection using foreach, don't forget you almost certainly want to use constant references to do so. Otherwise, the implementation makes a copy of each item being passed to you at the beginning of each pass through the loop, and destroys that instance at the end. All of this happens on the stack, of course, but you're still paying the constructor and destructor penalty, and if your object is large, you're thrashing your stack footprint needlessly.

I'll post a few more of these next week!