Getting Started
Total Page:16
File Type:pdf, Size:1020Kb
• Hello Qt • Making Connections • Using the Reference 11 Documentation Getting Started This chapter shows how to combine basic C++ with the functionality provided by Qt to create a few small graphical user interface (GUI) applications. This chapter also introduces two key Qt ideas: “signals and slots” and layouts. In Chapter 2, we will go into more depth, and in Chapter 3, we will start building a realistic application. Hello Qt Here’s a very simple Qt program: 001 #include <qapplication.h> 002 #include <qlabel.h> 003 int main(int argc, char *argv[]) 004 { 005 QApplication app(argc, argv); 006 QLabel *label = new QLabel("Hello Qt!", 0); 007 app.setMainWidget(label); 008 label->show(); 009 return app.exec(); 010 } We will first study it line by line, then we will see how to compile and run it. Lines 1 and 2 include the definitions of the QApplication and QLabel classes. Line 5 creates a QApplication object to manage application-wide resources. The QApplication constructor requires argc and argv because Qt supports a few command-line arguments of its own. Line 6 creates a QLabel widget that displays “Hello Qt!”. In Qt terminology, a widget is a visual element in a user interface. Buttons, menus, scroll bars, and frames are all examples of widgets. Widgets can contain other widgets; for 3 4 1. Getting Started example, an application window is usually a widget that contains a QMenuBar,a QToolBar,aQStatusBar, and some other widgets. The 0 argument to the QLabel constructor (a null pointer) means that the widget is a window in its own right, not a widget inside another window. Line 7 makes the label the application’smain widget. When the user closes the main widget (by clicking X in the window’s title bar, for example), the program terminates. Without a main widget, the program would keep running in the background even after the user has closed the window. Line 8 makes the label visible. Widgets are always created hidden, so that we can customize them before showing them, thereby avoiding flicker. Line 9 passes control of the application on to Qt. At this point, the program enters a kind of stand-by mode, where it waits for user actions such as mouse clicks and key presses. User actions generate events (also called “messages”) to which the program can respond, usually by executing one or more functions. In this respect, GUI applications differ drastically from conventional batch programs, which typi- cally process input, produce results, and terminate without human interven- tion. Figure 1.1. Hello on Windows XP It is now time to test the program on your machine. First, you will need to in- stall Qt 3.2 (or a later Qt 3 release), a process that is explained in Appendix A. From now on, we will assume that you have a correctly installed copy of Qt 3.2 and that Qt’s bin directory is in your PATH environment variable. (On Windows, this is done automatically by the Qt installation program, so you don’t need to worry about it.) You will also need the Hello program’s source code in a file called hello.cpp in a directory called hello.You can type in hello.cpp yourself, or copy it from the CD provided with this book, where it is available as \examples\chap01\hello\ hello.cpp. From a command prompt, change directory to hello, then type qmake -project to create a platform-independent project file (hello.pro), then type qmake hello.pro to create a platform-specific makefile from the project file. Run make to build the program, and run the program by typing hello on Windows, ./hello on Unix, and open hello.app on Mac OS X. If you are using Microsoft Visual C++, Hello Qt 5 you will need to run nmake instead of make. Alternatively, you can create a Visual Studio project file from hello.pro by typing qmake -tp vc hello.pro and then build the program in Visual Studio. Figure 1.2. A label with basic HTML formatting Now let’s have some fun: We will brighten up the label by using some simple HTML-style formatting. This can be done by replacing the line QLabel *label = new QLabel("Hello Qt!", 0); with QLabel *label = new QLabel("<h2><i>Hello</i> " "<font color=red>Qt!</font></h2>", 0); and rebuilding the application. Making Connections The next example illustrates how to respond to user actions. The application consists of a button that the user can click to quit. The source code is very similar to Hello, except that we are using a QPushButton instead of a QLabel as our main widget, and we are connecting a user action (clicking a button) to a piece of code. This application’s source code is on the CD in the file \examples\chap01\quit\ quit.cpp. Figure 1.3. The Quit application 001 #include <qapplication.h> 002 #include <qpushbutton.h> 003 int main(int argc, char *argv[]) 004 { 005 QApplication app(argc, argv); 006 QPushButton *button = new QPushButton("Quit", 0); 6 1. Getting Started 007 QObject::connect(button, SIGNAL(clicked()), 008 &app, SLOT(quit())); 009 app.setMainWidget(button); 010 button->show(); 011 return app.exec(); 012 } Qt’s widgets emit signals to indicate that a user action or a change of state has occurred.# For instance, QPushButton emits a clicked() signal when the user clicks the button. A signal can be connected to a function (called a slot in that context), so that when the signal is emitted, the slot is automatically executed. In our example, we connect the button’s clicked() signal to the QApplication object’s quit() slot. The SIGNAL() and SLOT() macros are part of the syntax; they are explained in more detail in the next chapter. We will now build the application. We assume that you have created a direc- tory called quit containing quit.cpp. Run qmake in the quit directory to gener- ate the project file, then run it again to generate a makefile: qmake -project qmake quit.pro Now build the application, and run it. If you click Quit,orpress Space (which presses the button), the application will terminate. The next example demonstrates how to use signals and slots to synchronize two widgets. The application asks for the user’s age, which the user can enter by manipulating either a spin box or a slider. Figure 1.4. The Age application The application consists of three widgets: a QSpinBox,aQSlider, and a QHBox (horizontal layout box). The QHBox is the application’s main widget. The QSpinBox and the QSlider are rendered inside the QHBox; they are children of the QHBox. Caption QHBox QSpinBox QSlider Figure 1.5. The Age application’s widgets #Qt signals are unrelated to Unix signals. In this book, we are only concerned with Qt signals. Making Connections 7 001 #include <qapplication.h> 002 #include <qhbox.h> 003 #include <qslider.h> 004 #include <qspinbox.h> 005 int main(int argc, char *argv[]) 006 { 007 QApplication app(argc, argv); 008 QHBox *hbox = new QHBox(0); 009 hbox->setCaption("Enter Your Age"); 010 hbox->setMargin(6); 011 hbox->setSpacing(6); 012 QSpinBox *spinBox = new QSpinBox(hbox); 013 QSlider *slider = new QSlider(Qt::Horizontal, hbox); 014 spinBox->setRange(0, 130); 015 slider->setRange(0, 130); 016 QObject::connect(spinBox, SIGNAL(valueChanged(int)), 017 slider, SLOT(setValue(int))); 018 QObject::connect(slider, SIGNAL(valueChanged(int)), 019 spinBox, SLOT(setValue(int))); 020 spinBox->setValue(35); 021 app.setMainWidget(hbox); 022 hbox->show(); 023 return app.exec(); 024 } Lines 8 to 11 set up the QHBox.# We call setCaption() to set the text displayed in the window’s title bar. Then we put some space (6 pixels) around and in between the child widgets. Lines 12 and 13 create a QSpinBox and a QSlider with the QHBox as the parent. Even though we didn’t set the position or size of any widget explicitly, the QSpinBox and QSlider appear nicely laid out side by side inside the QHBox. This is because QHBox automatically assigns reasonable positions and sizes to its children based on their needs. Qt provides many classes like QHBox to free us from the chore of hard-coding screen positions in our applications. Lines 14 and 15 set the valid range for the spin box and the slider. (We can safely assume that the user is at most 130 years old.) The two connect() calls shown in lines 16 to 19 ensure that the spin box and the slider are synchro- nized so that they always show the same value. Whenever the value of one widget changes, its valueChanged(int) signal is emitted, and the setValue(int) slot of the other widget is called with the new value. Line 20 sets the spin box value to 35. When this happens, the QSpinBox emits the valueChanged(int) signal with an int argument of 35. This argument is #If you get a compiler error on the QHBox constructor, it means that you are using an older version of Qt. Make sure that you are using Qt 3.2.0 or a later Qt 3 release. 8 1. Getting Started passed to the QSlider’s setValue(int) slot, which sets the slider value to 35.The slider then emits the valueChanged(int) signal, because its own value changed, triggering the spin box’s setValue(int) slot. But at this point, setValue(int) doesn’t emit any signal, since the spin box value is already 35. This prevents infinite recursion. Figure 1.6 summarizes the situation. 1. 00 ¤ S SSSSSSSSSSSSS setValue(35) 2.