Untitled

You might also like

Download as doc, pdf, or txt
Download as doc, pdf, or txt
You are on page 1of 49

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 is how it should look like:

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 -v
make -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.

Compiling Qt from sources on Windows

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.

Adjusting environment variables

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.

Application sources
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

{
Q_OBJECT

public:

myQtApp(QWidget *parent = 0);

public slots:

void getPath();

void doSomething();

void clear();

void about();

};

#endif

Let's look at this code line by line.

#ifndef MYQTAPP_H

#define MYQTAPP_H

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.

public slots:

void getPath();

void doSomething();

void clear();

void about();

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>,...

myQtApp::myQtApp(QWidget *parent)

setupUi(this); // this sets up GUI

// signals/slots mechanism in action

connect( pushButton_browse, SIGNAL( clicked() ), this, SLOT( getPath() ) );

connect( pushButton_do, SIGNAL( clicked() ), this, SLOT( doSomething() ) );

connect( pushButton_clear, SIGNAL( clicked() ), this, SLOT( clear() ) );

connect( pushButton_about, SIGNAL( clicked() ), this, SLOT( about() ) );

void myQtApp::getPath()

QString path;

path = QFileDialog::getOpenFileName(

this,

"Choose a file to open",

QString::null,

QString::null);

lineEdit->setText( path );

}
void myQtApp::doSomething()

int value1, value2;

Qt::CheckState state;

QString str;

textEdit->append( "Path to file: " + lineEdit->text() );

value1 = spinBox1->value();

value2 = spinBox2->value();

textEdit->append( "Number 1 value: " + QString::number(value1) );

textEdit->append( "Number 2 value: " + QString::number(value2) );

state = checkBox->checkState();

str = "Checkbox says: ";

if ( state == Qt::Checked ) str += "yes";

else str += "no";

textEdit->append( str );

textEdit->append( "ComboBox current text: " + comboBox->currentText() );

textEdit->append( "ComboBox current item: " + QString::number(comboBox-


>currentIndex()) );

}
void myQtApp::clear()

textEdit->clear();

void myQtApp::about()

QMessageBox::about(this,"About myQtApp",

"This app was coded for educational purposes.\n"

"Number 1 is: " + QString::number(spinBox1->value()) + "\n\n"

"Bye.\n");

We need to create main.cpp

#include <QApplication>

#include "myqtapp.h"

int main(int argc, char *argv[])

QApplication app(argc, argv);

myQtApp *dialog = new myQtApp;

dialog->show();

return app.exec();
}

Now we have all we need to create the project file myqtapp.pro HEADERS =
myqtapp.h

SOURCES = myqtapp.cpp main.cpp

FORMS = myqtapp.ui

# install

target.path = myqtapp

sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS *.pro

sources.path = .

INSTALLS += target sources

It is possible to generate the .pro file automaticly with qmake -project command.

Compilation
Applicaton zipped: my_first_qt_app.zip

Run windows cmd, go to the directory with application sources and type: qmake

make

After successful compilation and linking, myqtapp.exe will be created in "debug" folder.

Congratulations, you have done your first Qt GUI application!


Things to notice and tips
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:

// constructor code

setupUi( this );

Qt::WindowFlags flags;

flags = Qt::Window | Qt::WindowMinimizeButtonHint;

setWindowFlags( flags );

Result:

Have a look at Qt doc http://doc.trolltech.com/4.2/qwidget.html#windowFlags-prop

You may want window to start at the center of the screen. This code does the job. Add it after line
setupUi( this ); in the constructor.

QDesktopWidget *desktop = QApplication::desktop();

int screenWidth, width;

int screenHeight, height;

int x, y;

QSize windowSize;
screenWidth = desktop->width(); // get width of screen

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

enum EchoMode { Normal, NoEcho, Password, PasswordEchoOnEdit }

This says we can use type QLineEdit::EchoMode.

// some code

..

QLineEdit::EchoMode mode;

mode = myLineEdit->echoMode();

...

mode = QLineEdit::NoEcho;

myLineEdit->setEchoMode( mode );

// 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).

connect( pushButton_clear, SIGNAL( clicked() ), this, SLOT( clear() ) );

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.

connect( pushButton_select_all, SIGNAL( clicked() ), lineEdit,


SLOT( selectAll() ) );

You can try to add it to myQtApp.

Signals
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:

Define custom slot in myQtApp, in myqtapp.h.

