Preparations This tutorial uses the open source version of Qt4 for Microsoft Windows with mingw compiler (gcc port for Windows). We will briefly show installation of Qt and MinGW. However this tutorial is not limited to Windows and can be used on Linux/other platforms supported by Qt as well. This tutorial introduces no IDE (integrated development environment). The tools used here are just Qt Designer (for creating dialogs), a text editor (for writing code) and of course a compiler suite. Installation on Windows In general there are 2 way how to install Qt. Either use installer which install precompiled binaries (recommended on Windows) or to compile Qt from sources. Installing Qt using installer On Windows where is no need to compile Qt library from sources as Trolltech provide precompiled binaries with installer which will download and install also MinGW. Go to http://trolltech.com/downloads/opensource/appdev , choose "Qt for Windows: C++" and get qt-win-opensource-4.X.X-mingw.exe. During installation choose also to download and install MinGW. When finished we have to make sure env. variables are set correctly. Adjusting environment variables Set following environment variables (right click on My Computer, then Properties, Advanced, Environment variables): QTDIR to C:\Qt\4.X.X (or whatever path you installed QT) QMAKESPEC to win32-g++ and adjust PATH, add C:\Qt\4.X.X\bin and C:\MinGW\bin (or whatever path you installed MinGW)
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Preparations
This tutorial uses the open source version of Qt4 for Microsoft Windows with mingw compiler (gcc port for Windows). We will briefly show installation of Qt and MinGW. However this tutorial is not limited to Windows and can be used on Linux/other platforms supported by Qt as well.
This tutorial introduces no IDE (integrated development environment). The tools used here are just Qt Designer (for creating dialogs), a text editor (for writing code) and of course a compiler suite.
Installation on Windows
In general there are 2 way how to install Qt. Either use installer which install precompiled binaries (recommended on Windows) or to compile Qt from sources.
Installing Qt using installer
On Windows where is no need to compile Qt library from sources as Trolltech provide precompiled binaries with installer which will download and install also MinGW. Go to http://trolltech.com/downloads/opensource/appdev, choose "Qt for Windows: C++" and get qt-win-opensource-4.X.X-mingw.exe. During installation choose also to download and install MinGW. When finished we have to make sure env. variables are set correctly.
Adjusting environment variables
Set following environment variables (right click on My Computer, then Properties, Advanced, Environment variables):QTDIR to C:\Qt\4.X.X (or whatever path you installed QT)QMAKESPEC to win32-g++and adjust PATH, add C:\Qt\4.X.X\bin and C:\MinGW\bin (or whatever path you installed MinGW)
Logout/login or restart after changing environment variables, otherwise it won't work.
Now let's test if we have all we need.
Run Windows commandline go: Start -> Run, type cmd
These commands should work and produce output similar to one shown on screenshot. It some of them produce "is not recognized as an internal or external command" make sure you've correctly done all step above.
gcc -vmake -v
qmake -v
Automated installer installs both debug and release version of Qt. Release version is smaller (QtCore4.dll, ...) and is used for production state of software. Debug version (QtCore4d.dll, ...) is much bigger and is used if you need to debug program during development.
If you decide to compile Qt on Windows from sources, here are is how.
MinGW
Download and install MinGW compiler:
1. ftp://ftp.trolltech.com/misc/ , look for MinGW-3.4.2.exe (local copy) 2. http://mingw.org
You should have no problem with installation. Installer should adjust your PATH environment variable, so you should be able to run gcc from commandline. If not make also sure you have MINGW\bin (i.e C:\MinGW\bin) added to your PATH. Logout/login again or restart after installation for change of PATH to take place.
Go to MINGW\bin and create make.bat and put following lines in it: @echo off
mingw32-make %*
This causes you will have to type "make" instead of "mingw32-make" when compiling. Installer created this file automaticly and is places into QTDIR\bin.
Qt source code
Download and unpack lastest qt-win-opensource-src-4.X.X.zip from http://trolltech.com/downloads/opensource/appdev/windows-cpp to C:\qt\4.X.X or other location (path should not contain spaces!).
Compilation of Qt library
When we have Qt sources and compiler ready, we can go to next step - compilation of Qt library itself. Compilation process can take long time (2h+- on AthlonXP 2400+, 512MB RAM). On slow machines with 256MB or less RAM compilation will be misery.
Run Windows command line, go to Qt sources directory and type "configure", then "make". cd C:\qt\4.X.X
configure
make
If you need to change drive (e.g. you installed Qt in F:\qt\..), go like this: F:
cd F:\qt\4.X.X
..
..
When compilation is finished, run this command make clean
It will remove unnecessary files created during compilation and cut down size of whole directory.
See above how to do this (QTDIR, QMAKESPEC, PATH).
Final words
If we are done with compilation, go to QTDIR\examples and try to run some to see if everything is OK (e.g. examples\mainwindows\menus\release).
On linux there are no debug/release subdirectories. Binary is created directly in the main directory (it at least used to be like this).
As you can see, the directory contains subdirectories "debug" and "release" with one binary present in each. "Debug" binary is considerably bigger than "release" one. It's linked with debug version of Qt library (bin/QtGuid4.dll, QtCored4.dll, note "d" before 4) and contains many symbols and stuff useful for debuging. Release version of binary is linked with release version of Qt (bin/QtGuid.dll, QtCored.dll), and contains no debug stuff. Therefore it's smaller.
By default, Qt is compiled in both, debug and release versions. "configure" command have many switches to tune Qt, but we are happy with the defaults.
Installation on linux
Query your package manager for qt4, it's possible that QT packages are available (for development you would ideally need both "release" and "debug", but as QT compiled in debug mode is quite large, dist. packages usually have onle "release" QT version which is not suitable for debugging). I'll how few tips on compiling QT from sources.
On linux you probably have the compiler already installed, try the command gcc -v. If not found, install it (using package manager of your distribution).
Get lastest qt-x11-opensource-src-4.X.X.tar.gz from http://trolltech.com/downloads/opensource/appdev/linux-x11-cpp and unpack to ie. /usr/local/qt/4.X.X. cd /usr/local/qt/4.X.X
./configure
make
make clean
Set environment variables in your ~/.bashrc: export QTDIR=/usr/local/qt/4.X.X
export QMAKESPEC=linux-g++
Project files (.pro)
Before we start programming Qt applications it is essential to know something about project files and Qt build system. In project file (.pro) we define headers, sources, form and other files which out application consists of. You can look at some .pro files in examples directory, later we create our own project file. If we have project file (I assume one .pro file in the directory) we must run program "qmake". qmake
Qmake is nice utility which comes with Qt distribution and creates Makefile (possibly more than one) for our application (according to what is defined in pro file). Then we can run "make" (part of MinGW distribution), which take Makefile(s) created by qmake and compiles/linkes our application.
We will practice with a small exercise. Run cmd, go to QTDIR\examples\mainwindows\menus and go: make distclean // this wipes out all files except .pro and source files
qmake // creates Makefile(s)
make // compiles debug and release (normally just debug, copy menus examples elsewhere and see,
// in this case it's because of Qt configuration)
make clean // clean all temporary files (located in tmp, object files, moc generated)
make debug // compiles only debug version
make release // compiles only release version
We should now be ready to start with Qt programming.
Watch Architect Richard Gage - How Towers Fell or hi-quality 700MB avi for direct http download, torrent also available.
Qt4 tutorial for absolute beginners
<< Previous | TOC | Next >>
My first Qt GUI application
People know Qt as a library for creating GUI programs. So what I think your first question might be: How do I create some GUI program with Qt? OK, let's go to do it.
Dialog creation
First we need to create a main window of our application. Go to QTDIR\bin and launch designer.exe. We will probably be faced with New Form Dialog, just click Cancel. Then go to Edit -> User Interface Mode and choose Docked Window (this preference is of course a matter of taste, but for me is essential :-). You can also disable Action/Resources/Signal-slot editor from Tools, we won't need them for now.
Now go File -> New Form and choose Widget and click Create. Your screen should look like
this:
First thing you should do is change objectName of this widget to something reasonable, ie. myQtAppDLG.
Then change by giving the window a title, put it in the windowTitle property in Property Editor (ie. My first Qt GUI App).
Your task is to create some form like this:
We use Label, Combo Box, Text Edit, Spin Box, Check Box. Drag and drop appropriate widget from left menu to our form. We name (objectName) Browse button "pushButton_browse", Do something button "pushButton_do"... We'll need object names later when connecting with functions (slots).
To preview form, press Ctrl+R.
Final form: myqtapp.ui. If you open it in a text editor you'll see it's XML.
If we are happy with our form, it's time to create header file for this dialog. Open your favorite text editor and save the following lines as myqtapp.h
#ifndef MYQTAPP_H
#define MYQTAPP_H
#include "ui_myqtapp.h"
class myQtApp : public QWidget, private Ui::myQtAppDLG
This macro says if MYQTAPP_H is not defined, then define it and process code. It ensures that we define class only once even if this header is included from multiple sources in our application.
#include "ui_myqtapp.h"
This line is particularly important to understand. Our form created in designer is called myqtapp.ui. Forms in .ui (XML) format are converted during build process into C++ header files by UIC (User Interface Compiler). As Qt documentation says in the UIC documentation: The UIC reads an XML format user interface definition (.ui) file as generated by Qt Designer and creates a corresponding C++ header file.
If your form filename is myform.ui, uic generates ui_myform.h. No matter what name of your class (objectName) is.
It's actually a C++ definition of your dialog. To modify this header file makes no sense because it is recreated during the build process and any changes are lost.
class myQtApp : public QWidget, private Ui::myQtAppDLG
myQtApp is name of our class. myQtAppDLG is class name of the form we created in Designer. This line says our class inherit from QWidget (We have chosen QWidget then creating form. For a dialog based form, QDialog would go here.) and also private from Ui::myQtAppDLG. This is actually our form included from ui_myqtapp.h. It means we can access widgets in our form from member functions of myQtApp class. This is called The Multiple Inheritance Approach in Qt documentation.
There is also an alternative to this approach called The Single Inheritance Approach. Have a look, you may find it more convenient than multiple inheritance approach (but I don't believe it :-). Q_OBJECT
This macro expands to some definitions which are needed for signals/slots mechanism (we'll cover this later).
Important note: If Q_OBJECT macro wasn't present and you add it, do not forget to re-run "qmake" to adjust your Makefile. It will probable cause "undefined reference to vtable" errors during compilation. A lot of beginners have problems with this.
public:
myQtApp(QWidget *parent = 0);
Defines public construtor, every class must have this. QWidget *parent = 0 is an optional argument (myQtApp() constructor would also work). You may wonder what it is good for. Actually this is a customary form of widget constructor. Usually main windows and dialogs have no parent (i.e. parent == 0 ), but if somebody has a dialog that is used frequently (for example a "Find" dialog), he might want to create it once and then he might give it a parent, so that it will be destroyed automatically by Qt.
Defines some member functions of class called slots. Signals can be connected to these slots (function). When a signal is emitted, the function connected to it will trigger. We will see that later.
Ok, now let's create myqtapp.cpp file (implementation of our class defined in myqtapp.h).
#include <QtGui>
#include "myqtapp.h"
// if we include <QtGui> there is no need to include every class used: <QString>, <QFileDialog>,...
If you create new form in designer, you can choose from:
Dialog with Buttons (base class is QDialog - for dialog windows) Main window (QMainWindow - for main application windows with a menu bar, tool
bars, dock widgets and a status bar) Widget (QWidget - base class of all user interface objects)
Our form is resizeable. You can easily convert the form to unresizeable by setting minimumSize and maximumSize property the same values as geometry.
Forms with QWidget base class have minimize, maximize and close button by default.
You may wish, for example, to disable the maximize button. You can achieve this by setting windows flags. Add these lines to the constructor of myQtApp:
screenHeight = desktop->height(); // get height of screen
windowSize = size(); // size of our application window
width = windowSize.width();
height = windowSize.height();
// little computations
x = (screenWidth - width) / 2;
y = (screenHeight - height) / 2;
y -= 50;
// move window to desired coordinates
move ( x, y );
Watch Architect Richard Gage - How Towers Fell or hi-quality 700MB avi for direct http download, torrent also available.
Qt4 tutorial for absolute beginners<< Previous | TOC | Next >>
How to read Qt documentation, basic concepts
I hope previous tutorial satisfied your Qt impatience. Since this tutorial is meant for real beginners it's necessary to explain some thing about Qt documentation. Some basic concepts of Qt and C/C++ are also explained.
Basic look at class documentation
Let's have a look at http://doc.trolltech.com/4.2/qlineedit.html
Public Types
We see the part named Public Types. This is a list of public enumerated types we can use with this class. We see:Public Types
// or directly myLineEdit->setEchoMode( QLineEdit::NoEcho );
Public types are usually used in Properties. Property can have values of some of public types. We have already used Qt::WindowFlags public type in previous tutorial.
Properties
Properties can be get and set. Previous code show usual way to do it. Most important is probably text property.
Some of the properties of QLineEdit:acceptableInput : const bool
alignment : Qt::Alignment
cursorPosition : int
displayText : const QString
dragEnabled : bool
echoMode : EchoMode
..
Public Functions
Public functions are what we are most often interested in. These functions do something with an instance of the class.// we used this in previous tutorial
textEdit->append( "Path to file: " + lineEdit->text() );
Public Slots
Public Slots are functions to which we can connect signals.
In previous tutorial, we connected the signal "clicked()" of pushButton called "pushButton_clear" to slot "clear()" of "this". this means pointer to actual instance of the class (myQtApp in our case).
Assume we want to add a new button to the form in the previous tutorial. If we click it, the contents of QLineEdit will be selected. The button is named pushButton_select_all.
Signals are emitted from class, and we can connect them to a slot (or multiple slots). Signals can have parameters (a signal is actually a function). Parameters are passed to a slot when a signal is emitted. You can try this out with signal void textEdited ( const QString & text ) like this:
Connect in constructor myqtapp.cpp. Note we connect it to custom slot (function) mySlot. When signal customSignal is emited mySlot will be called with string as parameter.
Recompile and press Clear button. Note that we connected 2 signals to same slot.
Read http://doc.trolltech.com/4.2/signalsandslots.html and about automatic connections naming convenience.
Sources with custom slot and custom signal for download and compile
my_first_qt_app-custom-sig-slot.zip
Protected Functions
Protected functions are like public functions. The only difference is that these functions can be called from this class, classes derived from it and friendly classes. For better explanation refer to some C++ reference.
Static Public Members
QLineEdit doesn't have them so please look at QString documentation.
Static public members are functions we can call anywhere in the program (as long as we include <QString> or <QtCore>/<QtGui>).
In myQtApp we used QString public static function number(int):// use of static public member function QString number ( int n, int base = 10 )
if you do use an instance of a class, they won't influence it
We can nicely illustrate second statement with QProcess class.
QProcess myProcess;
myProcess.execute("some_program.exe"); // e.g. regedit.exe or whatever
// let's say we want to terminate execution of program some_program.exe
myProcess.terminate(); // doesn't work, does actually nothing because execute is static function
// if we check state of process with myProcess.state() before myProcess.terminate()
// we'll find out that it's not even running
// we must use public function to create controllable instance
// i.e. void start ( const QString & program, OpenMode mode = ReadWrite )
// instead of static execute
const QString &
Parameter definition const QString & can be found throughout all Qt documentation.
We defined our custom slot like this.
void myQtApp::mySlot(const QString& passedStr)
If you ask why we didn't define the parameter like this:
void myQtApp::mySlot(QString passedStr)
Answer is that we could with no problem. The reason why use const & is performance.
void myQtApp::mySlot(QString passedStr) {
// with this definition, a copy of passedStr is created and any changes made
// to it are lost when the subroutine ends so
passedStr = "abcd";
// would leave the variable it was called with unchanged and not set to "abcd"
..
void myQtApp::mySlot(const QString& passedStr) { // this means pass reference to the passedStr (no copy is created - saves resources) // and const says - do not allow reference to be modified ..
See this link for detail const keyword explanation.
Memory allocation on stack vs. heap
Stack/heap memory allocation is one of the fundamentals of C++ memory management. What to bear in mind is following:
We want to start a program using QProcess class.
void myQtApp::function()
{
QProcess proc; // we create this proc variable on stack
proc.start("regedit.exe"); // start program regedit.exe
}
If you call this function you would expect program regedit.exe to start. However it is actually not the case. No program is started. You'll see following error in console window instead (make sure your .pro file contains CONFIG += console). QProcess: Destroyed while process is still running.
Idea behind this is that when variables are created in a C++ program (when the variables are in scope like we did it above), the memory required to hold the variable is allocated from the program stack. When the variable goes out of scope, the memory which was taken on the stack is freed.
In our situation it means that proc variable will be destroyed right after function() returns. Brackets "{" and "}" define scope of variable, an area where proc exists. This is particularly important to remember.
Solution to this is to create variable on heap.
When memory is allocated dynamically (by the programmer using new operator) memory is taken from the heap (which consists of all of the computers virtual memory, which includes onboard RAM and space available on the disk drive.
void myQtApp::function()
{
QProcess *proc; // pointer definition
proc = new QProcess( this ); // memory allocation from heap, created with parent
Please notice that the QProcess constructor is invoked with this parent (which actually points to instance of myQtApp). If parent is destroyed all it's children is also destroyed.
Another solution is to declare proc as member variable of myQtApp.
Qt4 tutorial for absolute beginners
<< Previous | TOC | Next >>
Strings and numbers
Convenient dealing with strings and numbers is the key feature for every library/framework. Let's look at the Qt4 way.
Strings
The class mainly responsible for string handling is QString. Coveniently QStringList handles list of strings. We'll show how to use both of them.
To define string variable:
QString myStr
or with initialization:
QString myStr="hello world";
Some fun with strings:
QString str1, str2, str3;
str1 = "I love";
str2 = "strings";
// strings concatenation
str3 = str1 + " " + str2; // str3 now contains "I love strings";
str3 += " very"; // str3 = "I love strings very"
str3.append(" much"); // "I love strings very much"
// append and + operator do the same thing
str3.prepend("OH, "); // "OH, I love strings very much"
if ( str2.isEmpty() ) ... // true as well, str2 is empty string
if ( str1 == str2 ) ... // false
str1 = "word";
int size;
size = str.size(); // size of the string is 4
A really nice thing is that you don't have to care about memory allocation no matter how much string data you append. Qt handles it itself.
Strings are internaly represented as unicode characters. Sometimes conversion to 8bit form is needed. Use functions toAscii() or toLatin1() in such cases.
To get an upper or lowercase version of a string use toUpper() or toLower().
String to number conversion
A very common task is to convert a string to a number. Here's how to do it:
QString str;
int number;
double d;
str = "123";
int = str.toInt();
str = "10.987";
d = str.toDouble();
To check if the conversion was successfull (example from QString class documentation):
QString str = "FF";
bool ok;
int hex = str.toInt(&ok, 16); // hex == 255, ok == true
int dec = str.toInt(&ok, 10); // dec == 0, ok == false
Number to string conversion
This is maybe an even more common task then previous one, let's have a look at it.
// integer converstion
QString str;
str.setNum(1234); // str now contains "1234"
// double converstion
double d = 2.345;
str.setNum(d); // default format ("g"), default precision is 6, str is now "2.345000"
str.setNum(d, 'f', 3); // "2.345"
str.setNum(d, 'e', 3); // "2.345e+00"
Refer to arg() functions for format details.
In some situations it is more convenient to use static function number().
int myInt = 123;
QMessageBox(this, "Some label", "Hello, value of integer called myInt is " + QString::number(myInt) );
Please read QString class reference for complex information how to deal with strings in Qt.
QStringList class
This class is very handy if you need a list of strings.
// these 3 ways of adding string to list are equivalent
list.append("apple");
list += "banana";
list << "submarine";
// iterate over string list
QString str;
for (int i = 0; i < list.size(); ++i)
{
str = list[i]; // or list.at(i);
// do something with str
}
Allocation of memory is handled by Qt itself.
Please read QStringList class reference for details.
make sure that debug version of binary is compiled, do not forget to specify this in .pro file (no matter which platform). Keep in mind that it only has effect if you have QT compiled in debug mode (or both - debug and release). Some linux distros may ship QT compiled in just "release" mode. In that case you have to compile QT yourself, see preparations.CONFIG += debug
When developing on Windows it is essential to enable console application output. Add this into your .pro file:CONFIG += console
Juswant to debug Qt application on Windows you can use some basic debugging techniques provided by Qt.
To t run binary from console:cd myqtapp_directory
./myqtapp
Re-run "qmake" and recompile with "make". If you get strange errors, try to run "make distclean" first.
When application is run following message appears in console:
See also Debugging Techniques in Qt documentation.
Using debugger (GDB)
If your app unexpectedly crashes you need to use debugger to see what happened.
We'll show some basic usage of gdb - GNU Debugger for windows (console application). You can download and install it from http://mingw.org. I recommend GDB 6.x.
Make sure to add path of gdb.exe to PATH environment variable. When you invoke gdb -v from commandline you should see gdb version report.
Sometimes there are situations where we need to override some methods or add new methods/signal/slots to the widgets (i.e. when adding drag & drop capability). We'll show how to do this with Designer (and eventually without it :-).
Launch Designer and create new widget. Put Tree Widget there. Add some items and subitems by right clicking and choosing Edit Items.
Vertical layout is applied to the form. Name it myFormDLG (objectName).
Save form as myform.ui. You will also need main.cpp, as well as a myqtapp.cpp and myqtapp.h. Make application work. See My first Qt GUI application if you forgot.
If you are ready with application, Right click treeWidget and choose Promote to Custom Widget. Choose custom class name (myTreeWidget). Save form.
If you now try to build application, you'll get:ui_myform.h:11:26: mytreewidget.h: No such file or directory
Architect Richard Gage - How Towers Fell or hi-quality 700MB avi for direct http download , torrent also available.
Qt4 tutorial for absolute beginners
<< Previous | TOC | Next
Watch
Architect Richard Gage - How Towers Fell or hi-quality 700MB avi for direct http download , torrent also available.
Qt4 tutorial for absolute beginners
<< Previous | TOC
Threads
I was very politely asked to write a chapter that would illustrate basic use of threads in Qt4, so here it is. Greetings to azark :-]
The purpose of this tutorial is to show how to run some computations in new thread (in order not to block main window). We'll change our My first Qt GUI application .
Download complete project my_first_qt_app-threaded.zip and try.
Things to notice about threads
Bear in mind that two or more threads cannot simultaneously access one device/widget during a write operation. If you lanuch 2 threads and each will write to, for instance textEdit, your application will crash. Some locking mechanism (mutex, semaphore, wait condition) must be used to handle access in a non-conflicting way. If you just need read access, it's OK from as many threads as you want.