Jump to content

Development/Tutorials/Programming Tutorial KDE 3/kapp and Development/Tutorials/Using Qt Designer: Difference between pages

From KDE TechBase
(Difference between pages)
Fix the code tags
 
Dhaumann (talk | contribs)
m guys, whenever you rename a template, check "What links here" and fix all entries :)
 
Line 1: Line 1:
== Qt Designer User Interfaces in KDE ==
In this tutorial, we will explore how to programatically insert user interfaces
(UIs) created with Qt Designer, into your KDE project. 
=== Designing the UI ===
[http://www.trolltech.com/products/qt/features/designer Qt Designer] is a
graphical program which allows you to easily build user interfaces, using an
intuitive "drag n drop" interface.  Designer has its own excellent
[http://doc.trolltech.com/4.2/designer-manual.html user documentation]. 
It might make sense to provide a brief example of using Designer here, but
for now I will leave most of that to the Designer manual itself.
=== Adding the UI File to Your KDE Project ===
For our purposes, the most important part of using Designer is the
<tt>*.ui</tt> file that it creates.  This is simply an XML file that
encodes the user interface in a machine-readable (and human-readable!) way.
Let's imagine that you've created a UI named "MyDialog" with Designer, and
saved it as the file <tt>mydialog.ui</tt>.  To add this UI to your KDE
project, simply add a command like the following to your CMakeLists.txt file:
<code>
<code>
#include <qstring.h>
kde4_add_ui_files(myapp_SRCS myialog.ui)
#include <kapplication.h>
</code>
#include <kaboutdata.h>
 
Replace "<tt>myapp_SRCS</tt>" with the name of the main block in
your CMakeLists.txt file, defining all of the source code files.  It is usually the
name of your application, with "<tt>_SRCS</tt>" appended.
 
When you do this, the build system will run the Qt program <tt>uic</tt>
on <tt>mydialog.ui</tt>, to auto-generate a C++ header file that
defines the UI.  The generated file will be named <tt>ui_mydialog.h</tt>.
 
=== Using the UI in Your Code ===
 
The <tt>ui_mydialog.h</tt> file defines a class named
"<tt>Ui_MyDialog</tt>", that contains all of the widgets you created in
Designer as public members of the class.  It also contains the public function
"<tt>setupUi(QWidget*)</tt>", which instantiates all of the widgets,
sets up their properties, and inserts them into layout managers, all according
to what you specified in Designer.
 
Note that <tt>setupUi()</tt> takes a <tt>QWidget*</tt>
argument.  This argument represents the parent container widget, into which
all of the widgets in your UI will be inserted.  In other words,
'''<tt>Ui_MyDialog</tt> is not itself derived from QWidget''', and
'''it does not contain a toplevel widget itself'''.  You have to supply the toplevel widget
when you call <tt>setupUi()</tt>.  This is an important point.
 
One more important semantic detail:  the <tt>Ui_MyDialog</tt> class
also creates a <tt>Ui</tt> namespace, which simply creates an alias
for the class.  So you can use <tt>Ui::MyDialog</tt> to refer to the
same class.
 
Now, on to actually using the generated UI in your code.  There are a few ways
to do this; for now I will only discuss one method, in which we create a class
that inherits from both <tt>Ui::MyDialog</tt> and a Qt container class
like {{qt|QFrame}}.  Create a class definition file named
"<tt>mydialog.h</tt>", and add the following:
 
<code cppqt>
#ifndef MYDIALOG_H
#define MYDIALOG_H
 
#include <kdialog.h>
#include "ui_mydialog.h"
 
class MyDialogUI : public QFrame, public Ui::MyDialog
{
    Q_OBJECT
    public:
        MyDialogUI( QWidget *parent=0 );
};
 
class MyDialog : public KDialog
{
    Q_OBJECT
    public:
        MyDialog( QWidget *parent=0 );
        ~MyDialog();
 
    private slots:
        void slotButtonClicked();
 
    private:
        MyDialogUI *ui;
};
 
#endif
</code>
 
So we have defined two classes.  <tt>MyDialogUI</tt> is simply a
{{qt|QFrame}} with your UI elements placed inside it. 
<tt>MyDialog</tt> is a {{class|KDialog}} window, whose main
widget will be the <tt>MyDialogUI</tt> instance named
<tt>ui</tt> above.  Here is the "<tt>mydialog.cpp</tt>"
C++ definition file:
 
<code cppqt>
#include <klocale.h>
#include <kmessagebox.h>
#include <kmessagebox.h>
#include <kcmdlineargs.h>


int main (int argc, char *argv[])
#include "mydialog.h"
 
MyDialogUI::MyDialogUI( QWidget *parent )
: QFrame( parent )
{
{
        KAboutData aboutData( "test", "test",
    setupUi( this );
        "1.0", "test", KAboutData::License_GPL,
        "(c) 2006" );
        KCmdLineArgs::init( argc, argv, &aboutData );
        KApplication khello;
        KMessageBox::information(0,"This is an example");
}
}
MyDialog::MyDialog( QWidget *parent )
: KDialog( parent )
{
    ui = new MyDialogUI( this );
    setMainWidget( ui );
    setCaption( i18n("This is my Dialog window!") );
    setButtons( KDialog::Close );
    //Example Signal/Slot connection using widgets in your UI.
    //Note that you have to prepend "ui->" when referring to your UI widgets.
    connect( ui->MyButton, SIGNAL( clicked() ), this, SLOT( slotButtonClicked() ) );
}
MyDialog::~MyDialog()
{
    delete ui;
}
void MyDialog::slotButtonClicked()
{
    KMessageBox::information( this, i18n("You pressed the button!" ), i18n( "Hooray!" ) );
}
#include "mydialog.moc"
</code>
</code>
So, basically, we call <tt>setupUi(this)</tt> in the <tt>MyDialogUI</tt>
constructor, which places your UI elements into that widget.  Then, in the
<tt>MyDialog</tt> constructor, we create the <tt>MyDialogUI</tt>
instance named <tt>ui</tt> and set it to be our dialog's main widget.
We can then interact with all of the UI elements by prepending
"<tt>ui-></tt>" to their names.
=== Final Thoughts ===
The cascade of files and classes in this tutorial may seem daunting at
first, but the naming scheme I've layed out here has one nice intuitive
feature: the three source code files that you will be editing
directly (either as text or with Designer) are all named with the same
simple filename stem: <tt>mydialog.ui</tt>, <tt>mydialog.h</tt>, and
<tt>mydialog.cpp</tt>.  Just remember that you'll be using the
<tt>MyDialog</tt> class almost exclusively.  Setting up the
<tt>MyDialogUI</tt> class is easy (it only contains a one-line
constructor), and once it's set up you can pretty well ignore it.

Revision as of 18:21, 27 December 2006

Qt Designer User Interfaces in KDE

In this tutorial, we will explore how to programatically insert user interfaces (UIs) created with Qt Designer, into your KDE project.

Designing the UI

Qt Designer is a graphical program which allows you to easily build user interfaces, using an intuitive "drag n drop" interface. Designer has its own excellent user documentation. It might make sense to provide a brief example of using Designer here, but for now I will leave most of that to the Designer manual itself.

Adding the UI File to Your KDE Project

For our purposes, the most important part of using Designer is the *.ui file that it creates. This is simply an XML file that encodes the user interface in a machine-readable (and human-readable!) way.

Let's imagine that you've created a UI named "MyDialog" with Designer, and saved it as the file mydialog.ui. To add this UI to your KDE project, simply add a command like the following to your CMakeLists.txt file:

kde4_add_ui_files(myapp_SRCS myialog.ui)

Replace "myapp_SRCS" with the name of the main block in your CMakeLists.txt file, defining all of the source code files. It is usually the name of your application, with "_SRCS" appended.

When you do this, the build system will run the Qt program uic on mydialog.ui, to auto-generate a C++ header file that defines the UI. The generated file will be named ui_mydialog.h.

Using the UI in Your Code

The ui_mydialog.h file defines a class named "Ui_MyDialog", that contains all of the widgets you created in Designer as public members of the class. It also contains the public function "setupUi(QWidget*)", which instantiates all of the widgets, sets up their properties, and inserts them into layout managers, all according to what you specified in Designer.

Note that setupUi() takes a QWidget* argument. This argument represents the parent container widget, into which all of the widgets in your UI will be inserted. In other words, Ui_MyDialog is not itself derived from QWidget, and it does not contain a toplevel widget itself. You have to supply the toplevel widget when you call setupUi(). This is an important point.

One more important semantic detail: the Ui_MyDialog class also creates a Ui namespace, which simply creates an alias for the class. So you can use Ui::MyDialog to refer to the same class.

Now, on to actually using the generated UI in your code. There are a few ways to do this; for now I will only discuss one method, in which we create a class that inherits from both Ui::MyDialog and a Qt container class like QFrame. Create a class definition file named "mydialog.h", and add the following:

  1. ifndef MYDIALOG_H
  2. define MYDIALOG_H
  1. include <kdialog.h>
  2. include "ui_mydialog.h"

class MyDialogUI : public QFrame, public Ui::MyDialog {

   Q_OBJECT
   public:
       MyDialogUI( QWidget *parent=0 );

};

class MyDialog : public KDialog {

   Q_OBJECT
   public:
       MyDialog( QWidget *parent=0 );
       ~MyDialog();
   private slots:
       void slotButtonClicked();
   private:
       MyDialogUI *ui;

};

  1. endif

So we have defined two classes. MyDialogUI is simply a QFrame with your UI elements placed inside it. MyDialog is a KDialog window, whose main widget will be the MyDialogUI instance named ui above. Here is the "mydialog.cpp" C++ definition file:

  1. include <klocale.h>
  2. include <kmessagebox.h>
  1. include "mydialog.h"

MyDialogUI::MyDialogUI( QWidget *parent )

QFrame( parent )

{

   setupUi( this );

}

MyDialog::MyDialog( QWidget *parent )

KDialog( parent )

{

   ui = new MyDialogUI( this );
   setMainWidget( ui );
   setCaption( i18n("This is my Dialog window!") );
   setButtons( KDialog::Close );
   //Example Signal/Slot connection using widgets in your UI.
   //Note that you have to prepend "ui->" when referring to your UI widgets.
   connect( ui->MyButton, SIGNAL( clicked() ), this, SLOT( slotButtonClicked() ) );

}

MyDialog::~MyDialog() {

   delete ui;

}

void MyDialog::slotButtonClicked() {

   KMessageBox::information( this, i18n("You pressed the button!" ), i18n( "Hooray!" ) );

}

  1. include "mydialog.moc"

So, basically, we call setupUi(this) in the MyDialogUI constructor, which places your UI elements into that widget. Then, in the MyDialog constructor, we create the MyDialogUI instance named ui and set it to be our dialog's main widget. We can then interact with all of the UI elements by prepending "ui->" to their names.

Final Thoughts

The cascade of files and classes in this tutorial may seem daunting at first, but the naming scheme I've layed out here has one nice intuitive feature: the three source code files that you will be editing directly (either as text or with Designer) are all named with the same simple filename stem: mydialog.ui, mydialog.h, and mydialog.cpp. Just remember that you'll be using the MyDialog class almost exclusively. Setting up the MyDialogUI class is easy (it only contains a one-line constructor), and once it's set up you can pretty well ignore it.