Development/Tutorials/Using Qt Designer: Difference between revisions

From KDE TechBase
(reframe the article and use the direct approach instead of the single inheritance approach)
(Replaced content with link to Community WIki.)
 
(28 intermediate revisions by 9 users not shown)
Line 1: Line 1:
== Qt Designer User Interfaces in KDE ==
{{Note|This is now located at https://community.kde.org/Get_Involved/development/Tutorials/Using_Qt_Designer}}
 
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.3/designer-manual.html user documentation]. 
It might make sense to provide a brief example of using Designer here, but
for now this article 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>
kde4_add_ui_files(myapp_SRCS mydialog.ui)
</code>
 
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 *parent)</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. The Qt documentation
shows three ways of [http://doc.trolltech.com/latest/designer-using-a-component.html how to use ui-files];
here only the ''direct approach'' is discussed. The goal is to create a KDialog
which embeds the UI from the ui-file. First, we have to subclass MyDialog from
KDialog and add a pointer to Ui::MyDialog. The header file of
"<tt>mydialog.h</tt>" looks like the following:
 
<code cppqt>
#ifndef MYDIALOG_H
#define MYDIALOG_H
 
#include <KDialog>
 
namespace Ui {
    // forward declaration of Ui::MyDialog. This way we work
    // around the #include "ui_mydialog.h"
    class MyDialog;
}
 
class MyDialog : public KDialog
{
    Q_OBJECT
    public:
        MyDialog( QWidget *parent=0 );
        ~MyDialog();
 
    private slots:
        void slotButtonClicked();
 
    private:
        // pointer to the ui. we can access all gui elements
        // specified in Designer. If mydialog.ui contains a
        // button "myButton", we will be able to access it
        // with ui->myButton in the cpp file.
        Ui::MyDialog *ui;
};
 
#endif
</code>
 
Now we are going to look at the implementation of MyDialog, which is in the file
"<tt>mydialog.cpp</tt>".
 
<code cppqt>
#include <KLocale>
#include <KMessageBox>
 
// include the header file of the dialog
#include "mydialog.h"
 
// include the automatically generated header file for the ui-file
#include "ui_mydialog.h"
 
MyDialog::MyDialog( QWidget *parent )
: KDialog( parent )
{
    QWidget *widget = new QWidget( this );
 
    // create the user interface, the parent widget is "widget"
    ui = new Ui::MyDialog();
    ui->setupUi(widget); // this is the important part
 
    // set the widget with all its gui elements as the dialog's
    // main widget
    setMainWidget( widget );
 
    // other KDialog options
    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 elements.
    connect( ui->myButton, SIGNAL( clicked() ),
            this, SLOT( slotButtonClicked() ) );
}
 
MyDialog::~MyDialog()
{
    // no need to delete the user interface.
    // QObject derived classes automatically delete their children.
}
 
void MyDialog::slotButtonClicked()
{
    KMessageBox::information( this,
                              i18n("You pressed the button!" ),
                              i18n( "Hooray!" ) );
}
 
#include "mydialog.moc"
</code>
 
So, basically, we create a new Ui::MyDialog and then call
<tt>ui->setupUi(widget)</tt> in the constructor of <tt>MyDialog</tt>. This
places the UI elements into the given widget. Then we set the parent-widget
as the KDialog's main widget. We can then interact with all of the UI elements
by prepending "<tt>ui-></tt>" to their names, just like it is often done
with the prefix "<tt>m_</tt>".
 
== Final Thoughts ==
 
The cascade of files and classes in this tutorial may seem daunting at
first, but the naming scheme layed out here has one nice intuitive
feature: the source code files that you will be editing directly (either as
text or with Designer) are all named with the same scheme:
* '''mydialog.ui''': the user interface, created with Designer
* '''ui_mydialog.h''': auto-generated by moc, Qt's meta object compiler
* '''mydialog.h/cpp''': the dialog implementation
The steps in short are
# create <tt>mydialog.ui</tt>
# create <tt>mydialog.h/cpp</tt>
# add forward declaration and member variable Ui::MyDialog *ui; in <tt>mydialog.h</tt>
# call <tt>ui = new Ui::MyDialog(); ui->setupUi(widget);</tt>
# use the ui with <tt>ui-></tt>
 
== Qt Documentation ==
 
The Qt documentation contains a good article about
[http://doc.trolltech.com/latest/designer-using-a-component.html Using a Component in Your Application].
[[Category:C++]]
[[Category:KDE4]]

Latest revision as of 12:48, 16 May 2019