Anda di halaman 1dari 55

Qt

UI Development

Qt is 2009 Nokia Corporation and/or its subsidiaries. Nokia, Qt, Qt Development Frameworks and their respective logos are trademarks of Nokia Corporation in Finland and/or other countries worldwide.

Andreas Jakl, 2009

v2.0 28 October 2009

Disclaimer

These slides are provided free of charge at http://www.symbianresources.com and are used for trainings and during courses at the Upper Austria University of Applied Sciences, Campus Hagenberg, Austria ( http://www.fh-ooe.at/mc ) Respecting the copyright laws, you are allowed to use them:

for your own, personal, non-commercial use in the academic environment

In all other cases (e.g. for commercial training), please contact andreas.jakl@fh-hagenberg.at The correctness of the contents of these materials cannot be guaranteed. Andreas Jakl is not liable for incorrect information or damage that may arise from using the materials. Parts of these materials are based on books listed at the end of the slides of unit 1 and on official Qt documentation and source code. This document contains copyright materials which are proprietary to Qt Development Frameworks and Nokia. Qt, S60 and their respective logos are a trademark of Nokia. Pictures of mobile phones or applications are copyright their respective manufacturers / developers. Symbian , Symbian OS and all other Symbian-based marks and logos are trademarks of Symbian Foundation. All other trademarks are property of their respective owners.

Andreas Jakl, 2009

Contents

Subclassing Widgets (Signals & Slots, continued) Dialogs Main Window

Menus, Toolbars and Actions


Properties Data Types Internationalization
3 Andreas Jakl, 2009

Sending Values through Signals & Slots

Subclassing Widgets

Andreas Jakl, 2009

Signal and Slots, Continued

How to accomplish the following?

QObject::connect(button, SIGNAL(clicked()), label, SLOT(setText("new text")));

doesnt work that way, clicked()-signal doesnt give required number of arguments to setText()-slot.

Andreas Jakl, 2009

Custom Widgets (Slots)

Commonly used: subclass widgets to extend functionality


Class MyWindow is a widget (parent) Also manages child widgets Put text to display into this slot method instead of the connect statement

Widget adds new slot

Andreas Jakl, 2009

#include <QtGui/QApplication> #include "MyWindow.h"

Custom Widgets (Slots)


myWindow.h
#ifndef MYWINDOW_H #define MYWINDOW_H #include #include #include #include #include <QWidget> <QVBoxLayout> <QPushButton> <QLabel> <QObject>

myWindow.cpp
#include "MyWindow.h"

int main(int argc, char *argv[]) { QApplication a(argc, argv); MyWindow* window = new MyWindow(); window->show(); return a.exec(); }

main.cpp

MyWindow::MyWindow(QWidget* parent) : QWidget(parent) { label = new QLabel("old text"); button0 = new QPushButton("Update labels"); button1 = new QPushButton("Exit"); layout = new QVBoxLayout(this); layout->addWidget(button0); layout->addWidget(button1); layout->addWidget(label); setLayout(layout);

class MyWindow : public QWidget { Q_OBJECT public: MyWindow(QWidget *parent = 0); private: QLabel* label; QPushButton* button0; QPushButton* button1; QVBoxLayout* layout; }; private slots: void setText(); }; #endif // MYWINDOW_H

connect(button0, SIGNAL(clicked()), this, SLOT(setText())); connect(button1, SIGNAL(clicked()), this, SLOT(close()));

void MyWindow::setText() { label->setText("new text"); }

Andreas Jakl, 2009

Signals and Slots, Once More!

How to accomplish the following without writing three extra slots?

Andreas Jakl, 2009

Custom Widgets (Signals)

Subclass QPushButton to create a new ...


Signal: clicked(int) Called whenever button is clicked (internal signal slot connection) Emits the clicked() event plus int parameter
MyButton Signals clicked() clicked(int) Slots click() Slots myMsgBox(int) MyWindow Signals

Andreas Jakl, 2009

Custom Widgets (Slots) MyButton


