Sophie

Sophie

distrib > Mandriva > 8.2 > i586 > media > contrib > by-pkgid > 112b0974ad288f6cd55bf971ee6026a9 > files > 662

libqt3-devel-3.0.2-2mdk.i586.rpm

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- /tmp/qt-3.0-reggie-28534/qt-x11-free-3.0.2/tools/designer/book/chap-main-windows.leaf:3 -->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Creating Main Windows with Actions, Toolbars and Menus</title>
<style type="text/css"><!--
h3.fn,span.fn { margin-left: 1cm; text-indent: -1cm; }
a:link { color: #004faf; text-decoration: none }
a:visited { color: #672967; text-decoration: none }
body { background: #ffffff; color: black; }
--></style>
</head>
<body>

<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tr bgcolor="#E5E5E5">
<td valign=center>
 <a href="index.html">
<font color="#004faf">Home</font></a>
 | <a href="classes.html">
<font color="#004faf">All&nbsp;Classes</font></a>
 | <a href="mainclasses.html">
<font color="#004faf">Main&nbsp;Classes</font></a>
 | <a href="annotated.html">
<font color="#004faf">Annotated</font></a>
 | <a href="groups.html">
<font color="#004faf">Grouped&nbsp;Classes</font></a>
 | <a href="functions.html">
<font color="#004faf">Functions</font></a>
</td>
<td align="right" valign="center"><img src="logo32.png" align="right" width="64" height="32" border="0"></td></tr></table><p align="right">[<a href="designer-manual-2.html">Prev: Creating a Qt Application</a>] [<a href="designer-manual.html">Home</a>] [<a href="designer-manual-4.html">Next: The Designer Approach</a>]</p>
<h2 align="center">Creating Main Windows with Actions, Toolbars and Menus</h2>
<!-- index Actions and Action Groups --><!-- index Main Window!Creating --><!-- index Creating Main Windows --><!-- index Creating Menus --><!-- index Menus!Adding --><!-- index Creating Toolbars --><!-- index Toolbars, Creating --><!-- index Toolbar Buttons!Adding --><!-- index Adding!Menus --><!-- index Adding!Toolbars --><!-- index Adding!Actions and Action Groups --><!-- index Adding!Toolbar Buttons --><p>In this chapter we will explain how to create an application's main window and how to add actions (explained shortly), menus and toolbars. We will also demonstrate how some common actions, like cut and paste in a <b>QTextEdit</b>, can be performed automatically simply by making the appropriate signals and slots connections. We will build the <em>richedit</em> application to illustrate the necessary techniques.</p>
<p align="center"><img align="middle" src="richedit-main.png" width="739" height="383">
</p>
<blockquote><p align="center"><em>The Richedit Application</em></p></blockquote>
<!-- index Projects --><p>We begin by creating a project file. Start <em>Qt Designer</em> or if it is already running, close any existing projects and files. Click <b>File|New</b> to invoke the <em>New File</em> dialog. Click the 'C++ Project' icon, then click <b>OK</b> to invoke the <em>Project Settings</em> dialog. Click the ellipsis button to invoke the <em>Save As</em> dialog and navigate to where you want to put the new project. Use the <b>Create New Folder</b> toolbar button to create the 'richedit' directory if it doesn't exist. Make sure you're in the 'richedit' directory (double click it) and enter a file name of 'richedit.pro'. Click the <b>Save</b> button. The 'Project File' field of the <em>Project Settings</em> dialog will have the path and name of your new project; click <b>OK</b> to create the project.</p>
<p>If you're unfamiliar with Actions and Action Groups the sidebar provides the necessary introduction; otherwise skip ahead to "Designing the Main Window".</p>
<blockquote>
<p align="center"><b> Actions and Action Groups</b></p>
<p>An <em>action</em> is an operation that the user initiates through the user interface, for example, saving a file or changing some text's font weight to bold.</p>
<p>We often want the user to be able to perform an action using a variety of means. For example, to save a file we might want the user to be able to press <b>Ctrl+S</b>, or to click the <b>Save</b> toolbar button or to click the <b>File|Save</b> menu option. Although the means of invoking the action are all different, the underlying operation is the same and we don't want to duplicate the code that performs the operation. In Qt we can create an action (a <b>QAction</b> object) which will call the appropriate function when the action is invoked. We can assign an accelerator, (e.g. <b>Ctrl+S</b>), to an action. We can also add an action to a menu item and to a toolbar button.</p>
<p>If the action has an on/off state, e.g. bold is on or off, when the user changes the state, for example by clicking a toolbar button, the state of everything associated with the action, e.g. menu items and toolbar buttons, are updated.</p>
<p>Some actions should operate together like radio buttons. For example, if we have left align, center align and right align actions, only one should be 'on' at any one time. An <em>action group</em> (a <b>QActionGroup</b> object) is used to group a set of actions together. If the action group's <tt>exclusive</tt> property is TRUE then only one of the actions in the group can be on at any one time. If the user changes the state of an action in an action group where <tt>exclusive</tt> is TRUE, everything associated with the actions in the action group, e.g. menu items and toolbar buttons, are updated.</p>
<!-- index Actions and Action Groups --><p><em>Qt Designer</em> can create actions and action groups visually, can assign accelerators to them, and can associate them with menu items and toolbar buttons.</p>
</blockquote>
<h3><a name="1"></a>Designing the Main Window</h3>
<!-- index Main Window!Creating --><!-- index Creating Main Windows --><!-- index Main Window!Wizard --><!-- index Wizards!Main Window --><!-- index Creating Menus --><!-- index Menus!Adding --><!-- index Adding!Menus --><!-- index Creating Toolbars --><!-- index Toolbars, Creating --><!-- index Toolbar Buttons!Adding --><!-- index Adding!Toolbars --><!-- index Adding!Actions and Action Groups --><!-- index Adding!Toolbar Buttons --><p>We will use the main window wizard to build a main window. The wizard allows us to create actions and a menu bar and a toolbar through which the user can invoke the actions. We will also create our own actions, menus and toolbar. We will add some widgets to the toolbar and add a main widget to the main window. Finally we will connect signals to slots to take advantage of Qt's default functionality and minimize our coding.</p>
<h4><a name="1-1"></a>Creating the Main Window</h4>
<p>Click <b>File|New</b> to invoke the <em>New File</em> dialog, click Mainwindow, then click <b>OK</b>. A new <b>QMainWindow</b> form will be created and the Mainwindow Wizard will pop up.</p>
<ol type=1><li><p>The <em>Choose available menus and toolbars</em> wizard page appears first. It presents three categories of default actions, File Actions, Edit Actions and Help Actions. For each category you can choose to have <em>Qt Designer</em> create menu items, toolbar buttons and signal/slots connections for the relevant actions. You can always add or delete actions, menu items, toolbar buttons and connections later.</p>
<!-- index Creating Menus --><!-- index Menus!Adding --><!-- index Creating Toolbars --><!-- index Toolbars, Creating --><!-- index Toolbar Buttons!Adding --><!-- index Adding!Menus --><!-- index Adding!Toolbars --><!-- index Adding!Actions and Action Groups --><!-- index Adding!Toolbar Buttons --><!-- index Signals and Slots!Connecting Actions --><p>We will accept the defaults for File Actions, i.e. have menu items, toolbar buttons and the relevant connections created. But for the Edit Actions we don't want any connections created since we'll be connecting the actions directly to the <b>QTextEdit</b> we'll create later, so uncheck the Edit Action's Create Slots and Connections checkbox. We won't have any Help Actions on the toolbar so uncheck the Help Action's Toolbar checkbox. Click <b>Next</b> to move on to the next wizard page.</p>
<p align="center"><img align="middle" src="qd-chapmainwin-mainwinwiz1.png" width="612" height="430">
</p>
<blockquote><p align="center"><em>Main Window Wizard- Choosing menus and toolbars</em></p></blockquote>
<li><!-- index Creating Toolbars --><!-- index Toolbars, Creating --><!-- index Toolbar Buttons!Adding --><!-- index Adding!Toolbar Buttons --><!-- index Separator!Menu item --><!-- index Separator!Toolbar button --><p>The <em>Setup Toolbar</em> wizard page is used to populate a toolbar with actions from each of the default action categories. The Category combobox is used to select which set of actions you wish to work on. The Actions list box lists the actions available for the current category. The Toolbar listbox lists the toolbar buttons you want to create. The blue left and right arrow buttons are used to move actions into or out of the Toolbar list box. The blue up and down arrow buttons are used to move actions up and down within the Toolbar list box. Note that the '&lt;Separator&gt;' item in the Actions list box may be moved to the Toolbar list box as often as required and will cause a separator to appear in the finished toolbar.</p>
<p>Copy the New, Open and Save Actions to the Toolbar list box. Copy a &lt;Separator&gt; to the Toolbar list box. Change the Category to Edit and copy the Undo, Redo, Cut Copy and Paste actions to the Toolbar list box. Click <b>Next</b> and then click <b>Finish</b>.</p>
<p align="center"><img align="middle" src="qd-chapmainwin-mainwinwiz2.png" width="612" height="430">
</p>
<blockquote><p align="center"><em>Main Window Wizard- Setting up the toolbar</ol></em></p></blockquote>
<p>If you preview the form (<b>Ctrl+T</b>) the File and Edit menus will be available and you'll be able to drag the toolbar either into an independent window of its own, or to dock it to the left, right, bottom or top of the window. The menus and toolbars are not functional yet but we will rectify this as we progress.</p>
<p align="center"><img align="middle" src="qd-chapmainwin-mainwinwiz3.png" width="608" height="508">
</p>
<blockquote><p align="center"><em>Previewing the Form</em></p></blockquote>
<p>Click <b>File|Save</b> to save the form as <tt>richedit.ui</tt>.</p>
<h4><a name="1-2"></a>Creating and Deleting Actions and Action Groups</h4>
<h5><a name="1-2-1"></a>Creating Actions</h5>
<!-- index Actions and Action Groups!Adding Actions --><!-- index Adding!Actions and Action Groups --><p>Our application requires more menu items and toolbar buttons than the the defaults we created with the main window wizard. But before we create the menu items and toolbar buttons we will create the actions that they'll invoke. The Action Editor appears automatically when you create a main window. You can also access it through the Window menu (click <b>Window|Action Editor</b>).</p>
<p align="center"><img align="middle" src="qd-chapmainwin-actioneditor1.png" width="200" height="242">
</p>
<blockquote><p align="center"><em>Action Editor</em></p></blockquote>
<p>For the richedit application we need to create actions for indicating bold, italic and underlined font attributes, and to set text alignment.</p>
<p>Right click in the <em>Action Editor</em> where the actions are listed, then left click New Action. This will create a new action called 'Action' at the top of the list of actions. The Property Editor will change to show the default settings for the new action. We'll now go through all the properties we need to change.</p>
<ol type=1><li><p>Change the <em>name</em> of the action to 'boldAction'.</p>
<li><p>Since bold can only be on or off change the <em>toggleAction</em> property to True.</p>
<li><!-- index Adding!Pixmaps --><!-- index Pixmaps!Adding --><p>The <em>iconSet</em> property is used to set an icon which will appear to the left of the action's name in any menu you associate the action with. The <em>iconSet</em> is also used for the toolbar button if you associate the action with a toolbar. Click the ellipsis button (<b>...</b>) to invoke the <em>Choose an Image</em> dialog. The ellipsis button appears when you click in the Value part of the Properties list by a <em>pixmap</em> or <em>iconSet</em> property. The pixmap we require is not in the default collection. Click the <b>Add</b> button and a file dialog will appear. The icons we require are in the Qt examples directory, <tt>qt/examples/textedit/</tt>. Navigate to the textedit directory and select the <tt>textbold.xpm</tt> file and then click <b>Open</b>. Click the new textbold icon in the pixmap collection then click <b>OK</b>.</p>
<p align="center"><img align="middle" src="qd-chapmainwin-actioneditor2.png" width="200" height="242">
</p>
<blockquote><p align="center"><em>Properties of Bold Action</em></p></blockquote>
<li><p>Change the <em>text</em> property to 'bold'. This automatically changes the <em>menuText</em>, <em>toolTip</em> and <em>statusTip</em> properties.</p>
<li><p>Change the menu text to '&amp;Bold'. If we choose to associate this action with a menu item then this property is used; otherwise it is ignored.</p>
<li><p>Change the <em>accel</em> property to 'CTRL+B'. This will associate the <b>Ctrl+B</b> keyboard accelerator with this action.</p>
<p align="center"><img align="middle" src="qd-chapmainwin-propeditnewact.png" width="217" height="351">
</p>
<blockquote><p align="center"><em>Properties for the Bold Action</em></p></blockquote>
</ol><p>Note that at this point the only way to invoke this action is to use the keyboard accelerator (<b>Ctrl+B</b>), because we have not yet associated the action with a menu item or with a toolbar button.</p>
<!-- index Adding!Actions and Action Groups --><p>We need to add two more actions, italic and underline. For each one right click the <em>Action Editor</em> and click New Action. Then repeat the steps listed above to change each action's properties:</p>
<ul><li><p>For the italic action change its <em>name</em> to 'italicAction' and ensure its <em>toggleAction</em> property is True. The <em>iconSet</em> is in the textedit directory and is called <tt>textitalic.xpm</tt>; add its pixmap in the same way that we added the bold pixmap. (For example, click the ellipsis (<b>...</b>), click <b>Add</b>, navigate to the textedit directory and click the <tt>textitalic.xpm</tt> pixmap and then click <b>Open</b>. Then click the textitalic icon in the pixmap collection and click <b>OK</b>). Change the action's <em>text</em> to 'italic', its <em>menuText</em> to '&amp;Italic' and its <em>accel</em> to 'CTRL+I'.</p>
<li><p>For the underline action change its <em>name</em> to 'underlineAction' and set its <em>toggleAction</em> property to True. The <em>iconSet</em> is in the same directory and is called <tt>textunder.xpm</tt>; add it in the same way as the previous pixmaps. Change its <em>text</em> to 'underline', its <em>menuText</em> to '&amp;Underline' and its <em>accel</em> to 'CTRL+U'.</p>
</ul><h5><a name="1-2-2"></a>Creating Action Groups</h5>
<!-- index Actions and Action Groups!Adding Action Groups --><!-- index Adding!Actions and Action Groups --><p>It is perfectly possible to have bold, italic and underline all active at once. But for alignment, i.e. left align, right align and centered, it only makes sense for one of them to be active at any one time. Because we need the alignment actions to operate in sync with one another we must create an Action Group which will automatically manage the behaviour of the actions it contains in the way we require.</p>
<!-- index Actions and Action Groups!Exclusive Actions --><!-- index Exclusive Actions, Actions and Action Groups --><p>Right click the <em>Action Editor</em> then left click New Action Group. Change the action group's <em>name</em> in the Property Editor to 'alignActionGroup', and change its <em>text</em> to 'align'. The '<em>exclusive</em>' property's default is True. This ensures that only one action within the action group can be 'on' at any one time which is the behaviour we require.</p>
<p>We create the actions within the action group in almost the same way as before. The only difference is that we must right click the alignActionGroup (rather than an Action) and then left click New Action to create a new action <em>within</em> the action group. We will create three new actions within the alignActionGroup:</p>
<ol type=1><li><!-- index Adding!Pixmaps --><!-- index Pixmaps!Adding --><p>Create a new action within the alignActionGroup action group. Change the <em>name</em> of this action to 'leftAlignAction' and ensure its <em>toggleAction</em> property is True. Use the <em>iconSet</em> in the textedit directory called <tt>textleft.xpm</tt>, adding the pixmap to the pixmap collection in the same way as we added the textbold pixmap earlier. Change its <em>text</em> to 'left', its menuText to '&amp;Left' and its <em>accel</em> to 'CTRL+L'.</p>
<p align="center"><img align="middle" src="qd-chapmainwin-actiongroup.png" width="200" height="236">
</p>
<blockquote><p align="center"><em>Creating an Action group</em></p></blockquote>
<li><p>Create another new action within alignActionGroup. Change this action's <em>name</em> to 'rightAlignAction' and set its <em>toggleAction</em> property to True. Set its <em>iconSet</em> to <tt>textright.xpm</tt> using the pixmap collection as before. Change its <em>text</em> to 'right', its menuText to '&amp;Right' and its <em>accel</em> to 'CTRL+R'.</p>
<li><p>Create a third action within alignActionGroup. Change its <em>name</em> to 'centerAlignAction' and make its <em>toggleAction</em> property True. Change its <em>iconSet</em> to <tt>textcenter.xpm</tt>. Change its <em>text</em> to 'center' and its <em>menuText</em> to '&amp;Center'. We won't set an accelerator for this action.</p>
<p align="center"><img align="middle" src="qd-chapmainwin-alignactiongroup.png" width="200" height="236">
</p>
<blockquote><p align="center"><em>Align Action Group</em></p></blockquote>
</ol><p>Note that the <em>toolTip</em> and <em>statusTip</em> properties were inherited from the action group; you may wish to change these to be specific to the actions concerned.</p>
<h5><a name="1-2-3"></a>Deleting Actions and Action Groups</h5>
<!-- index Actions and Action Groups!Deleting --><!-- index Deleting!Actions and Action Groups --><p>We have some actions that we don't intend providing for this first release, for example, the editFindAction and the filePrintAction. Click editFindAction and then click the <b>Delete Action</b> toolbar button. Delete the filePrintAction in the same way. Action Groups (including any actions they contain) can also be deleted with the <b>Delete Action</b> toolbar button.</p>
<p align="center"><img align="middle" src="qd-chapmainwin-deleteaction.png" width="200" height="236">
</p>
<blockquote><p align="center"><em>Deleting editFindAction</em></p></blockquote>
<h4><a name="1-3"></a>Creating and Populating a Toolbar</h4>
<!-- index Creating Toolbars --><!-- index Adding!Toolbars --><!-- index Toolbars, Creating --><p>All the actions we require are now in place and we are ready to create a new toolbar and add some of our actions to it. Right click on the right hand side of the toolbar area, or on the form, then left click Add Toolbar. The new toolbar is empty and is visible only by its <em>toolbar handle</em>. (Toolbar handle's are usually represented as a gray area containing either two thick vertical lines or with many small pits).</p>
<p align="center"><img align="middle" src="qd-chapmainwin-toolbarhandle.png" width="90" height="30">
</p>
<blockquote><p align="center"><em>Toolbar Handle</em></p></blockquote>
<!-- index Actions and Action Groups!Adding to a Toolbar --><!-- index Separator!Toolbar button --><!-- index Adding!Actions and Action Groups to a Toolbar --><!-- index Adding!Toolbar Separators --><p>We'll add the new actions we've just created. Drag the alignActionGroup, (not any action it contains), to the new toolbar and drop it on the toolbar handle to the right of the vertical lines. The three alignment actions will be added to the toolbar.</p>
<p align="center"><img align="middle" src="qd-chapmainwin-toolbarhandle2.png" width="290" height="37">
</p>
<blockquote><p align="center"><em>Dragging the Action Group to the Toolbar</em></p></blockquote>
<p align="center"><img align="middle" src="qd-chapmainwin-toolbaractiongroup1.png" width="353" height="30">
</p>
<blockquote><p align="center"><em>Populating the Toolbar with an Action Group</em></p></blockquote>
<p>The bold, italic and underline actions do not belong to an action group, and must be dragged to the toolbar individually. Drag the bold action to the toolbar: when the mouse is over the toolbar a thick red line will appear indicating the position at which the toolbar button will be inserted; drop the bold action on the toolbar. Drag the italic and underline actions to the toolbar and drop them next to the bold button. Separate the alignment toolbar buttons from the font related buttons by right clicking the centered toolbar button and clicking Insert Separator.</p>
<!-- index Separator!Toolbar button --><!-- index Deleting!Toolbar Separators --><!-- index Deleting!Toolbars --><p>Toolbar buttons and separators (usually represented as indented vertical gray lines), can be dragged and dropped into new positions in the toolbar at any time. Separators can be inserted by right clicking a toolbar button and clicking Insert Separator. Toolbar buttons and separators can be deleted by right clicking them and clicking Delete Item. Toolbars can be deleted by right clicking their toolbar handle and clicking Delete Toolbar.</p>
<!-- index Previewing!Toolbars --><p>If you preview the application you'll find that both the original and new toolbar can be dragged to different docking points or dragged out of the application as independent tool windows.</p>
<p align="center"><img align="middle" src="qd-chapmainwin-previewing.png" width="448" height="29">
</p>
<blockquote><p align="center"><em>Toolbar with all the Actions Added</em></p></blockquote>
<h5><a name="1-3-1"></a>Adding Widgets to the Toolbar</h5>
<!-- index Toolbars!Adding Widgets --><!-- index Widgets!Adding to Toolbars --><!-- index Adding!Widgets --><p>We want our users to be able to choose the font and font size from the toolbar. To achieve this we'll create a font combobox and a font size spinbox and place them in the formatting toolbar we created in the previous section.</p>
<!-- index Widgets!ComboBox --><!-- index Widgets!SpinBox --><!-- index Separator!Toolbar button --><p>Click <em>Qt Designer</em>'s <b>ComboBox</b> toolbar button and click the last (right-most) toolbar button in the application's new toolbar. Change the combobox's name to 'fontComboBox'. Click the <b>SpinBox</b> toolbar button and click the combobox we've just added to insert the spinbox next to it. Change the spinbox's <em>minValue</em> property to 6, its <em>value</em> property to 10 and its <em>suffix</em> to a space followed by 'pt'. Insert a separator to the left of the combobox.</p>
<p align="center"><img align="middle" src="qd-chapmainwin-addwidg.png" width="622" height="35">
</p>
<blockquote><p align="center"><em>Adding Widgets to the Toolbar</em></p></blockquote>
<p>Although you can put any widget into a toolbar we recommend that widgets which can be associated with an action should <em>not</em> be added to the toolbar directly. For these widgets, i.e. menu items, toolbar buttons and lists of items, you should create an action (drop down action for a list of items), associate the action with the widget, and add the action to the toolbar. Widgets that can sensibly be inserted directly into a toolbar are <em>ComboBox</em>es, <em>SpinBox</em>es and <em>Line Edit</em>s.</p>
<h4><a name="1-4"></a>Creating Menus</h4>
<!-- index Creating Menus --><!-- index Menus!Adding --><!-- index Adding!Menus --><p>We'll now add the actions we added to the new toolbar to a new menu and modify the existing menus slightly.</p>
<!-- index Menus!Adding Menu Items --><!-- index Adding!Menu Items --><p>Right click our application's menu bar and click Add Menu Item. A new menu item called 'Menu' will appear. Right click this menu item and click Rename Item. Change its name to 'F&amp;ormat'.</p>
<p align="center"><img align="middle" src="qd-chapmainwin-namemenu.png" width="403" height="147">
</p>
<blockquote><p align="center"><em>Format Menu</em></p></blockquote>
<p>Click the menu item and a red bar will appear beneath it -- this is the empty menu. Drag the alignActionGroup from the Action Editor to the Format menu item and drop the action group on the menu. (The menu's red bar will appear and a thick red line will be drawn where the new menu items will appear -- drop when the red line is in the position you require.) Now if you click the Format menu item the three alignment actions will be displayed. Just like the toolbar we must add the bold, italic and underline actions individually. Drag the bold action to the Format menu and move the mouse so that the red line is positioned at the bottom of the menu, then drop the action. Repeat this process for the italic and underline actions.</p>
<p align="center"><img align="middle" src="qd-chapmainwin-dragtomenu.png" width="182" height="62">
</p>
<blockquote><p align="center"><em>Draggin the Action Group to the Menu Bar</em></p></blockquote>
<p align="center"><img align="middle" src="qd-chapmainwin-dropinmenu1.png" width="450" height="169">
</p>
<blockquote><p align="center"><em>Dragging and Dropping Align Action Group to the Format Menu</em></p></blockquote>
<!-- index Creating Menus --><!-- index Menus!Adding --><!-- index Separator!Menu item --><!-- index Menus!Adding Menu Separators --><!-- index Adding!Menu Separators --><!-- index Menus!Deleting --><!-- index Deleting!Menus --><!-- index Deleting!Menu Items --><!-- index Deleting!Menu Separators --><p>We'll now deal with the separators in the menus. Firstly we'll add a separator in the Format menu and then we'll remove some redundant separators from the other menus. Click the Format menu and right click the bold item towards the top of the highlighted area; click Insert Separator. Note that you could also right click the center align item towards the bottom of the highlighted area to insert the separator between the align actions and the font actions. ###Click the File menu and right click one of the separators above the Exit action; click Delete Item. Click the Edit menu, right click the separator at the very bottom of the menu and click Delete Item. Delete Item can be used to delete separators, menu items and menus.###</p>
<!-- index Menus!Moving --><p>Click the Format menu and drag it to the left of the Help menu, then drop the Format menu. (A thick red bar will appear to indicate the insertion postion.) Both menus and menu items may be dragged and dropped to different positions in the same way.</p>
<!-- index Previewing!Menus --><p>Preview the application and try clicking the alignment and font style toolbar buttons and menu items. Qt will automatically keep the state of the menu items and the toolbar buttons synchronized.</p>
<h4><a name="1-5"></a>Adding and Connecting the Main Widget</h4>
<!-- index Main Widget --><!-- index Adding!Main Widgets --><!-- index Widgets!Adding a Main Widget --><!-- index Main Window!Adding a Main Widget --><!-- index Signals and Slots --><p>Our application is a rich text editor, but so far there has been nowhere for the user to edit text. We'll add a <b>QTextEdit</b> widget and use Qt's signals and slots mechanism to minimize the code we have to write to make it functional.</p>
<p>Click <em>Qt Designer</em>'s Richtext Editor (<b>Text Edit</b>) toolbar button and click in the center of the form. Click the form, then click the <b>Lay Out Horizontally</b> toolbar button. We're now ready to make the connections we need; but first we will do some renaming to make things easier to understand. Click on the <em>Text Edit</em> widget and change its <em>name</em> property to 'textEdit'. Change the <em>textFormat</em> property to 'RichText'. Change the <em>name</em> of the form to 'EditorForm' and its caption to 'Rich Edit'.</p>
<p align="center"><img align="middle" src="qd-chapmainwin-addtextedit.png" width="617" height="362">
</p>
<blockquote><p align="center"><em>Adding Rich Text Edit Widget</em></p></blockquote>
<!-- index Clipboard --><!-- index Cut and Paste (in Applications) --><p>The <b>QTextEdit</b> widget contains built-in functionality for cut and paste and various other editing functions. By connecting the appropriate signals to our textEdit we can take advantage of this functionality without the need to write any code.</p>
<h5><a name="1-5-1"></a>Connecting Actions to Change Font Attributes</h5>
<!-- index Signals and Slots!Connecting Actions --><p>Click the underlineAction in the <em>Action Editor</em>, then click the Connect button in the Action Editor toolbar. The <em>Edit Connections</em> dialog will appear. Click the<!-- index toggled() --> <tt>toggled()</tt> signal. Since we wish to connect this signal to the text edit widget, drop down the Slots combobox and click textEdit. The text edit's slots that can respond to a toggled signal will appear in the right hand list box. Click the<!-- index  --> setUnderline() <tt>setUnderline()</tt> slot, then click <b>OK</b>.</p>
<p align="center"><img align="middle" src="qd-chapmainwin-connaction.png" width="617" height="363">
</p>
<blockquote><p align="center"><em>Connecting the Underline Action</em></p></blockquote>
<p>Connect up the bold and italic actions in the same way. (For example, click the bold action and click Connect. Click the<!-- index toggled() --> <tt>toggled()</tt> signal, change the Slots combobox item to textEdit and click the<!-- index setBold() \SignalOrSlot setBold() slot. --> Click <b>OK</b>.) If you preview the form you'll find that you can enter text and that choosing bold, italic or underline will work.</p>
<h5><a name="1-5-2"></a>Connecting Actions to Implement Cut, Copy, Paste, Undo and Redo</h5>
<!-- index Clipboard --><!-- index Cut and Paste (in Applications) --><!-- index Signals and Slots!Connecting for Cut --><!-- index Signals and Slots!Connecting for Copy --><!-- index Signals and Slots!Connecting for Paste --><!-- index Signals and Slots!Connecting for Undo --><!-- index Signals and Slots!Connecting for Redo --><!-- index Previewing!Signals and Slots --><!-- index Signals and Slots!Previewing --><p>The cut, copy, paste, undo and redo actions are connected in the same way as the font attributes. For example, click the editPasteAction action and click Connect. Click the<!-- index activated() \SignalOrSlot --> activated() signal, change the Slots combobox item to textEdit and click the<!-- index paste() \SignalOrSlot paste() slot. Click \OK to save --> the connection. Connect the cut, copy, undo and redo actions in the same way. (For example, click the editCopyAction action, click Connect, click the<!-- index activated() \SignalOrSlot activated() --> signal, change the Slots combobox item to textEdit, click the<!-- index  --> copy() <tt>copy()</tt> slot then click <b>OK</b>.) Then the cut, copy, paste, undo and redo actions will all work in preview mode.</p>
<h5><a name="1-5-3"></a>Connecting for Text Alignment</h5>
<!-- index Signals and Slots!Connecting for Text Alignment --><!-- index Text Alignment --><p>We need to create a slot to receive signals from alignment actions and set the textEdit widget's alignment state accordingly. One approach would be to connect each individual alignment action to our slot, but because the align actions are in a group we will connect the alignActionGroup to our slot and determine which alignment the user chose from the <b>QAction</b> pointer that is passed.</p>
<p>Create a new slot with the signature <tt>changeAlignment(QAction *align)</tt>. (Click <b>Edit|Slots</b>, click <b>New Slot</b>, enter the slot's signature and click <b>OK</b>.) Click alignActionGroup in the <em>Action Editor</em>, then click <b>Connect</b>. Connect the<!-- index selected(QAction*) \SignalOrSlot --> selected(QAction*) signal to our change alignment slot, then click <b>OK</b>.</p>
<p align="center"><img align="middle" src="qd-chapmainwin-connalign1.png" width="661" height="362">
</p>
<blockquote><p align="center"><em>Connecting the Alignment Actions</em></p></blockquote>
<p>We'll have to write the code to set the alignment ourselves; we'll cover this in <a href="designer-manual-3.html#2-1-2">Aligning Text</a>.</p>
<h5><a name="1-5-4"></a>Connecting for Font Names and Sizes</h5>
<!-- index Connecting!Signals and Slots --><!-- index Signals and Slots!Connecting for Font Sizes --><!-- index Signals and Slots!Connecting for Font Names --><!-- index Font Sizes --><!-- index Previewing!Signals and Slots --><!-- index Signals and Slots!Previewing --><p>We'll start by dealing with font size since it's easiest. Click the <b>Connect Signals/Slots</b> toolbar button then click the spinbox and drag to the text edit widget; release on the text edit. Click the<!-- index valueChanged(int) \SignalOrSlot valueChanged(int) --> signal and then click the textEdit's<!-- index setPointSize(int) \SignalOrSlot --> setPointSize(int) slot. Click <b>OK</b> and font sizes are done. (Since font sizes are handled purely through built-in signals and slots they work in preview mode.)</p>
<p align="center"><img align="middle" src="qd-chapmainwin-connfontsize.png" width="617" height="363">
</p>
<blockquote><p align="center"><em>Connecting the Font Sizes</em></p></blockquote>
<p>Connect the fontComboBox's<!-- index activated() --> <tt>activated()</tt> signal to the textEdit's<!-- index setFamily() --> <tt>setFamily()</tt> slot. This connection will handle updating the textEdit's font family with the user's choice of font. Note that when you invoke the <em>Edit Connections</em> dialog the first signal that is highlighted is <tt>activated(int)</tt>. Since the<!-- index  --> setFamily() <tt>setFamily()</tt> slot takes a <b>QString</b> argument it does <em>not</em> appear in the list of slots. Only those slots which are compatible with the highlighted signal are shown, in this case, slots which take no argument or which take an integer argument. Click the <tt>activated(const QString</tt>&amp;) signal and the list of slots will change to those which take no argument or which take a <b>QString</b> argument; the list will now include<!-- index setFamily() --> <tt>setFamily()</tt> since this takes a <b>QString</b> argument. We will have to populate the combobox with the font names for the user to choose from in code. (See the<!-- index init() \Func init() function --> in <a href="designer-manual-3.html#2-1-3">Changing Fonts</a>.) It's a good idea to connect the fontComboBox's<!-- index activate() \SignalOrSlot activate() signal to --> the textEdit's<!-- index setFocus() \SignalOrSlot setFocus() slot; this --> will ensure that after the user has changed font the focus will return to the text.</p>
<p>The richedit application is nearly complete. We will have to write code to handle text alignment, font family and file loading and saving. We will also write the code for application exit to deal correctly with any unsaved changes.</p>
<h3><a name="2"></a>Converting the Design into an Executable Application</h3>
<!-- index Code Editing --><!-- index Adding!Code!Code Editing --><p>We've built the user interface through <em>Qt Designer</em> and connected those slots that provided sufficient default functionality. The last steps are to code the slots that require customization and then to create<!-- index main.cpp --> <tt>main.cpp</tt> so that we can compile and build our application.</p>
<h4><a name="2-1"></a>Implementing the Main Window's Functionality</h4>
<p>When the user starts the richedit application we want the focus to be in the textEdit widget so we need to create an<!-- index init() --> <tt>init()</tt> function with one line of code to achieve this. (All the code snippets are from <tt>qt/tools/designer/examples/richedit/richedit.ui.h</tt>.)</p>
<pre>    void EditorForm::init()
    {
        textEdit-&gt;setFocus();
            }
</pre>
<p>We'll add more to this function later.</p>
<h5><a name="2-1-1"></a>New Files and Loading and Saving Existing Files</h5>
<p>The code for these tasks is straightforward. When the user clicks <b>File|New</b> we check to see if there are unsaved changes in the existing text and give them the opportunity to save, continue without saving or cancel the operation. When the user opts to open an existing file or exit the application we perform the same check and offer them the same choices.</p>
<pre>    void EditorForm::fileNew()
    {
        if ( saveAndContinue( "New" ) )
            textEdit-&gt;clear();
    }
</pre>
 <p>The <tt>fileNew()</tt> function clears the text and the filename.</p>
<pre>    void EditorForm::fileOpen()
    {
        if ( saveAndContinue( "Open" ) ) {
            <a href="qstring.html">QString</a> fn( QFileDialog::<a href="qfiledialog.html#getOpenFileName">getOpenFileName</a>(
                            QString::null,
                            "Rich Text Files (*.htm*)", this ) );
            if ( !fn.<a href="qstring.html#isEmpty">isEmpty</a>() ) {
                fileName = fn;
                <a href="qfile.html">QFile</a> file( fileName );
                if ( file.<a href="qfile.html#open">open</a>( IO_ReadOnly ) ) {
                    <a href="qtextstream.html">QTextStream</a> ts( &amp;file );
                    textEdit-&gt;setText( ts.<a href="qtextstream.html#read">read</a>() );
                }
            }
        }
    }
</pre>
 <p>The <tt>fileOpen()</tt> function asks the user to choose a file using<!-- index QFileDialog::getOpenFileName() --> <tt>QFileDialog::getOpenFileName()</tt>. If they choose a file we set the fileName member to its name, open it and read its contents directly into the text edit via a text stream.</p>
<pre>    void EditorForm::fileSave()
    {
        if ( fileName.isEmpty() ) {
            fileSaveAs();
        } else {
            <a href="qfile.html">QFile</a> f( fileName );
            if ( f.<a href="qfile.html#open">open</a>( IO_WriteOnly ) ) {
                <a href="qtextstream.html">QTextStream</a> ts( &amp;f );
                ts &lt;&lt; textEdit-&gt;text();
                textEdit-&gt;setModified( FALSE );
            }
        }
    }
</pre>
 <p>If there is no current file name we call <tt>fileSaveAs()</tt> which will prompt for a file name and if a file name is given calls <tt>fileSave()</tt>. If we have a file name we open a file and write the text from the text edit into the file via a text stream. We also set the text edit's modified property to FALSE.</p>
<pre>    void EditorForm::fileSaveAs()
    {
        <a href="qstring.html">QString</a> fn = QFileDialog::<a href="qfiledialog.html#getSaveFileName">getSaveFileName</a>(
                                    "", "Rich Text Files (*.htm*)", this );
        if ( !fn.<a href="qstring.html#isEmpty">isEmpty</a>() ) {
            fileName = fn;
            fileSave();
        }
    }
</pre>
 <p>The <tt>fileSaveAs</tt> function prompts the user for a file name and if they give a file name, saves the text to the file by calling <tt>fileSave()</tt>.</p>
<pre>    void EditorForm::fileExit()
    {
        if ( saveAndContinue( "Exit" ) )
            qApp-&gt;<a href="qapplication.html#exit">exit</a>();
    }
</pre>
 <p>When we exit the application we must perform the same check for unsaved changes as we've done in the preceding functions, so we've included the <tt>fileExit()</tt> function's code here.</p>
<pre>    int EditorForm::saveAndContinue(const <a href="qstring.html">QString</a> &amp; action)
    {
        int continueAction = 1;

        if ( textEdit-&gt;isModified() ) {
            switch( QMessageBox::<a href="qmessagebox.html#information">information</a>(
                    this, "Rich Edit",
                    "The document contains unsaved changes.\n"
                    "Do you want to save the changes?",
                    "&amp;Save", "&amp;Don't Save", "&amp;Cancel " + action,
                    0, // Enter == button 0
                    2 ) ) { // Escape == button 2
            case 0: // Save; continue
                    fileSave();
                    break;
            case 1: // Do not save; continue
                    break;
            case 2: // Cancel
                    continueAction = 0;
                    break;
            }
        }

        return continueAction;
    }
</pre>
 <p>The <tt>saveAndContinue()</tt> function is included for completeness.</p>
<h5><a name="2-1-2"></a>Aligning Text</h5>
<pre>    void EditorForm::changeAlignment(QAction * align)
    {
        if ( align == leftAlignAction )
            textEdit-&gt;setAlignment( Qt::<a href="qt.html#AlignmentFlags-enum">AlignLeft</a> );
        else if ( align == rightAlignAction )
            textEdit-&gt;setAlignment( Qt::<a href="qt.html#AlignmentFlags-enum">AlignRight</a> );
        else if ( align == centerAlignAction )
            textEdit-&gt;setAlignment( Qt::<a href="qt.html#AlignmentFlags-enum">AlignCenter</a> );
    }
</pre>
 <p>We compare the chosen alignment action's pointer to the the pointers stored in the form and if we get a match set the appropriate alignment in the textEdit widget.</p>
<h5><a name="2-1-3"></a>Changing Fonts</h5>
<p>We've already connected the fontComboBox's<!-- index activated() --> <tt>activated()</tt> signal to the textEdit's<!-- index setFamily() --> <tt>setFamily()</tt> slot so we just have to populate the combobox with the font names when we call<!-- index init() --> <tt>init()</tt>.</p>
<pre>    void EditorForm::init()
    {
        textEdit-&gt;setFocus();

        <a href="qfontdatabase.html">QFontDatabase</a> fonts;
        fontComboBox-&gt;insertStringList( fonts.<a href="qfontdatabase.html#families">families</a>() );
        <a href="qstring.html">QString</a> font = textEdit-&gt;family();
        <a href="qwidget.html#font-prop">font</a> = font.<a href="qstring.html#lower">lower</a>();
        for ( int i = 0 ; i &lt; fontComboBox-&gt;count(); i++ ) {
            if ( <a href="qwidget.html#font-prop">font</a> == fontComboBox-&gt;text( i ) ) {
                fontComboBox-&gt;setCurrentItem( i );
                break;
            }
        }
    }
</pre>
 <p>The first line sets the focus as we've already mentioned. We then create a <b>QFontDatabase</b> object and insert its list of font families into the fontComboBox. Finally we set the fontComboBox's current item to the textEdit's current font.</p>
<h4><a name="2-2"></a>Making the Application Run</h4>
<!-- index Object Hierarchy --><!-- index Forms!Forward declarations --><!-- index Forward declarations --><!-- index Includes --><!-- index Adding!Forward declarations --><!-- index Adding!Includes --><p>With all the connections and code in place we are now ready to make our application run. Click on the Source tab of the Object Hierarchy window and click on the Includes (in Implementation) item. We need to include the files that our source code depends on. Right click the Includes item and click New. Type in <tt>&lt;qapplication.h&gt;</tt> for <tt>fileExit()</tt>'s<!-- index exit() --> <tt>exit()</tt> call. In the same way add <tt>&lt;qmessagebox.h&gt;</tt> for <tt>saveAndContinue()</tt>'s message box, <tt>&lt;qfiledialog.h&gt;</tt> for the <tt>fileOpen()</tt> and <tt>fileSaveAs()</tt> functions, and <tt>&lt;qfontdatabase.h&gt;</tt> for the <b>QFontDatabase</b> class in<!-- index init() --> <tt>init()</tt>.</p>
<!-- index Forms!Class variables --><!-- index Adding!Class variables --><!-- index Class variables --><p>We referred to a member variable, <tt>fileName</tt>, in our source code so we must add it to the form. Click the Source tab, right click the Class Variables item, click New from the pop up menu, then enter 'QString fileName;'.</p>
<!-- index Adding!Source Files to Project Files --><p>The simplest way to create a new source file is by clicking <b>File|New</b> to invoke the 'New File' dialog, then click 'C++ Source' or 'C++ Header' as appropriate, then click <b>OK</b>. A new empty source window will appear. Click <b>File|Save</b> to invoke the <em>Save As</em> dialog, enter 'main.cpp', then click <b>Save</b>. Enter the following code in the <tt>main.cpp</tt> C++ editor window:</p>
<pre>    #include &lt;<a href="qapplication-h.html">qapplication.h</a>&gt;
    #include "richedit.h"

    int main( int argc, char *argv[] )
    {
        <a href="qapplication.html">QApplication</a> app( argc, argv );

        EditorForm richeditForm;
        app.<a href="qapplication.html#setMainWidget">setMainWidget</a>( &amp;richeditForm );
        richeditForm.show();

        return app.<a href="qapplication.html#exec">exec</a>();
    }
</pre>
<!-- index Makefiles --> <p>All that's left to do is to generate the Makefile, compile and run. The Makefile is created with <tt>qmake</tt>: <tt>qmake -o Makefile richedit.pro</tt>.</p>
<p>The richedit application demonstrates how easy it is to create a Qt application's main window with menus and dockable toolbars. A great deal of functionality was obtained by connecting the appropriate built-in signals and slots. The remaining functionality was achieved by connecting built-in signals to our own custom slots. We could continue developing the application, for example updating the fontComboBox, the font size spinbox and the actions with the font attributes as the user moves the cursor through their text. But our objective has been to demonstrate the creation of a main window with actions, menus and toolbars so we must stop at this point and leave further development and experimentation to you.</p>
<!-- eof -->
<p align="right">[<a href="designer-manual-2.html">Prev: Creating a Qt Application</a>] [<a href="designer-manual.html">Home</a>] [<a href="designer-manual-4.html">Next: The Designer Approach</a>]</p>
<p><address><hr><div align=center>
<table width=100% cellspacing=0 border=0><tr>
<td>Copyright &copy; 2001 
<a href="http://www.trolltech.com">Trolltech</a><td><a href="http://www.trolltech.com/trademarks.html">Trademarks</a>
<td align=right><div align=right>Qt version 3.0.2</div>
</table></div></address></body>
</html>