The K Desktop Environment

Next Previous Table of Contents

5. User Control Elements

5.1 The Menubar

The menu bar is a central component of the main window. It allows the user to execute operations that the application (or to be precise: the mainview) offers in regards of manipulating the main view's contents. In opposition to Qt's QMenuBar, KDE offers the use of the class KMenuBar. Additionally, the menu bar is already constructed for the programmer when using KTMainWindow with the first call of menuBar().

The menu bar itself, independent which class is going to be used, contains entries that the user can select with the mouse or by using keyboard accelerators with the ALT-key and the underlined character. The menus that have to pop up on a selection have to be created with the class QPopupMenu, which itself only provides the popups, entries have to be inserted using the methods provided by QMenuData.

Mind that menu-bars should always contain all functions a program has to offer except those that can be accessed by additional dialogs. The menu bar also makes use of the KApplication help menu already provided. Inserting the menu is just easy with

menuBar()->insertItem(i18n("Help"), kapp->getHelpMenu());

Example construction of a menu bar with using KTMainWindow and setting the menu bar explicitely:


my_menubar=new KMenuBar(this,"my_menubar");

file_menu = new QPopupMenu;
file_menu->insertItem(Icon("filenew.xpm"),i18n("&New..."),
                      this,SLOT(slotFileNew()),0,ID_FILE_NEW);
file_menu->insertItem(Icon("open.xpm"),i18n("&Open..."),
                      this, SLOT(slotFileOpen()),0 ,ID_FILE_OPEN);
file_menu->insertItem(i18n("&Close"),
                      this, SLOT(slotFileClose()),0,ID_FILE_CLOSE);
file_menu->insertSeparator();
file_menu->insertItem(Icon("save.xpm"),i18n("&Save"),
                      this, SLOT(slotFileSave()),0 ,ID_FILE_SAVE);
file_menu->insertItem(i18n("Save &As..."),
                      this, SLOT(slotFileSaveAs()),0 ,ID_FILE_SAVE_AS);
file_menu->insertItem(Icon("save_all.xpm"),i18n("Save All"),
                      this, SLOT(slotFileSaveAll()),0,ID_FILE_SAVE_ALL);
file_menu->insertSeparator();
file_menu->insertItem(Icon("fileprint.xpm"),i18n("&Print..."),
                      this, SLOT(slotFilePrint()),0 ,ID_FILE_PRINT);
file_menu->insertSeparator();
file_menu->insertItem(i18n("E&xit"),
                      this, SLOT(slotFileQuit()),0 ,ID_FILE_QUIT);

my_menubar->insertItem(i18n("&File"), file_menu);

setMenu(my_menubar);

The example creates a menu bar and a popup menu first. Then the popup menu is filled with entries. The used method of QMenuData here allows an implicit connection to the method to call when the popup menu emits SIGNAL(activated(int)). The zero parameters after the slot declaration is left out as the example assumes the program will use KAccel to set the according keyboard accelerators with changeMenuAccel(). Further you can see that the integer value ID is inserted like the method name with all uppercase letters and underscores to separate the words. The menu id's themselves are set with #define in a separate file to keep track of the used numbers. You would think that you don't need the menu id if the activated() signal is already connected - in fact the id can be used to forward the signal highlighted(int) to a method that compares the id by a switch statement and sets a statusbar help message for the menu entry. You could as well do that for the signal activated(int) as well to call the according method by a switch statement. Then you have to add a connect() for each popup menu you want to use.

You can as well insert a separator into the menu bar with my_menubar->insertSeparator(). This will align all entries inserted after the separator to the right in Motif style, in windows style this has no effect.

The creation of a separate menu bar allows the creation of several menubars which can be set as the actual menu with setMenu(). This is how we did it in KDevelop to change the menu bar when switching to the dialogeditor and back to the project editor.

Finally, the ampersand in the menu entry sets the following character as the keyboard accelerator when the user presses ALT+ the character.

5.2 The Toolbar