myButton.h
#ifndef MYBUTTON_H #define MYBUTTON_H #include <QPushButton> #include <QWidget> #include <QString> class MyButton : public QPushButton { Q_OBJECT public: MyButton(const QString& text, int id, QWidget* parent = NULL); MyButton(const QString& text, QWidget* parent = NULL); private: static int nextId; int m_id; public slots: void click();

myButton.cpp
#include "mybutton.h" int MyButton::nextId = 0; MyButton::MyButton(const QString& text, int id, QWidget* parent) : QPushButton(text, parent), m_id(id) { connect(this, SIGNAL(clicked()), this, SLOT(click())); } MyButton::MyButton(const QString& text, QWidget* parent) : QPushButton(text, parent), m_id(nextId++) { connect(this, SIGNAL(clicked()), this, SLOT(click())); } void MyButton::click() { emit clicked(m_id); }

// Overwrite click()

signals: // Add a new signal void clicked(int id); }; #endif // MYBUTTON_H

10

Andreas Jakl, 2009

Custom Widgets (Slots) MyWindow


myWindow.h
#ifndef MYWINDOW_H #define MYWINDOW_H #include #include #include #include <QWidget> <QtCore> <QtGui> "myButton.h"

myWindow.cpp
#include "myWindow.h" MyWindow::MyWindow(QWidget* parent) : QWidget(parent) { myButton[0] = new MyButton(tr("Press me")); myButton[1] = new MyButton(tr("Me too")); myButton[2] = new MyButton(tr("And me")); QVBoxLayout* layout = new QVBoxLayout(this); for (int i = 0; i < 3; i++) { layout->addWidget(myButton[i]); connect( myButton[i], SIGNAL(clicked(int)), this, SLOT(myMessageBox(int))); } // The qApp pointer is a global variable declared in // the <QApplication> header file. It points to the // application's unique QApplication instance. connect( myButton[2], SIGNAL(clicked()), qApp, SLOT(quit()) ); } void MyWindow::myMessageBox(int id) { QMessageBox::information(this, tr("A button has been clicked"), QString(tr("Button ID: %1")).arg(id), QMessageBox::Ok); }

