Development/Tutorials/Using Qt Designer: Difference between revisions

    From KDE TechBase
    (I can't get the {{kde|KDialog}} template to work :/)
    (Replaced content with link to Community WIki.)
     
    (40 intermediate revisions by 12 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.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>
    kde4_add_ui_files(myapp_SRCS myialog.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*)</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 {{kde|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 "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!" ) );
    }
     
    #include "mydialog.moc"
    </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.

    Latest revision as of 12:48, 16 May 2019