| 
				     | 
				
| (31 intermediate revisions by 10 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*)</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 we 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>
  |  | 
 | #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>
  |  | 
 | #include <KMessageBox>
  |  | 
 |    |  | 
 | #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.
  |  | 
 |    |  | 
 | === Troubleshooting ===
  |  | 
 | If you get errors similar to 
  |  | 
 | <code>
  |  | 
 | mydialog.h:9: error: expected class-name before ‘{’ token
  |  | 
 | </code>
  |  | 
 |    |  | 
 | recheck the names of the dialog in the mydialog.ui file (should be "MyDialog"), the pushButton ("pushButton") and any other objects you've designed.
  |  | 
 |    |  | 
 | === 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 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.
  |  | 
 | [[Category:C++]]
  |  | 
 | [[Category:KDE4]]
  |  |