class MyWindow : public QWidget { Q_OBJECT public: MyWindow(QWidget* parent = NULL); private: MyButton* myButton[3]; public slots: // Slot for output void myMessageBox(int id); }; #endif // MYWINDOW_H

main.cpp is similar to previous example 11

Andreas Jakl, 2009

Let users and applications talk to each other

Dialogs

12

Andreas Jakl, 2009

QObject

QPaintDevice QWidget

Dialogs

Dialog is:

QDialog

Top-level window Used for short-term tasks, brief user communication Can provide return value
Dialog blocks other application windows (e.g., file open dialog) Usually called with exec(), returns when dialog is closed Call with show(): returns immediately, get results via signals Operates independently from other windows (e.g., find & replace dialog) Always called with show(): returns immediately
13 Andreas Jakl, 2009

Modal

Modeless

Custom Dialog

clicked() signal from button in main widget triggers dialog Change label in main widget depending on user action selected in dialog

14

Andreas Jakl, 2009

Signals & Slots Diagram


okButton Signals clicked() Slots Slots exec(int) accept() reject() startButton Signals clicked() Slots

Dialog Signals accepted() rejected()

cancelButton Signals clicked() Slots

MyWindow Signals

Slots checkInputDialog()

15

Andreas Jakl, 2009

The Dialog
mydialog.h
#ifndef MYDIALOG_H #define MYDIALOG_H #include #include #include #include <QDialog> <QPushButton> <QVBoxLayout> <QLabel>

mydialog.cpp
#include "mydialog.h" MyDialog::MyDialog() { setFixedSize(150, 100); QVBoxLayout* vbox = new QVBoxLayout(); QLabel* label = new QLabel("Please confirm."); QPushButton* okButton = new QPushButton("Ok"); QPushButton* cancelButton = new QPushButton("Cancel"); // Set the ok button as default okButton->setDefault(true); vbox->addWidget(label); vbox->addWidget(okButton); vbox->addWidget(cancelButton); setLayout(vbox); // Connect the buttons to slots defined by QDialog connect(okButton, SIGNAL(clicked()), this, SLOT(accept())); connect(cancelButton, SIGNAL(clicked()), this, SLOT(reject())); }

class MyDialog : public QDialog { Q_OBJECT public: MyDialog(); }; #endif // MYDIALOG_H

16

Andreas Jakl, 2009

QDialog Base Class


Slot virtual void accept() virtual void reject() virtual void done(int r) Description Hides the dialog and sets the result code to Accepted (1). Hides the dialog and sets the result code to Rejected (0). Closes the dialog and sets return value to r. If the dialog is started via exec(), done() causes the event loop to finish, and exec() to return r. Deletes the dialog if Qt::WA_DeleteOnClose is set.

int exec()

Shows the dialog as a modal dialog, blocking until the user closes it. Returns dialog return value (DialogCode) like Accepted or Rejected.
Description Emitted when dialog has been accepted through calling accept() or done() with the argument QDialog::Accepted Emitted when dialog has been rejected through calling reject() or done() with the argument QDialog::Rejected Emitted when the dialogs result code has been set (setResult()) and either accept(), reject() or done() is called.
Andreas Jakl, 2009

Signal void accepted() void rejected() void finished(int result)

17

The Widget
mywidget.h
[...]
class MyWidget : public QWidget { Q_OBJECT public: MyWidget(QWidget *parent = 0); ~MyWidget(); private slots: void checkInputDialog(); private: QPushButton* startButton; QLabel* instructionsLabel; QLabel* resultLabel; QVBoxLayout* layout; MyDialog* dialog; }; #endif // MYWIDGET_H }

mywidget.cpp
#include "mywidget.h" MyWidget::MyWidget(QWidget *parent) : QWidget(parent) { startButton = new QPushButton("Start dialog"); instructionsLabel = new QLabel("Please push the button"); resultLabel = new QLabel(); layout = new QVBoxLayout(this); layout->addWidget(instructionsLabel); layout->addWidget(startButton); layout->addWidget(resultLabel); dialog = new MyDialog(); connect(startButton, SIGNAL(clicked()), dialog, SLOT(exec())); connect(dialog, SIGNAL(accepted()), this, SLOT(checkInputDialog())); connect(dialog, SIGNAL(rejected()), this, SLOT(checkInputDialog())); setWindowTitle("Main Window - Dialog Example");

main.cpp is similar to previous example

18

void MyWidget::checkInputDialog() { int res = dialog->result(); // Gets result (Accepted/Rejected) if (res == QDialog::Accepted) { resultLabel->setText("\"Ok\" was selected"); } else if (res == QDialog::Rejected) { resultLabel->setText("\"Cancel\" was selected"); } }

Andreas Jakl, 2009

Custom Return Values


mydialog.h
[...] private slots: void setResult(); [...]

mydialog.cpp
[...] connect(ignoreButton, SIGNAL(clicked()), this, SLOT(setResult())); [...] void MyDialog::setResult() { int result = 99; emit done(result); }

mywidget.cpp
[...] connect(dialog, SIGNAL(finished(int)), this, SLOT(checkInputDialog(int))); [...] void MyWidget::checkInputDialog(int res) { if (res == 99) { resultLabel->setText("\"Ignore\" was selected"); } }

mywidget.h
[...] private slots: void checkInputDialog(); void checkInputDialog(int); [...]

19

Andreas Jakl, 2009

Pre-Defined Dialogs
QColorDialog QErrorMessage

QFontDialog

QInputDialog QFileDialog

QMessageBox

20

Andreas Jakl, 2009

Pre-Defined Dialogs

Example: Message box


Modal dialog User selection return value

int ret = QMessageBox::warning( this, "Exit?", "Do you really want to exit the application?", QMessageBox::Yes | QMessageBox::No );

21

Andreas Jakl, 2009

User interaction with a real application

Main Window, Menus and Actions

22

Andreas Jakl, 2009

Main Window

Provides main application window


Menu Bar Toolbars Dock Widgets Central Widget

Pre-defined layout for standard components Central widget must be defined, others optional Subclass to create your own implementation
Status Bar

Differences?

Possible with dialog / widgets as well But: more comfortable, consistent and efficient
23 Andreas Jakl, 2009

Example QMainWindow
mainwindow.h
[...]
class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = 0, Qt::WFlags flags = 0); ~MainWindow(); private: QTextEdit* editor; } [...] }; #endif // MAINWINDOW_H

