Coding GUIs in Linux

By : |November 30, 2006 0

By: Ankit Khare

GUI programming for Linux has traditionally been a difficult task. Trolltech has changed all that by introducing Qt, a platform-independent Object-oriented library, that allows programmers to create GUIs easily. The Qt library allows components of the GUI to interact with each other elegantly by using slots and signals. Qt is in its third avatar, meaning v3.0, and is now a mature library. It has even branched off as Qtopia, for development of GUI in embedded systems. The Qt development kit is available commercially for nearly every platform, including the Mac. For Linux it’s under L’GPL. 

We’ll talk about how to use Qt by building a basic graphical frontend for mpg123, a popular command line MP3 player for Linux, using C++. Extensions are also available for using the Qt library in Perl or Python programs. To get started, install Qt development libraries from your Linux installation CD. It’s not installed by default. You’ll find them in PCQ Linux 7.1 CD2 in the RPMs folder with file names qt-designer and qt-devel.

Hello Qt 
To begin on any programming odyssey, a Hello world program is necessary. So, let’s see how to write one in Qt. Simply put the following script in any text editor and save it in a separate directory. 

#include <qapplication.h>
#include <qpushbutton.h>
int main( int argc, char **argv )
{
QApplication a( argc, argv );
QPushButton hello(“Hello world!”, 0 );
hello.resize( 100, 30 );
a.setMainWidget( &hello );
hello.show();
return a.exec();
}

Now for compiling the code we have to take care of the following three steps. 

  • Create the project file using the qmake –project 
  • Type qmake at the command prompt to create the makefile 
  • Compile the source code with the make command. If all your libraries are installed correctly, an executable file of the same name as the directory will be created. Execute to see your very first Qt program work. 

In the program above, the qapplication header file has the definition of QApplication class, which is the single most important class in any Qt application. All Qt applications are instances of this class. The main function parameters (argc & agrv) are passed to the constructors when creating an object of this class. QPushButton is a simple push button, which is instantiated as hello in this example. Two arguments are passed, first the label or the text to be written on the button and the other a number identifying the parent window (0 in this case). hello.resize(100,30) is self explanatory. QApplication object allows us to set a main widget. If the main widget is killed somehow, the application dies. This is done through a.setMainWiget(&hello).

hello.show() is akin to the VB’s visible property. It does nothing but make the component visible. exec() executes in a loop and passes all events to the respective components of the GUI. This executes until the application closes or is explicitly killed.

[image_library_tag 209/13209, height=”174″ hspace=”10″ width=”250″ vspace=”10″ border=”0″ alt=”” ,default]

You use slots and signals to add functionality to the interface

Next step
Now that we have got our feet wet, its time to create a more complex GUI, which is a very basic frontend for mpg123. We have given the associated source code for this on our CD in the source code section. In this article, we’ll explain the main elements of the code. 

For building the GUI we will use Qt designer for designing the frontend. Fire up the designer from the command line by giving the designer command or use the link in the Start Menu. Go to File menu and choose new, which will open a dialog box asking for file type to be created. Choose dialog and press OK. You will now see a VB style form on which you can add various components (widgets), just as you do in VB. For the present context we will restrict ourselves to three types of widgets: push button, pixmap and a dial. Now, create a simple form by dragging and dropping the widgets.

This will serve as the GUI for your MP3 player. Save the form you’ve created, and the Qt designer will output it as an XML based .ui (user interface) file. We’ve given the .ui file for it on the CD. You can preview this interface using the preview option from the menu. The pixmap label is used to show the image. Once the interface is done, we have to add functionality to it. This is where slots and signals come into play. Qt component widgets emit signals when events occur. For example, a button will emit a ‘clicked’ signal when it is clicked. The programmer can choose to connect to a signal by creating a function (called a slot) and calling the connect () function to relate the signal to the slot. This can also be done directly in Qt designer (see picture on the right). 

To create the slots, we use the Edit->slots option. Add five slots fileplay(), filestop(), bye(), volume(int) and filechange() for the five basic operations in the MP3 player, namely play, stop, quit, change volume and change song. For connecting slots and signals, the Qt designer provides a very intuitive method. Press F3 and select the widget emitting the signal and drag the mouse to the empty space in the form. A dialog window will pop and associate the required signal to one of the slots. In this fashion associate clicked signal of each of the push buttons to the four slots (file). Associate the valueChanged(int) signal of the dial to the volume(int) slot. The valueChanged signal is emitted whenever the dial is moved. The label on the buttons and the caption on the windows can be changed from the property editor accessible from window->view->property editor. After doing all this cosmetic work it’s time to write the actual code. The user interface file is used by uic (user interface compiler) to generate the corresponding c++ code. This is taken care of in the makefile generated by qmake in the second step of compiling the Qt code. So, any modifications to this c++ code will get erased, therefore, more functionality is added by sub classing. Let’s see how this is done. 

We created slots for the main form, hence we would be sub classing the same. We named the Main Form as MP3. We now create a file mp3_player.h having the definition of the new sub class mp3_player. The c++ code for this is as follows. 

#ifndef MP3_PLAYER_H
#define MP3_PLAYER_H
#include “mp3.h”
class mp3_player : public MP3
{
Q_OBJECT
public :
mp3_player( QWidget* parent = 0, const char* name = 0, bool modal = FALSE, WFlags f = 0 ) : MP3( parent, name, modal, f ) {}
public slots :
virtual void fileplay() ;
virtual void filechange();
virtual void filestop();
virtual void volume(int a);
virtual void bye();
} ;
#endif

Q_OBJECT is used by moc, Meta Object Compiler during the compilation process. “public slots” are now added using the virtual specifier.

Now let’s create the mp3_player.cpp file, which will contain the functional code. This will contain the code for all the slots. Here, we’ll explain two of them, namely filechange() and fileplay(). The remaining slots are similar to the filechange() function.

___________________________________________________________________________________________________________

void mp3_player::filechange() {
s = QFileDialog::getOpenFileName(
“/” , “Audio files (*.mp3)” ,
this ,
“open mp3 file “
“choose your mp3” );
}

In the above code, s is a QString type global variable in which the filename is stored. This is done by calling the static method getOpenFileName() of the QFileDialog class. The code for fileplay() will be as follows. 

void mp3_player::fileplay() {
QMessageBox::information ( this , “Now Playing “ , s , QMessageBox::Ok ) ;
QString play(“mpg123 “);
QString file=play+”’”+s+”’”+”&” ;
system(file.latin1());
}

In this the variable ‘s’ from the filechange() function is used to create a command line argument for mpg123 and finally mpg123 is executed using the system() call. 

The working of another slot, namely the volume(int a) is similar to the fileplay() function, where the dial position ‘a’ is used to generate arguments for aumix (audio mixer for Linux) used for controlling the volume. 

After all this, we have to write the main.cpp file, similar to the hello world code, where the main widget is an instance of the mp3_player class. Compile the code as we explained above. There is one quirk in the program. If the player is killed explicitly (using a kill command or from the X button), the song doesn’t stop playing. This is because the mpg123 is run as a separate program in the background and not as a child process. We’ll leave the solution to this to you as an exercise.

Source: PCQuest

No Comments so fars

Jump into a conversation

No Comments Yet!

You can be the one to start a conversation.