Toolbars are another component that enhance user interaction with symbols representing most needed functions that an application provides. The KDE libraries are again offering another class to use with KDE applications, KToolBar. As KTMainWindow already handles the geometry management for all user interface elements, it also provides methods to add toolbars. Now, the good thing is that you can use as many toolbars as your application may require and the creation is done easily with toolBar(). This method also takes a parameter which is the according toolbarnumber. The first toolbar has by default number 0, so the parameter can be left out there; the next has to be called with toolBar(1) etc. You can also make this more variable with a define for your toolbar and use a descriptive name; this avoids changing the toolbarnumber everywhere when you decide to set a toolbar to another position.

Now, when using a toolbar, you have many choices. The class KToolBar provides a whole set of methods to insert user elements such as buttons, which is probably the most recently used method, delayed popups, lineedits, combos and generally a widget of your choice. Further you need to know that toolbars are created with using the full width of the parent window - but that is configurable. All following toolbars are then appended to the end of the last toolbar. Also you can set the toolbar to show at a certain position. This is often used by applications that offer painting facilities. The following example shows you how to use a toolbar with KTMainWindow:


1   // first call of toolBar() - creates the toolbar 0.
2   toolBar()->insertButton(Icon("new.xpm"), ID_FILE_NEW, true, i18n("New File"));

3   QPopupMenu* select_menu = new QPopupMenu();
4   toolBar()->insertButton(Icon("select.xpm"), ID_OPTIONS_SELECT, select_menu, true, i18n("Select Option"));

5   connect(toolBar(), SIGNAL(clicked( int )), SLOT( slotSelected( int )) );


6   Foo::slotSelected( int id ){

7     switch (id ){

8       case ID_FILE_NEW:
9         slotFileNew();
10        break;
11    }
12  }

The above explains some specialities for toolbars - we will discuss these now in detail. First of all, you see that we used the toolBar() method. This returns a pointer to the according toolbar and creates one if the toolbar doesn't exist. We use the insertButton() method to add a toolbar button representing the standard "New File" action. Now, when looking at the class-documentation of KToolBar, you see that there is a QPixmap required as the first parameter. Here, we only set the name of the pixmap embraced by the Icon() method. This is a macro which makes inserting icons very easy, provided by kapp.h. In fact, it makes the application's KIconLoader instance load the icon with the filename new.xpm for you using a list of standard directories within the KDE File System. Additionally, the icon new.xpm is already provided - you don't have to paint it yourself. The KDE libraries come with a whole set of toolbar icons that are ready to use for insertion. This is also the reason why, when testing an application, sometimes a button looks a bit scrambled although you have painted the pixmap - it just can't be found if it isn't installed at the correct location within the KDE FSSTD; whereas standard icons are already present.

The exact execution of the Icon() macro is therefore:

KApplication::getKApplication()->getIconLoader()->loadIcon("new.xpm")
In KDE2, you have to use BarIcon() to load menu/toolbar icons

which implicitely uses the kapp macro to get the application object. You see that using this macro saves lots of code but offers a very nice way to load an icon for a toolbar button.

The second parameter, the ID of the button, is a macro that our application specifies itself to name certain actions logically by a #define. Obviously, you could think that using another method of KToolBar would do the same when directly specifying the receiver object and the slot to call, but this way you save a lot of code. The first place is that you only have to write one connect() (line 5) to connect all toolbar elements. The other is, that by this way you can use the same ID for your toolbar items as well as for your menubar items. The following code completes this example with the according menubar action:

QPopupMenu* file_menu = new QPopupMenu();
file_menu->insertItem(Icon("filenew.xpm"),i18n("&New..."),0,ID_FILE_NEW);

connect(file_menu, SIGNAL(activated(int)), SLOT(slotSelected(int)));

menuBar()->insertItem(file_menu, i18n("&File"));

By this, the file_menu is already connected to the slotSelected() method and the corresponding entry "New File" executes the same action. Just collect all your ID's as #defines into one file and you can keep a good overview over the used numbers (which naturally have to be integer values).

The next example in line 3 and 4 add a button that opens a popup menu when the user presses the button. This can be used if the button itself does not perform any action but represents a better access method for e.g. a list of entries. Just create your popup menu and insert it with the according ID and pointer as a button.

