300 likes | 323 Views
Using Qt for GUI development. Brad Whitlock March 2002. Outline. GUI toolkits What is Qt? Qt Features Signals and slots Examples Creating a custom widget Networking. What makes a good GUI Toolkit?. Implementation language Easy to program Consistent interface
E N D
Using Qt for GUI development Brad Whitlock March 2002
Outline • GUI toolkits • What is Qt? • Qt Features • Signals and slots • Examples • Creating a custom widget • Networking
What makes a good GUI Toolkit? • Implementation language • Easy to program • Consistent interface • Little code for large results • Excellent documentation • Availability of tools for code generation • Portability • Easy to extend
Some GUI Toolkits • Qt • Written in C++ • Qt programs are portable • Object oriented. Allows your window to be encapsulated into a real C++ class • Easy to hand code • GTK • Written in C • GTK programs are mostly limited to UNIX though GTK does exist on other platforms • Not object oriented • Motif • Written in C • Motif programs are limited to UNIX • Not object oriented • Difficult to hand code • MFC • MFC programs are limited to Windows
Qt Background • Created and maintained by Trolltech since 1995 • Now on version 3.0.2 • Foundation of KDE a popular Linux desktop environment
What is Qt? Qt is a C++ toolkit for cross-platform GUI and application development. It lets application developers target all major operating systems with a single application source code. • Supported platforms • UNIX • MS Windows 9x/NT/2000/XP • Mac OS X • Embedded (PDA’s)
Features • Fully object-oriented • Consistent interfaces • Rich set of widgets (controls) • Have native look and feel • Drag and drop • Customizable appearance • Utility classes • OpenGL support • Network support • Database support • Plugin support • Unicode/Internationalization support • GUI builder
Utility classes This is a sample of the dozens of utility classes provided by Qt. Containers • QString – String class • QList – Template List class • QMap – Template map class Program • QThread – Platform independent threads • QProcess – Launches processes and communicates with them XML • QXmlSimpleReader – Simple XML reader
Widgets A widget is a user interface component such as a button or a scroll-bar • Reusable! • Well defined interface • Uses C++ inheritance • All widgets derive from a common base • Widgets may contain other widgets • Custom widgets can be created from existing widgets or they can be created from scratch
Qt Built-in dialogs • File dialog • Font dialog • Color dialog • Printer dialog
OpenGL Support • QGLWidget • Subclass of QWidget so it behaves like any other QWidget • Gives you access to the OpenGL context • Can make raw OpenGL function calls
Remote files accessed using the FTP and HTTP protocols New protocols can be implemented by subclassing QNetworkProtocol Inter-process communication and socket-based TCP and UDP networking are also fully supported QSocket and QServerSocket provide socket communication Network support
Cross platform interface for accessing SQL databases Supported Databases Oracle Microsoft SQL Server Sybase Adaptive Server PostgreSQL MySQL ODBC Any Qt widget can be made data aware SQL module fully integrated into Qt designer Database support
Plugin support • Style plugins • Image readers/writers • Widget plugins • Netscape plugins
Unicode/Internationalization • Programmer can freely mix any language supported by Unicode • Includes tools to support application translation • Qt Linguist • Can identify strings that need translation in the source code using tr() • Button->setText(tr(“Save”));
Qt Designer • Written using Qt so it is available on all platforms where Qt is available • Used to speed design of Qt applications • Supports all Qt widgets and can be used to incorporate custom widgets
#include <qapplication.h> #include <qlabel.h> int main(int argc, char *argv[]) { // Create an application object QApplication *app = new QApplication(argc, argv); // Create a label QLabel *label = new QLabel(“Hello World!”, 0, “label”); app->setMainWidget(label); // Show the label and enter the main loop label->show(); int ret =app->exec(); // Clean up omitted return ret; } QApplication Manages widget style, colors, global preferences Operates main event loop and dispatches events to other objects Hello World!
Using Layouts Layouts should be used to manage widget position and resize behavior • Layout types • Horizontal • Vertical • Grid • Layouts can be nested • User can control layout spacing, stretch, and strut
Signals and Slots • Facilitates inter-object communication • Replaces callback mechanism found in older toolkits • Type safe since arguments for signal must match arguments slot • Objects don’t have to care about other objects. • Can be overloaded or re-implemented in subclasses • Signals can be connected to multiple slots or other signals
Signals and Slots 2 • An object emits a signal with a certain prototype • Other objects may be connected to that object’s signal • connect(button, SIGNAL(clicked()), qApp, SLOT(quit())); • The slot functions for all the connected objects are called
Example class BankAccount : public QObject { Q_OBJECT Public: BankAccount() { curBalance = 0; } int balance() const { return curBalance; } signals: void balanceChanged(int newBalance); publicslots: void setBalance(int newBalance) { if(curBalance != newBalance) { curBalance = newBalance; emit balanceChanged(curBalance); } } private: int curBalance; }; Usage // Create 2 accounts that have zero balance BankAccount x, y; // Connect account x to account y so that // whenever it gets money, account y gets // the same amount. connect(&x, SIGNAL(balanceChanged(int)), &y, SLOT(setBalance(int))); // Set the balance for account x x.setBalance(2450); // Account y also now has $2450 Signals and Slots 3
Building classes that have signals and slots • Class definition must contain Q_OBJECT macro • Slots are defined with slots “keyword” • Can be declared public, protected, private • Signals are declared with signals “keyword” • Qt provides the body for a signal function • MOC preprocessor • Reads class header file and creates supplementary C++ code to support signals/slots • All header files for classes defining signals/slots need to use MOC • Easily incorporated into Make rules • Transparent to user
Derive from an existing class Customize behavior by overriding member functions Creating a custom widget • Derive from the base class • Provide all relevant behavior by overriding or adding member functions
Simple custom widget #ifndef SIMPLE_H #define SIMPLE_H #include <qwidget.h> #include <qtimer.h> #include <qpainter.h> #include <qpointarray.h> class Simple : public QWidget { Q_OBJECT public: Simple(QWidget *parent, const char *name) : QWidget(parent, name), shape(4) { angle = 0.; timer = new QTimer(this,"timer"); connect(timer, SIGNAL(timeout()), this, SLOT(rotateAngle())); shape.setPoint(0, QPoint(-50, -50)); shape.setPoint(1, QPoint(50, -50)); shape.setPoint(2, QPoint(50, 50)); shape.setPoint(3, QPoint(-50, 50)); setMinimumSize(200,200); } virtual ~Simple() { timer->stop(); }; virtual QSize sizeHint() { return QSize(200,200); }; publicslots: virtual void show() { timer->start(50); QWidget::show(); } virtual void hide() { timer->stop(); QWidget::hide(); } protected: virtual void paintEvent(QPaintEvent *pe) { QPainter paint(this); paint.setBrush(QColor(0,0,255)); QWMatrix m1; m1.rotate(-angle); QWMatrix m2; m2.translate(width()/2,height()/2); QWMatrix m3 = m1*m2; paint.setWorldMatrix(m3, TRUE); paint.drawPolygon(shape); } privateslots: void rotateAngle() { angle += 3.; if(angle >= 360.) angle -= 360.; update(); } private: QTimer *timer; double angle; QPointArray shape; }; #endif
Simple custom widget 2 #include <Simple.h> #include <qapplication.h> #include <qvbox.h> #include <qpushbutton.h> int main(int argc, char *argv[]) { QApplication *app = new QApplication(argc, argv); QVBox *top = new QVBox; app->setMainWidget(top); Simple *s = new Simple(top, "simple"); QPushButton *btn = new QPushButton("Quit", top, "btn"); app->connect(btn, SIGNAL(clicked()), qApp, SLOT(quit())); top->show(); int ret = app->exec(); delete top; delete app; return ret; }
Simple networking example Class MessagePrinter : public QObject { Q_OBJECT Public: MessagePrinter(const QString &host, int port) : QObject() { // Create a new socket and connect to a port. S = new QSocket(this); connect(S, SIGNAL(readyRead()), this, SLOT(readMessage())); S->connectToHost(host, port); } virtual ~MessagePrinter() { S->close(); }; Privateslots: void readMessage() { if(S->canReadLine()) { qDebug(“MSG=%s”, S->readLine().latin1()); S->close(); } } Private: QSocket *S; };
VisIt • Developed here at LLNL • Uses Qt 2.3 or greater • Hand coded windows • Custom widgets • OpenGL • Uses some Qt networking code
Qt licensing • Qt Free Edition • For UNIX/X11 • Version 2.2 and later • Open source license QPL and GPL • May be freely copied and distributed • Binaries may be redistributed • Users creating closed source projects must purchase a development license from Trolltech
Where to find Qt • On the Web • http://www.trolltech.com • On LC computers • /usr/gapps/visit/qt/current/<platform>/