public slots:

..

void mySlot(const QString&);

Implement mySlot in myqtapp.cpp

void myQtApp::mySlot(const QString& passedStr)

QMessageBox::information(this, "Some window label here", "String: " +


passedStr);

And connect in constructor myqtapp.cpp.


myQtApp::myQtApp(QWidget *parent)

..

// signals/slots mechanism in action

..

..

connect( lineEdit, SIGNAL( textEdited (const QString&) ), this, SLOT( mySlot(const


QString&) ) );

Now if you edit the contents of lineEdit, QMessageBox will show up.

How to define a custom signal

We can also define a custom signal.

Please note that example below uses custom slot we defined above. Before you
proceed add custom slot as shown above.

myqtapp.h

public:

myQtApp(QWidget *parent = 0);

signals:
void customSignal( const QString& );

..

myqtapp.cpp - adjust myQtApp::clear(). The signal is emitted using the emit


keyword.

void myQtApp::clear()

emit customSignal( textEdit->toPlainText() );

textEdit->clear();

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.

connect( this, SIGNAL( customSignal (const QString&) ), this, SLOT( mySlot(const


QString&) ) );

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 )

textEdit->append( "Number 1 value: " + QString::number(value1) );

Remember 2 things:

• static public functions don't need an instance of class (QString) to invoke


them
• 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 &amp; 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

proc->start("regedit.exe"); // start program

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"

// strings comparison

str1 = "some nice word";

str2 = "";

if ( str1 == "some nice word" ) // true

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.

QStringList list;

// add string into the list

// 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.

If we run debug/myqtapp.exe, we see the console alongside with our


application.

Let's modify the clear() slot of our myQtApp in myqtapp.cpp:

void myQtApp::clear()

qDebug() << "myQtApp::clear() slot invoked";


qDebug() << "spinBox1 value: " << spinBox1->value();

qDebug() << "textEdit text: " << textEdit->toPlainText();

textEdit->clear();

qDebug() << "textEdit cleared";

qDebug() << "Widget" << this << "at position" << this->pos();

// qDebug() just writes to console, nothing more

Recompile, run and press Clear button.

The console catches non-fatal messages. I.e. if we connect signal to


non nonexistent slot like this:

connect( pushButton_about, SIGNAL( clicked() ), this,


SLOT( nonexistent() ) );
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.

Let's make some buggy code.

void myQtApp::clear()

QProcess *proc;

delete proc; // pointer proc is uninitialized


}

Pushing clear button produces error and application closes.

Load application into debugger.gdb debug/myqtapp.exe

GNU gdb 6.3

Copyright 2004 Free Software Foundation, Inc.

..

Now let's run program using "run".(gdb) run

Application is run in the debugger which catches fatal


message:Program received signal SIGSEGV, Segmentation fault.

0x004021d5 in myQtApp::clear() (this=0x392bff8) at myqtapp.cpp:105

105 delete p;

Backtrace

Backtrace is very usefull. It provides maximum information available


about crash. It's invoked with bt command.(gdb) bt

#0 0x004021d5 in myQtApp::clear (this=0x392bff8) at myqtapp.cpp:105

#1 0x004028f2 in myQtApp::qt_metacall (this=0x392bff8,


_c=InvokeMetaMethod,

_id=2, _a=0x22eaf0) at debug/moc_myqtapp.cpp:69

#2 0x100f8d93 in QMetaObject::activate (sender=0x392cf18,

from_signal_index=28, to_signal_index=29, argv=0x22eaf0)

at kernel/qobject.cpp:2809

#3 0x100f90c4 in QMetaObject::activate (sender=0x392cf18,


m=0xbfa2c0,
from_local_signal_index=2, to_local_signal_index=3,
argv=0x22eaf0)

at kernel/qobject.cpp:2860

..

..

To quit GDB, use "q" or "quit".

Redirecting GDB output into file

If you would like to redirect GDB output, use following gdb command
(works with GDB 6.x):(gdb) set logging on

gdb.txt will be created in current directory.

Qt4 tutorial for absolute beginners

<< Previous | TOC | Next >>

Layouts - what are they good for

Video: Playing with Designer (5 MB)

Let's show this one example.


Launch Designer and create a new widget. Make it look like this one:

Now press Ctrl+R to preview it. Try to resize it and see how it

behaves.