Besides the example you can do a lot of other things like making a button a toggle button. This is useful if the button executes an on/off action (which in the corresponding menubar popup is represented by a checkmark). See the complete reference of KToolBar for more information.

5.3 The Statusbar

KDE also provides the pendant to Qt's QStatusBar, KStatusBar. The statusbar can contain labels as well as widgets, such as progress bars (those have to have the statusbar as parent). The statusbar is used to display information about the current state of the application and gives hints about the usage of commands e.g. over toolbars and menubars.

5.4 Keyboard Accelerators

Keyboard accelerators are a good enhancement for any kind of application. GUI application designers often think that the user can access all methods with the provided graphical interface, but advanced users usually want to work as fast as possible and using the mouse to call actions doesn't make an application very attractive. The more a user will make use of your application, the more he will miss keyboard accelerators. Fortunately, the Qt and KDE libraries provide a whole set of functions and classes to support keyboard accelerators in conjunction with GUI elements. This section therefore collects all these classes and shows the possible implememtation for various situations.

Menu Accelerators

The first thing where keyboard accelerators are used without much effort from the programmer's side is over menuentries. The menubar, as mentioned above, consists of a set of QPopupMenus, which are inserted in the order they will appear later from left to right. The popup menu itself can be called by the user by a keyboard shortcut if he presses the ALT-key together with the underlined character of the desired menu of the menubar. The menuentry itself has to define the underlined character at the time you insert the popup into the menubar.

Example:

menuBar()->insertItem(i18n("&File"), file_menu);

Mind the ampersand in front of "File". This makes the "F" the key with which the user can pop up the popup menu file_menu when pressed together with the ALT-key. The same goes with entries within the popups, where the user, after a popup is active, only has to press the key to invoke the desired action. Selfexplaining, you should watch the usage of underlined characters very closely, because a key that is used twice either in the menubar or within the same popup makes the last inserted item the one that is activated and this makes the previously defined shortcuts useless.

Using the menu-accelerators is therefore very easy for the programmer - just select the key you want to be used and set an ampersand in front of it while inserting the entry. As the KDE applications get internationalized, translators take over the responsibility to place the keys in their translated version later. They should watch the same principles for placing the keys and shouldn't only translate one-to-one but test the application later if everything is accessible again by their keyboard shortcuts.

Tabulator and Button Accelerators

The keyboard accelerators with the ALT-key don't only work with the menus - they do the same over dialogs, tab-pages and on buttons. Therefore it should be used whereever possible, the principle is the same: on a dialog, you have to watch the used keys, on e.g. a QTabDialog you have to watch the keys for each page plus the used keys to activate the pages in the addTab() methods.

Within the user interface, buttons have an additional option - as mentionend, the keyboard input focus is forwarded in user interfaces with the TAB and SHIFT-TAB keys. When a button receives the focus, it gets a slight frame like other active elements, the user has to press the SPACE-key to execute the action connected to the button. Now, this can be changed by using setDefault(true) on one button or by setting setAutoDefault(true) on several buttons on the dialog. The difference is that if the User presses the ENTER-key, the default button will be pressed. If several buttons shall provide this behavoir, setAutoDefault() has to be used on those. If one of them receives the keyboard input focus, it will automatically become the default button.

KKeyDialog: keyboard accelerator configuration dialog KKeyChooser KAccel

5.5 Other Widgets

Control elements are used within visible areas of the application and can be combined together to create a dialog or view. Beyond the control elements that the Qt library provides, KDE offers:

KButton: active raise-lower button KButtonBox: manages buttons KColorButton: button displaying a color setting KIconLoaderButton: button displaying a selected Icon KCombo: similar to QComboBox KDatePicker: Date selection widget KIntegerLine: lineedit that only accepts integer values KLedLamp: LED lamp KLined: line edit KPanner: panner devider KNewPanner: panner devider managing two widgets KPopupMenu: popup menu with title KRestrictedLine: lineedit that only accepts certain input KSelector: value selector KSeparator: standard separator KSlider: slider widget KTabCtl: tabulator widget

Next Previous Table of Contents