10.3 A first example
Our job is to define classes from which we can make objects that we want to see on the screen. For example, we might want to draw a graph as a series of connected lines. Here is a small program presenting a very simple version of that:
#include "Simple_window.h" // get access to our window library #include "Graph.h" // get access to our graphics library facilities int main() { using namespace Graph_lib; // our graphics facilities are in Graph_lib Application app; // start a Graphics/GUI application Point tl {900,500}; // to become top left corner of window Simple_window win {tl,600,400,"Canvas"}; // make a simple window Polygon poly; // make a shape (a polygon) poly.add(Point{300,200}); // add a point poly.add(Point{350,100}); // add another point poly.add(Point{400,200}); // add a third point poly.set_color(Color::red); // adjust properties of poly win.attach (poly); // connect poly to the window win.wait_for_button(); // give control to the display engine }
When we run this program, the screen looks something like this:
AA
In the background of our window, we see a laptop screen (cleaned up for the occasion). For people who are curious about irrelevant details, we can tell you that my background is a famous painting by the Danish painter Peder Severin Krøyer. The ladies are Anna Ancher and Marie Krøyer, both well-known painters. If you look carefully, you’ll notice that we have the Microsoft C++ compiler running, but we could just as well have used some other compiler (such as GCC or Clang). Let’s go through the program line by line to see what was done.
First we #include our graphics interface library:
#include "Simple_window.h" // get access to our window library #include "Graph.h" // get access to our graphics library facilities
Why don’t we use a module Graph_lib (§7.7.1)? One reason is at the time of writing not all implementations are up to using modules for this relatively complex task. For example, the system we use to implement our graphics library, Qt, exports its facilities using header files (§7.7.2). Another reason is that there is so much C++ code “out there” using header files (§7.7.2) that we need to show a realistic example somewhere.
Then, in main(), we start by telling the compiler that our graphics facilities are to be found in Graph_lib:
using namespace Graph_lib; // our graphics facilities are in Graph_lib
Then we start our display engine (§10.2):
Application app; // start a Graphics/GUI application
Then, we define a point that we will use as the top left corner of our window:
Point tl {900,500}; // to become top left corner of window
Next, we create a window on the screen:
Simple_window win {tl,600,400,"Canvas"}; // make a simple window
We use a class called Simple_window to represent a window in our Graph_lib interface library. The name of this particular Simple_window is win; that is, win is a variable of class Simple_window. The initializer list for win starts with the point to be used as the top left corner, tl, followed by 600 and 400. Those are the width and height, respectively, of the window, as displayed on the screen, measured in pixels. We’ll explain in more detail later, but the main point here is that we specify a rectangle by giving its width and height. The string "Canvas" is used to label the window. If you look, you can see the word Canvas in the top left corner of the window’s frame.
Next, we put an object in the window:
Polygon poly; // make a shape (a polygon) poly.add(Point{300,200}); // add a point poly.add(Point{350,100}); // add another point poly.add(Point{400,200}); // add a third point
We define a polygon, poly, and then add points to it. In our graphics library, a Polygon starts empty and we can add as many points to it as we like. Since we added three points, we get a triangle. A point is simply a pair of values giving the x and y (horizontal and vertical) coordinates within a window.
Just to show off, we then color the lines of our polygon red:
poly.set_color(Color::red); // adjust properties of poly
Finally, we attach poly to our window, win:
win.attach(poly); // connect poly to the window
If the program wasn’t so fast, you would notice that so far nothing had happened to the screen: nothing at all. We created a window (an object of class Simple_window, to be precise), created a polygon (called poly), painted that polygon red (Color::red), and attached it to the window (called win), but we have not yet asked for that window to be displayed on the screen. That’s done by the final line of the program:
win.wait_for_button(); // give control to the display engine
To get a GUI system to display objects on the screen, you have to give control to “the system.” Our wait_for_button() does that, and it also waits for you to “press” (“click”) the “Next” button in the top right corner of our Simple_window before proceeding. This gives you a chance to look at the window before the program finishes and the window disappears. When you press the button, the program terminates, closing the window.
For the rest of the Graphics-and-GUI chapters, we eliminate the distractions around our window and just show the window itself:
You’ll notice that we “cheated” a bit. Where did that button labeled “Next” come from? We built it into our Simple_window class. In Chapter 14, we’ll move from Simple_window to “plain” Window, which has no potentially spurious facilities built in, and show how we can write our own code to control interaction with a window.
For the next three chapters, we’ll simply use that “Next” button to move from one “display” to the next when we want to display information in stages (“frame by frame”).
The pictures in this and the following chapters were produced on a Microsoft Windows system, so you get the usual three buttons on the top right “for free.” This can be useful: if your program gets in a real mess (as it surely will sometimes during debugging), you can kill it by hitting the X button. When you run your program on another system, a different frame will be added to fit that system’s conventions. Our only contribution to the frame is the label (here, Canvas).