Sizes of the widgets stay the same no matter what the size of window
is.
Now select File label, lineEdit and Browse button and apply

horizontal layout.

OK, now click the form so no particular widget is selected. That will
select form itself (make sure topmost item in the Object Inspector is

highlighted).

Click vertial layout button.

This gives layout to form itself.

Press Ctrl+R and try to resize window.


Widgets now adapt to size of whole window. Have a look at sizePolicy
property in Property Editor and experiment with it.

Read QSizePolicy class reference.

To break layout use button.

Qt4 tutorial for absolute beginners

<< Previous| TOC| Next >>

Customing widgets (subclassing)

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
applicationif 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

... more errors here

Right, we need to define mytreewidget.h and mytreewidget.cpp files


which are actually definition and implementation our customized
treeWidget.
mytreewidget.h

#ifndef MYTREEWIDGET_H

#define MYTREEWIDGET_H

#include <QtGui>

class myTreeWidget : public QTreeWidget

Q_OBJECT

public:

myTreeWidget(QWidget *parent = 0);

};

#endif

mytreewidget.cpp

#include "mytreewidget.h"

myTreeWidget::myTreeWidget(QWidget *parent)

: QTreeWidget(parent)

}
Do not forget to add mytreewidget.h and mytreewidget.cpp to
your .pro file and re-run qmake to update makefiles.

You can add your method/signal/slots or override existing ones.

Project ready: custom_treewidget.zip

Watch

Architect Richard Gage - How Towers Fellor hi-quality 700MB avi for
direct http download, torrentalso available.

Qt4 tutorial for absolute beginners

<< Previous| TOC| Next >>

Watch

Architect Richard Gage - How Towers Fellor hi-quality 700MB avi for
direct http download, torrentalso available.

Qt4 tutorial for absolute beginners

<< Previous| TOC| Next >>

Drag and drop

Video: Drag and Drop(5 MB)

Valuable drag and drop examples for beginner are not present in Qt
distribution, so let's have a closer look at it.

Please read customing widgetsand have a look at Qt documentation


about drag&dropbefore reading this.
Adjust the form from previous tutorial, place QLineEdit, QTreeWidget

and QListWidget on it.

Promote QLineEdit, QTreeWidget and QListWidget to promote widgets and


create appropriate .h and .cpp files like we did in previous

tutorial.

Make sure acceptDrops property is set to true on each of them.

Add drop capability to customized QLineEdit

We will implement drop capability to QLineEdit (now myLineEdit). When


file is dropped (but not directory), path will appear in myLineEdit.

Define the following methods in mylineedit.h

void dragEnterEvent(QDragEnterEvent *event);

void dropEvent(QDropEvent *event);


and implement in mylineedit.cpp

void myLineEdit::dragEnterEvent(QDragEnterEvent *event)

// accept just text/uri-list mime format

if (event->mimeData()->hasFormat("text/uri-list"))

event->acceptProposedAction();

void myLineEdit::dropEvent(QDropEvent *event)

QList&lt;QUrl&gt; urlList;

QString fName;

QFileInfo info;

if (event->mimeData()->hasUrls())

urlList = event->mimeData()->urls(); // returns list of QUrls

// if just text was dropped, urlList is empty (size == 0)

if ( urlList.size() > 0) // if at least one QUrl is present


in list

