Top Banner
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)
53
Welcome message from author
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
Page 1: Untitled

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)

Page 2: Untitled

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

Page 3: Untitled

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

Page 4: Untitled

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

Page 5: Untitled

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.

Page 6: Untitled

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.

Page 7: Untitled

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

Page 8: Untitled

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();

Page 9: Untitled

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,

Page 10: Untitled

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() );

Page 11: Untitled

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();

Page 12: Untitled

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!

Page 13: Untitled

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

Page 14: Untitled

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.

Page 15: Untitled

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

Page 16: Untitled

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&) ) );

Page 17: Untitled

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();

}

Page 18: Untitled

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

Page 19: Untitled

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"

..

Page 20: Untitled

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

}

Page 21: Untitled

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"

Page 22: Untitled

// 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();

Page 23: Untitled

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;

Page 24: Untitled

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

Page 25: Untitled

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:

Page 26: Untitled

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

Page 27: Untitled

}

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)

Page 28: Untitled

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:

Page 29: Untitled

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.

 

Page 30: Untitled

 

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

Page 31: Untitled

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

... more errors here

Page 32: Untitled

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)

{

Page 33: Untitled

}

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 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 | 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 widgets and have a look at Qt documentation about drag&drop before reading this.

Page 34: Untitled

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

Page 35: Untitled

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

Page 36: Untitled

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

Page 37: Untitled

{

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

}

Page 38: Untitled

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

Page 39: Untitled

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.

Page 40: Untitled

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);

}

Page 41: Untitled

Project ready: drag_and_drop.zip

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

 

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 .

Page 43: Untitled

#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);

Page 44: Untitled

#else

sleep(t);

#endif

}

qDebug() << "Execution done";

exec();

}

App in action:

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.