mainwindow.cpp
#include "mainwindow.h" MainWindow::MainWindow(QWidget *parent, Qt::WFlags flags) : QMainWindow(parent, flags) { editor = new QTextEdit(); setMinimumSize(160, 160); resize(480, 320); setCentralWidget(editor); setWindowTitle("QMainWindow with Menus"); QString message = "Welcome"; statusBar()->showMessage(message);

main.cpp is similar to previous example

24

Andreas Jakl, 2009

Represent abstract user interface action Define once, use in multiple components Inserted into widgets

Stores information about


Icons Text Keyboard shortcut Status text

Menus (can create actions implicitly)

Toolbar buttons
Keyboard shortcuts
25

Whats This? text


Tooltip

Andreas Jakl, 2009

Image by Anna Cervova (Public Domain)

Action

Menu Bar

QMenu provides a menu widget for menu bars, context menus and other popup menus Supports:

Triggered Items Separators Submenus Tear-off menus

QMenuBar automatically created by QMainWindow QMenu(s) contains individual menu items ( Actions)
26 Andreas Jakl, 2009

Example QAction
mainwindow.h
[...]
class MainWindow : public QMainWindow { Q_OBJECT [...] private slots: void openFile(); private: QMenu *fileMenu; QAction *openAct; };

mainwindow.cpp
[...] // Create a new Open action with an icon, keyboard shortcut and // info-text for the status bar. openAct = new QAction("&Open...", this); openAct->setIcon(QIcon("images/open.png")); openAct->setShortcut(tr("Ctrl+O")); openAct->setStatusTip(tr("Open an existing file")); connect(openAct, SIGNAL(triggered()), this, SLOT(openFile()));

// Add the action to the menu fileMenu = menuBar()->addMenu(tr("&File")); fileMenu->addAction(openAct);


