Professional Documents
Culture Documents
Untitled
Untitled
Untitled
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.
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.
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.
MinGW
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
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
..
..
It will remove unnecessary files created during compilation and cut down size of whole directory.
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).
./configure
make
make clean
export QMAKESPEC=linux-g++
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.
make // compiles debug and release (normally just debug, copy menus examples
elsewhere and see,
make clean // clean all temporary files (located in tmp, object files, moc
generated)
Watch Architect Richard Gage - How Towers Fell or hi-quality 700MB avi for direct http download,
torrent also available.
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).
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).
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"
{
Q_OBJECT
public:
public slots:
void getPath();
void doSomething();
void clear();
void about();
};
#endif
#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.
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:
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)
void myQtApp::getPath()
QString path;
path = QFileDialog::getOpenFileName(
this,
QString::null,
QString::null);
lineEdit->setText( path );
}
void myQtApp::doSomething()
Qt::CheckState state;
QString str;
value1 = spinBox1->value();
value2 = spinBox2->value();
state = checkBox->checkState();
textEdit->append( str );
}
void myQtApp::clear()
textEdit->clear();
void myQtApp::about()
QMessageBox::about(this,"About myQtApp",
"Bye.\n");
#include <QApplication>
#include "myqtapp.h"
dialog->show();
return app.exec();
}
Now we have all we need to create the project file myqtapp.pro HEADERS =
myqtapp.h
FORMS = myqtapp.ui
# install
target.path = myqtapp
sources.path = .
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.
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;
setWindowFlags( flags );
Result:
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.
int x, y;
QSize windowSize;
screenWidth = desktop->width(); // get width of screen
width = windowSize.width();
height = windowSize.height();
// little computations
x = (screenWidth - width) / 2;
y = (screenHeight - height) / 2;
y -= 50;
move ( x, y );
Watch Architect Richard Gage - How Towers Fell or hi-quality 700MB avi for direct
http download, torrent also available.
// some code
..
QLineEdit::EchoMode mode;
mode = myLineEdit->echoMode();
...
mode = QLineEdit::NoEcho;
myLineEdit->setEchoMode( mode );
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.
alignment : Qt::Alignment
cursorPosition : int
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
Public Slots
Public Slots are functions to which we can connect signals.
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
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:
public slots:
..
..
..
..
Now if you edit the contents of lineEdit, QMessageBox will show up.
Please note that example below uses custom slot we defined above. Before you
proceed add custom slot as shown above.
myqtapp.h
public:
signals:
void customSignal( const QString& );
..
void myQtApp::clear()
textEdit->clear();
Recompile and press Clear button. Note that we connected 2 signals to same slot.
Static public members are functions we can call anywhere in the program (as long as
we include <QString> or <QtCore>/<QtGui>).
Remember 2 things:
QProcess myProcess;
// i.e. void start ( const QString & program, OpenMode mode = ReadWrite )
Answer is that we could with no problem. The reason why use const & is performance.
// with this definition, a copy of passedStr is created and any changes made
passedStr = "abcd";
// would leave the variable it was called with unchanged and not set to "abcd"
..
void myQtApp::function()
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.
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()
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.
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:
str2 = "strings";
// strings concatenation
str3 = str1 + " " + str2; // str3 now contains "I love strings";
// strings comparison
str2 = "";
str1 = "word";
int size;
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.
QString str;
int number;
double d;
str = "123";
int = str.toInt();
str = "10.987";
d = str.toDouble();
bool ok;
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;
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;
list.append("apple");
list += "banana";
QString str;
for (int i = 0; i < list.size(); ++i)
./myqtapp
Re-run "qmake" and recompile with "make". If you get strange errors,
try to run "make distclean" first.
void myQtApp::clear()
textEdit->clear();
qDebug() << "Widget" << this << "at position" << this->pos();
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.
void myQtApp::clear()
QProcess *proc;
..
105 delete p;
Backtrace
at kernel/qobject.cpp:2809
at kernel/qobject.cpp:2860
..
..
If you would like to redirect GDB output, use following gdb command
(works with GDB 6.x):(gdb) set logging on
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).
If you are ready with application, Right click treeWidget and choose
Promote to Custom Widget. Choose custom class name (myTreeWidget).
Save form.
#ifndef MYTREEWIDGET_H
#define MYTREEWIDGET_H
#include <QtGui>
Q_OBJECT
public:
};
#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.
Watch
Architect Richard Gage - How Towers Fellor hi-quality 700MB avi for
direct http download, torrentalso available.
Watch
Architect Richard Gage - How Towers Fellor hi-quality 700MB avi for
direct http download, torrentalso available.
Valuable drag and drop examples for beginner are not present in Qt
distribution, so let's have a closer look at it.
tutorial.
if (event->mimeData()->hasFormat("text/uri-list"))
event->acceptProposedAction();
QList<QUrl> urlList;
QString fName;
QFileInfo info;
if (event->mimeData()->hasUrls())
{
fName = urlList[0].toLocalFile(); // convert first QUrl
to local path
event->acceptProposedAction();
You may think we will do the same as with QLineEdit, but setup is
little different.
mytreewidget.cpp
QList<QUrl> urlList;
QTreeWidgetItem *item;
urlList = data->urls(); // retrieve list of urls
else
parent->setExpanded( true );
item->setText( 0, url.toLocalFile() );
return true;
{
QStringList qstrList;
qstrList.append("text/uri-list");
return qstrList;
mylistwidget.h
mylistwidget.cpp
QFileInfo info;
QString fName;
fName = url.toLocalFile();
info.setFile( fName );
insertItem(index, item);
return true;
}
Qt::DropActions myListWidget::supportedDropActions () const
mylistwidget.h
mylistwidget.cpp
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);
Watch
Architect Richard Gage - How Towers Fellor hi-quality 700MB avi for
direct http download, torrentalso available.
Watch
Architect Richard Gage - How Towers Fellor hi-quality 700MB avi for
direct http download, torrentalso available.
#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QtGui>
{
Q_OBJECT
public:
MyThread(QObject *parent);
};
#endif
mythread.cpp
#include "mythread.h"
MyThread::MyThread(QObject *parent)
: QThread(parent)
void MyThread::run()
for(int i=0;i<10;i++)
#ifdef Q_OS_WIN32
t = t * 1000;
_sleep(t);
#else
sleep(t);
#endif
exec();
}
App in action:
Watch
Architect Richard Gage - How Towers Fellor hi-quality 700MB avi for
direct http download, torrentalso available.