Qt

I recently started programming with Qt because I wanted to use the same source code for other platforms like Windows and Mac. Qt is based on C++. In Qt, methods can be slots which can be called automatically when a signal arrives to the class where the slot is declared in. There is a function called connect() which you can use to connect signals with slots.

To install the SDK and demos on Ubuntu:

aptitude install qdevelop qt-creator qt4-demos

You can find the demos and examples in /usr/lib/qt4. There are 2 programming environments: qdevelop (older, with more features) and qtcreator (newer, with less features). The company recommends qtcreator. Double clicking on a .ui file within qdevelop or qtcreator, opens qt-designer which is a GUI designer. You can drag widgets onto the form, and in the context menu you can "go to slot", which creates a slot in your source code and brings up the editor with the cursor in the slot's body, so you can implement it right away. The .ui file is automatically converted to a C++ class in the source code, and the class you are editing is a subclass from it, so you won't lose any changes when code is regenerated using the .ui file. Buiding and running is done with the "play" buttons in the lower left corner.

For Windows, go to the site and choose Downloads, LGPL / Free, Download Qt SDK for Windows. The install path is not allowed to have any spaces, so you cannot install Qt under "Program Files". Also, the installer says it needs 1Gb, but it actually needs twice as much while installing. Under Windows, stdin and stdout are not working, so don't bother using cin and cout. For debugging, #include <QDebug> and use qDebug() instead of cout. Additionally you can use qDebug the same way as printf(). To run the executable without the developing environment, you need to copy minwm10.dll, QtCore4.dll, QtGui4.dll and possibly other DLL files from C:\\qt\2009.003\qt\bin to the folder where your executable is located. Any output of qDebug() gets lost, because this only works within the developing environment. For MySql support, there is extra (10 minutes) of work to be done. The instructions below apply for Qt 4.5.

  • go to the MYSQL download section and choose community server, windows and download the windows essentials.
  • double click on it, change the install path to C:\MYSQL, disable the server installation if you do not intend to use it, enable the clients and the development headers and libraries.
  • copy C:\MYSQL\BIN\LIBMYSQL.DLL to C:\QT\2009.03\QT\BIN.
  • open QT command prompt
  • type:
    cd %QTDIR%\src\plugins\sqldrivers\mysql
    qmake "INCLUDEPATH+=C:\MySQL\include" "LIBS+=C:\MYSQL\lib\opt\libmysql.lib" mysql.pro
    mingw32-make debug release
    
  • copy *.a and *.dll from both the DEBUG and RELEASE folders in C:\QT\2009.03\QT\SRC\PLUGINS\SQLDRIVERS\MYSQL to C:\QT\2009.03\QT\PLUGINS\SQLDRIVERS.

Programming tips:

  • to open additional windows use QDialog. Use QDialog::exec() to display modal dialogs or QDialog::show() to display modeless windows.
  • for intercepting window close events (in order to close other windows, or to prevent closing and display a warning dialog), override the protected closeEvent() function. See the docs of QWidget.
  • here is some code for accessing a MySQL database:
    QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL", "somename");
    db.setHostName("hostname");
    db.setDatabaseName("databasename");
    if (!db.open("username", "password"))
    {
       qDebug("error: %s\n", db.lastError().databaseText().toAscii().constData());
       return;
    }
    qDebug("connection opened\n");
    QSqlQuery query("select field1, field2 from sometable", db);
    if (!query.isActive())
    {
       qDebug("error in query: %s\n", query.lastError().databaseText().toAscii().constData());
       return;
    }
    qDebug("processing");
    // Show first field of all rows
    while (query.next())
       qDebug("%s\n", query.value(0).toString().toAscii().constData());
    qDebug("Done\n");
    query.finish();
    db.close();
  • To invoke a slot manually use QMetaObject::invokeMethod().
  • For handling strings the QString class is used. Many functions in the examples directory return QString objects (not pointers to QString objects) which implies copying and seems to be a good alternative for allocating memory in the function and freeing it somewhere else. To get the raw char* ascii string, use .toAscii().constData().
  • In C++ the const keyword is used commonly. The const keyword always applies to the word immediately to the left of the const keyword, except when there is nothing there; then it applies to the word immediately to the right of the const keyword. When the const keyword is applied at the end of a method prototype, then it means the method will not alter any variables of its own class.
  • Use QMessageBox() to display a simple messagebox with Ok-button.
  • You can attempt to typecast a pointer of an object to a pointer of a subclass of that object using qobject_cast<some_class *>(pointer_to_some_object). When some_class is not the class or a subclass of some_object, 0 is returned. This can be used to check if an object belongs to a given (sub)class:
    bool foo = qobject_cast<some_class *>(pointer_to_some_object);