[...] void MainWindow::openFile() { // Define two filter options one for documents, one for all files // The filter mask is automatically parsed, ;; separates lines QString file = QFileDialog::getOpenFileName(this, "Please choose a file to open", QDir::homePath(), "Documents (*.pdf *.doc *.docx);;All files (*.*)"); if (!file.isNull()) { QString info("You chose this file\n"); info.append(file); QMessageBox::information(this, "Your Choice", info, QMessageBox::Ok); } }

27

Andreas Jakl, 2009

Toolbar

Same actions as for menu can be used for toolbar Default automatically enables drag & drop

28

Andreas Jakl, 2009

Example QToolBar
mainwindow.h
[...]
class MainWindow : public QMainWindow { Q_OBJECT [...] private: QToolBar *toolFile; };

mainwindow.cpp
#include "mainwindow.h" MainWindow::MainWindow(QWidget *parent, Qt::WFlags flags) : QMainWindow(parent, flags) { [...] // Open action openAct = new QAction("&Open...", this); openAct->setIcon(QIcon("images/open.png")); openAct->setShortcut(tr("Ctrl+O")); openAct->setStatusTip(tr("Open an existing file")); connect(openAct, SIGNAL(triggered()), this, SLOT(openFile())); // Exit action exitAct = new QAction("E&xit", this); exitAct->setIcon(QIcon("images/exit.png")); exitAct->setShortcut(tr("Ctrl+Q")); exitAct->setStatusTip(tr("Exit the application")); connect(exitAct, SIGNAL(triggered()), this, SLOT(close()));

// Create the file menu fileMenu = menuBar()->addMenu(tr("&File")); fileMenu->addAction(openAct); fileMenu->addSeparator(); fileMenu->addAction(exitAct);


// Add the actions to the toolbar toolFile = addToolBar("File"); toolFile->addAction(openAct); toolFile->addAction(exitAct); [...] }

29

Andreas Jakl, 2009

Additional Object Meta-Information

Properties

30

Andreas Jakl, 2009

Property System

Add data to meta-object of class instances


Behaves like class property member Define in class header file

Or add dynamically at runtime (any property to any class)


Used by Qt Designer for widget setup

31

Andreas Jakl, 2009

Query Properties

Example: default properties of QPushButton instance

Default: 71 properties defined

// Get meta object of target object const QMetaObject *metaobject = but->metaObject(); // Number of properties int count = metaobject->propertyCount(); for (int i=0; i<count; ++i) { // Retrieve current property QMetaProperty metaproperty = metaobject->property(i); // Print name and value to debug out const char *name = metaproperty.name(); QVariant value = but->property(name); qDebug() << "Name:" << name << ", value:" << value; }
Name: Name: Name: Name: Name: Name: Name: Name: Name: Name: Name: Name: Name: Name: Name: Name: Name: Name: Name: Name: ... objectName , value: QVariant(QString, "") enabled , value: QVariant(bool, true) pos , value: QVariant(QPoint, QPoint(0,0) ) size , value: QVariant(QSize, QSize(200, 100) ) width , value: QVariant(int, 200) height , value: QVariant(int, 100) rect , value: QVariant(QRect, QRect(0,0 200x100) ) isActiveWindow , value: QVariant(bool, true) focus , value: QVariant(bool, true) visible , value: QVariant(bool, true) minimized , value: QVariant(bool, false) maximized , value: QVariant(bool, false) fullScreen , value: QVariant(bool, false) sizeHint , value: QVariant(QSize, QSize(76, 23) ) toolTip , value: QVariant(QString, "") statusTip , value: QVariant(QString, "") whatsThis , value: QVariant(QString, "") locale , value: QVariant(QLocale, ) text , value: QVariant(QString, "Hello Property") down , value: QVariant(bool, false)

32

Andreas Jakl, 2009

Adding Own Properties

Define with Q_PROPERTY() macro (inherited from QObject)


In private section of class READ function: creator(). Must be const. (required) WRITE function: setCreator(). Must return void, exactly one argument with type of property or pointer/reference to that type (optional)
... Name: creator , value: QVariant(QString, "Mopius")

mybutton.h
class MyButton : public QPushButton mainwindow.cpp { but->setCreator(tr("Mopius")); Q_OBJECT Q_PROPERTY(QString creator READ creator WRITE setCreator) public: MyButton(const QString& text, QWidget* parent = NULL); void setCreator(QString aCreator); QString creator() const { return iCreator; }

mybutton.cpp
void MyButton::setCreator(QString aCreator) { iCreator = aCreator; }

private: QString iCreator; };

33

Andreas Jakl, 2009

Dynamic Properties

Add new properties to an instance at runtime setProperty() behaviour:


Name equals existing property & type is compatible: updates property Non-compatible type compatible: no update Name does not exist (not declared with Q_PROPERTY()): new property is added

mainwindow.cpp
but->setProperty("Owner", tr("Andreas Jakl")); QList<QByteArray> dynProperties = but->dynamicPropertyNames(); foreach (QByteArray curProperty, dynProperties) { QVariant value = but->property(curProperty); qDebug() << "Dyn-Name:" << curProperty << ", value:" << value; } Dyn-Name: "Owner" , value: QVariant(QString, "Andreas Jakl")

34

Andreas Jakl, 2009

How to actually work with data?

Data Types

35

Andreas Jakl, 2009

Fundamental Data Types


Important for cross platform development Datatypes defined via typedef


Qt type qint8 qint16 qint32 qint64 qreal uchar / quint8 ushort / quint16 typedef from signed char signed short signed int long long int double / float (ARM) unsigned char unsigned short 0 to 255 0 to 65535 Value range -128 to +127 -32768 to +32767 -2147483648 to +2147483647 signed 64 bit

uint / quint32
ulong qulonglong / quint64
36

unsigned int
unsigned long unsigned long long int
Andreas Jakl, 2009

0 to 4294967296
0 to 4294967296 unsigned 64 bit values

QString

Similar to standard C++ String Qt always uses Unicode (16 bit QChar) Uses implicit sharing to increase efficiency and reduce memory overhead Use QByteArray to store raw bytes and 8-bit \0-terminated strings

37

Andreas Jakl, 2009

Implicit Sharing Example


// Line 1
str1 Data: Hello world Reference count: 1

// Line 2
str1 str2 Data: Hello world Reference count: 2

// Line 3
str1 Data: Hello world Reference count: 1 str2 Data: Hello Qt Reference count: 1

Line 1

Constructs first QString object Converts const char* data to Unicode

Line 2

QString str1 = "Hello world"; QString str2 = str1; str2.replace("world", "Qt");

Assigns value of str1 to str2, but Qt doesnt copy it right away Instead: only pointer is passed (shallow copy) Modifies str2: Qt separates both strings in memory (deep copy) Happens behind the scenes
38 Andreas Jakl, 2009

Line 3

Implicit Sharing

obj1 obj2

Data Ref-count

Works automatically behind the scenes

Only pointer to data is passed


Data only copied if a function writes on it (copy-on-write) Reference counting implemented as atomic operation (thread-safe) Shallow copy: reference copy Deep copy: duplicates object Object assignment (operator=()) uses shallow copies Modifying methods perform deep copy if needed QString, QImage, etc. Using for own classes: QSharedDataPointer
39 Andreas Jakl, 2009

Pointer to shared data block, which contains reference count and data

Copies

Usage in Qt

QVariant

Union for most common Qt data types Stores one type of data Converts between different types
QDataStream out(...); QVariant v(123); int x = v.toInt(); out << v; v = QVariant("hello"); v = QVariant(tr("hello")); int y = v.toInt(); QString s = v.toString(); out << v; [...] QDataStream in(...); in >> v; int z = v.toInt(); qDebug("Type is %s", v.typeName()); v = v.toInt() + 100; v = QVariant(QStringList()); // // // // // // // // // // // // The variant now contains an int x = 123 Writes a type tag and an int to out The variant now contains a QByteArray The variant now contains a QString y = 0 since v cannot be converted to an int s = tr("hello") (see QObject::tr()) Writes a type tag and a QString to out (opening the previously written stream) Reads an Int variant z = 123 prints "Type is int"

// The variant now hold the value 223

40

Andreas Jakl, 2009

Lists, etc.

Tulip Container classes similar to STL


Less error-prone syntax than STL Using STL is possible, but might not be fully implemented by all compilers
Sequential containers Associative containers

QList (QStringList)
QLinkedList QVector QStack QQueue

QMap
QMultiMap QHash QMultiHash QSet

41

Andreas Jakl, 2009

Iterating over QStringList


// Define and populate a string list // (like QList<QString> with some enhancements) QStringList sList; sList << "apple" << "pear" << "orange"; // foreach is a Qt specific addition to C++, implemented via the preprocessor foreach(QString str, sList) std::cout << str.toAscii().constData() << std::endl; // Iterate over list using indexing for (int i = 0; i < sList.size(); i++) std::cout << sList.at(i).toAscii().constData() << std::endl; // Use an STL-style iterator QStringList::const_iterator constIt; for (constIt = sList.constBegin(); constIt != sList.constEnd(); ++constIt) std::cout << (*constIt).toAscii().constData() << std::endl; // Java-style iterator QStringListIterator javaStyleIterator(sList); while (javaStyleIterator.hasNext()) std::cout << javaStyleIterator.next().toAscii().constData() << std::endl; 42 Andreas Jakl, 2009

QDebug

// The global functions are available anywhere. qDebug("Processing Fruits..."); // Using the << operator requires including <QDebug> qDebug() << "Fruit: " << sList.at(1);

Four global functions available:


qDebug(): writing custom debug output. qWarning(): report warnings and recoverable errors in your application. qCritical(): writing critical error messages and reporting system errors. qFatal(): writing fatal error messages shortly before exiting.

Outputs to:

Mac OS X and Unix: stderr Windows: Console application console. GUI application debugger.
43 Andreas Jakl, 2009

Preparing your applications for the international market

Internationalization

44

Andreas Jakl, 2009

Internationalization

... is more than language


Spelling Ligatures: Formats (numbers, dates, currencies) Non-spacing or diacritical marks (accents / umlauts in European languages) Special line breaking behaviour Character encoding Presentation conventions (bidirectional writing) Input techniques

Internationalization support built into Qt widgets & tools


45 Andreas Jakl, 2009

Qt Linguist

Tool to translate your application

Translation files (.ts, xml-based) extracted from your source code Qt Linguist only needs xml file simple for external translators

Provides validation and preview (for Qt Designergenerated UIs)


46 Andreas Jakl, 2009

Preparing your Application

Mark user-visible strings for translation with tr()

Inside functions in QObject subclasses that use the Q_OBJECT macro:


label = new QLabel("Hello World"), this);