{
fName = urlList[0].toLocalFile(); // convert first QUrl
to local path

info.setFile( fName ); // information about file

if ( info.isFile() ) setText( fName ); // if is file,


setText

event->acceptProposedAction();

Recompile and try to drop file (from explorer) into customized


QLineEdit.

Drop to customized QTreeWidget

You may think we will do the same as with QLineEdit, but setup is
little different.

If you look at Protected Functions of QTreeWidget you'll see some


virtual functions responsible for drag/drop.

To actually implement drop on QTreeWidget, define following methods


in mytreewidget.h

virtual bool dropMimeData(QTreeWidgetItem *parent, int index, const


QMimeData *data, Qt::DropAction action);

QStringList mimeTypes() const;

Qt::DropActions supportedDropActions () const;

mytreewidget.cpp

bool myTreeWidget::dropMimeData(QTreeWidgetItem *parent, int index,


const QMimeData *data, Qt::DropAction action)

QList<QUrl> urlList;

QTreeWidgetItem *item;
urlList = data->urls(); // retrieve list of urls

foreach(QUrl url, urlList) // iterate over list

// make new QTreeWidgetItem and set its text

// if parent is null - add top level item (this parent)

if (parent == NULL) item = new QTreeWidgetItem(this);

else

// else add QTreeWidgetItem with parent and expand parent

item = new QTreeWidgetItem(parent);

parent->setExpanded( true );

// set item text

item->setText( 0, url.toLocalFile() );

return true;

QStringList myTreeWidget::mimeTypes () const

{
QStringList qstrList;

// list of accepted mime types for drop

qstrList.append("text/uri-list");

return qstrList;

Qt::DropActions myTreeWidget::supportedDropActions () const

// returns what actions are supported when dropping

return Qt::CopyAction | Qt::MoveAction;

DragDropOverwriteMode property can be enabled to enhance visual


effect when dropping.

Drop to customized QListWidget

This is pretty much same as with QTreeWidget. The only difference is


different parameters list in function dropMimeData.

mylistwidget.h

virtual bool dropMimeData(int index, const QMimeData *data,


Qt::DropAction action);

QStringList mimeTypes() const;

Qt::DropActions supportedDropActions () const;

mylistwidget.cpp

bool myListWidget::dropMimeData(int index, const QMimeData *data,


Qt::DropAction action)

QList <QUrl> urlList;


QListWidgetItem *item;

QFileInfo info;

QString fName;

urlList = data->urls(); // retrieve list of urls

foreach(QUrl url, urlList) // iterate over list

fName = url.toLocalFile();

info.setFile( fName );

item = new QListWidgetItem(info.fileName());

insertItem(index, item);

++index; // increment index to preserve drop order

return true;

QStringList myListWidget::mimeTypes () const

// same as with QTreeWidget

}
Qt::DropActions myListWidget::supportedDropActions () const

// same as with QTreeWidget

Drag from customized QListWidget

To implement drag operation, override mouseMoveEvent(QMouseEvent


*event) method.

mylistwidget.h

void mouseMoveEvent(QMouseEvent *event);

mylistwidget.cpp

void myListWidget::mouseMoveEvent(QMouseEvent *event)

// if not left button - return

if (!(event->buttons() & Qt::LeftButton)) return;

// if no item selected, return (else it would crash)

if (currentItem() == NULL) return;

QDrag *drag = new QDrag(this);

QMimeData *mimeData = new QMimeData;

// construct list of QUrls

// other widgets accept this mime type, we can drop to them

QList<QUrl> list;
list.append(QUrl(currentItem()->text())); // only QUrl in list
will be text of actual item

// mime stuff

mimeData->setUrls(list);

drag->setMimeData(mimeData);

// start drag

drag->start(Qt::CopyAction | Qt::MoveAction);

Project ready: drag_and_drop.zip

Watch

Architect Richard Gage - How Towers Fellor hi-quality 700MB avi for
direct http download, torrentalso available.

Qt4 tutorial for absolute beginners

<< Previous| TOC| Next

Watch

Architect Richard Gage - How Towers Fellor hi-quality 700MB avi for
direct http download, torrentalso 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.

New user interface:

Let's implement mythread.h and mythread.cpp

mythread.h - subclass of QThread

#ifndef MYTHREAD_H

#define MYTHREAD_H

#include <QtGui>

class MyThread : public QThread

{
Q_OBJECT

public:

MyThread(QObject *parent);

void run(); // this is virtual method, we must implement it in


our subclass of QThread

};

#endif

mythread.cpp

#include "mythread.h"

MyThread::MyThread(QObject *parent)

: QThread(parent)

void MyThread::run()

qDebug() << "Executing in new independant thread, GUI is NOT


blocked";

for(int i=0;i<10;i++)

qDebug() << "Time: " << 10-i;


int t=1;

// some OS specific stuff

// mingw (3.4.2) sleep on windows is called _sleep and uses


microseconds

#ifdef Q_OS_WIN32

t = t * 1000;

_sleep(t);

#else

sleep(t);

#endif

qDebug() << "Execution done";

exec();

}
App in action:

Download complete project my_first_qt_app-threaded.zipand 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.

Now read QThread, I hope you'll understand it better after reading


this.

Ideas how to improve this tutorial are welcome.

Watch

Architect Richard Gage - How Towers Fellor hi-quality 700MB avi for
direct http download, torrentalso available.

Qt4 tutorial for absolute beginners

<< Previous| TOC

You might also like