![]() |
Home · Overviews · Examples |
This palette uses the indicated color as background and picks other colors suitably. (For this widget only the background and text colors will actually be used.) We then call setAutoFillBackground(true) to tell Qt fill the background automatically.
The QColor is specified as a RGB (red-green-blue) triplet, where each value is between 0 (dark) and 255 (bright). We could also have used a predefined color such as Qt::yellow instead of specifying an RGB value. Missing snippet: tutorials/tutorial/t8/cannonfield.cpp. Missing snippet: tutorials/tutorial/t8/cannonfield.cpp. This function sets the angle value. We have chosen a legal range of 5 to 70 and adjust the given number of degrees accordingly. We have chosen not to issue a warning if the new angle is out of range.
If the new angle equals the old one, we return immediately. It is important to only emit the angleChanged() signal when the angle really has changed.
Then we set the new angle value and repaint our widget. The QWidget::update() function clears the widget (usually filling it with its background color) and sends a paint event to the widget. This results in a call to the paint event function of the widget.
Finally, we emit the angleChanged() signal to tell the outside world that the angle has changed. The emit keyword is unique to Qt and not regular C++ syntax. In fact, it is a macro. Missing snippet: tutorials/tutorial/t8/cannonfield.cpp. Missing snippet: tutorials/tutorial/t8/cannonfield.cpp. This is our first attempt to write a paint event handler. The event argument contains information about the paint event, for example information about the region in the widget that must be updated. For the time being, we will be lazy and just paint everything.
Our code displays the angle value in the widget at a fixed position. To achieve this we create a QPainter operating on the CannonField widget and use it to paint a string representation of the currentAngle value. We'll come back to QPainter later; it can do a great many things.t8/main.cpp
t8/main.cpp
Missing snippet: tutorials/tutorial/t8/main.cpp.
We include the definition of our new class.
Missing snippet: tutorials/tutorial/t8/main.cpp.
The MyWidget class will include a single LCDRange and a CannonField.
Missing snippet: tutorials/tutorial/t8/main.cpp.
In the constructor, we create and set up the LCDRange widget.
Missing snippet: tutorials/tutorial/t8/main.cpp.
We set the LCDRange to accept angles from 5 to 70 degrees.
Missing snippet: tutorials/tutorial/t8/main.cpp.
We create our CannonField widget.
Missing snippet: tutorials/tutorial/t8/main.cpp.
Missing snippet: tutorials/tutorial/t8/main.cpp.
Here we connect the valueChanged() signal of the LCDRange to the setAngle() slot of the CannonField. This will update CannonField's angle value whenever the user operates the LCDRange. We also make the reverse connection so that changing the angle in the CannonField will update the LCDRange value. In our example we never change the angle of the CannonField directly; but by doing the last connect() we ensure that no future changes will disrupt the synchronization between those two values.
This illustrates the power of component programming and proper encapsulation.
Notice how important it is to emit the angleChanged() signal only when the angle actually changes. If both the LCDRange and the CannonField had omitted this check, the program would have entered an infinite loop upon the first change of one of the values. Missing snippet: tutorials/tutorial/t8/main.cpp. So far, we have used QVBoxLayout for geometry management. Now, however, we want to have a little more control over the layout, and we switch to the more powerful QGridLayout class. QGridLayout isn't a widget; it is a different class that can manage the children of any widget.
We don't need to specify any dimensions to the QGridLayout constructor. The QGridLayout will determine the number of rows and columns based on the grid cells we populate.
![]() | ![]() |
In this particular example, any stretch factor greater than 0 for column 1 would have the same effect. In more complex layouts, you can use the stretch factors to tell that a particular column or row should stretch twice as fast as another by assigning appropriate stretch factors. Missing snippet: tutorials/tutorial/t8/main.cpp. We set an initial angle value. Note that this will trigger the connection from LCDRange to CannonField. Missing snippet: tutorials/tutorial/t8/main.cpp. Our last action is to set angle to have keyboard focus so that keyboard input will go to the LCDRange widget by default.
LCDRange does not contain any keyPressEvent(), so that would seem not to be terribly useful. However, its constructor just got a new line:
Missing snippet: tutorials/tutorial/t8/lcdrange.cpp.
The LCDRange sets the slider to be its focus proxy. That means that when someone (the program or the user) wants to give the LCDRange keyboard focus, the slider should take care of it. QSlider has a decent keyboard interface, so with just one line of code we've given LCDRange one. When the slider is operated, the CannonField displays the new angle value. Upon resizing, CannonField is given as much space as possible. If you give the left-hand column a non-zero stretch factor, what happens when you resize the window? Leave out the QWidget::setFocus() call. Which behavior do you prefer? Try to change "Quit" to "&Quit". How does the button's look change? (Whether it does change or not depends on the platform.) What happens if you press Alt+Q while the program is running? Center the text in the CannonField.Running the Application
The keyboard now does something: The arrow keys, Home, End, PageUp, and PageDown all do something sensible. Exercises
Try to resize the window. What happens if you make it really narrow or really squat?
Copyright © 2008 Trolltech
Trademarks