label = new QLabel(tr("Hello World"), this);

Other text-positions within your source code:


Use tr() from other QObject-derived class QCoreApplication::translate() Completely outside functions: QT_TR_NOOP() / QT_TRANSLATE_NOOP() macros
Andreas Jakl, 2009

47

Translation Context

Translation might be different according to context


Open for file in German: ffnen Open for Internet connection in German: Aufbauen Class name automatically provided by Qt Linguist Custom comments through 2nd parameter of tr():

Additional Information for the Translator


Add explanation for context or usage area


setWindowTitle(tr("Welcome", "Window title"));

Provide even more through TRANSLATOR comments


48 Andreas Jakl, 2009

Plural, Keyboard Accelerators

Plural: provide extra translations depending on a value


int nrHellos = 1; label2 = new QLabel(tr("Said hello %n time(s)", "", nrHellos));

More information: http://qt.nokia.com/doc/qq/qq19-plurals.html


exitAct = new QAction(tr("E&xit"), this); exitAct->setShortcut(tr("Ctrl+Q", "Quit"));

Also translate keyboard accelerators

49

Andreas Jakl, 2009

Add Languages

Edit the .pro file and add desired translation(s):


TARGET = translator1 TEMPLATE = app SOURCES += main.cpp \ mywidget.cpp HEADERS += mywidget.h FORMS += TRANSLATIONS = translator1_de.ts \ translator1_fr.ts

Run lupdate <.pro-filename>


Finds translatable strings in source code, headers and Qt Designer files Generates/updates XML file for each language Translate these files with Qt Linguist

50

Andreas Jakl, 2009

Finished Translations?

Run lrelease <.pro-filename>


Produces compact binary .qm files out of .ts files Only integrates translations marked as finished

51

Andreas Jakl, 2009

Loading Translations

To use translations use QTranslator Usually initialized at beginning of main()


// Get locale of the system QString locale = QLocale::system().name(); // Load the correct translation file (if available) QTranslator translator; translator.load(QString("translator1_") + locale, qApp->applicationDirPath()); // Adds the loaded file to list of active translation files app.installTranslator(&translator);

52

Andreas Jakl, 2009

Loading Translations II

Locale:

Locale: de_AT (Austrian dialect of German language) translator1_de_at.qm translator1_de_at translator1_de.qm translator1_de translator1.qm translator1

e.g., de_AT

QTranslator::load()

Second parameter: directory of .qm file(s)


Automatically tries to load more generic translations

// Get locale of the system QString locale = QLocale::system().name(); // Load the correct translation file (if available) QTranslator translator; translator.load(QString("translator1_") + locale, qApp->applicationDirPath()); // Adds the loaded file to list of active translation files app.installTranslator(&translator); (copy from previous slide)

53

Andreas Jakl, 2009

Troubleshooting?

Not loading the translations?


Make sure the translation files are found Copy *.qm to directory of executable if in doubt!

54

Andreas Jakl, 2009

Thats it.

Thanks for your attention.

55

Andreas Jakl, 2009

Anda mungkin juga menyukai