CSCE 121 Chapter 16
Jump to navigation
Jump to search
« previous | Wednesday, October 20, 2010 | next »
More intuitive GUI
- window with components
- Titles / Text
- Fields / Dialogs
- Buttons
- mouse
GUI is based on two techniques:
- Object-oriented programming
- Events (like mouse click)
How do we do this?
- define custom window not Simple_window
- define buttons and boxes
- listen for actions
- storing entered text
- creating lines, etc.
Answer:
struct Lines_window : Window {
Lines_window(Point xy, int width, int height, const string& title);
Open_polyline lines;
private:
// buttons
Button next_button;
Button quit_button;
// i/o boxes
In_box next_x;
In_box next_y;
Out_box xy_out;
void next(); // what to do when next_button is pushed
void quit(); // what to do when quit_button is pushed
static void cb_next(Address, Address window); // callback for next_button
static void cb_quit(Address, Address window); // callback for quit_button
};
Lines_window::Lines_window(Point xy, int w, int h, const string& title) : Window(xy, w, h, title),
next_button(Point(x_max()-150,0), 70, 20, "Next point", cb_next), // note callback cb_next
quit_button(Point(x_max()-70,0), 70, 20, "Quit", cb_quit), // note callback cb_quit
next_x(Point(x_max()-310,0), 50, 20, "next x:"),
next_y(Point(x_max()-210,0), 50, 20, "next y:"),
xy_out(Point(100,0), 100, 20, "current (x,y):")
{
attach(next_button);
attach(quit_button);
attach(next_x);
attach(next_y);
attach(xy_out);
attach(lines);
}
All of the elements on the window are Widgets or "controls"
Callbacks
Connecting functions to widgets is messy in most GUIs:
- System doesn't "know about" C++
- callback maps system conventions to C++:
void Lines_window::cb_quit(Address, Address pw) {
// First argument is not used, second argument is the current window
// Call Lines_window::quit() for the window located at address pw
reference_to<Lines_window>(pw).quit(); // map address into reference to type of object at that address (explained later)
}
void Lines_window::quit() {
hide();
}
void Lines_window::next() {
int x = next_x.get_int();
int y = next_y.get_int();
lines.add(Point(x,y));
// update current position box:
stringstream ss;
ss << '(' << x << ',' << y << ')';
xy_out.put(ss.str());
redraw(); // redraw the screen
}
Summary
We know about:
- Windows
- Buttons
- Textual Input/Output boxes
- Graphical output
We still don't know about:
- mouse tracking
- menus
- etc
Fancier Example
Lines_window.h
#include "Graph.h"
#include "GUI.h"
#include "Window.h"
#include <iostream>
#include <sstream>
struct Lines_window : Window {
Lines_window(Point xy, int w, int h, const string& title);
private:
Open_polyline lines;
Button next_button;
Button quit_button;
In_box next_x;
In_box next_y;
Out_box xy_out;
Menu color_menu;
Button menu_button;
void change(Color c) {
lines.set_color(c);
}
void hide_menu() {
// hide color menu and show button to display menu
color_menu.hide();
menu_button.show();
}
// actions invoked by callbacks
void menu_pressed() {
// hide menu button and show color menu
menu_button.hide();
color_menu.show();
}
void red_pressed() {
change(Color::red);
hide_menu();
}
void blue_pressed() {
change(Color::blue);
hide_menu();
}
void black_pressed() {
change(Color::black);
hide_menu();
}
void next() { /* ... */ }
void quit() { /* ... */ }
// callbacks
static void cb_red(Address, Address pw) {
reference_to<Lines_window>(pw).red_pressed();
}
static void cb_blue(Address, Address pw) {
reference_to<Lines_window>(pw).blue_pressed();
}
static void cb_black(Address, Address pw) {
reference_to<Lines_window>(pw).black_pressed();
}
static void cb_next(Address, Address pw) {
reference_to<Lines_window>(pw).next();
}
static void cb_quit(Address, Address pw) {
reference_to<Lines_window>(pw).quit();
}
};
Lines_window.cpp
#include "Lines_window.h"
Lines_window::Lines_window(Point xy, int w, int h, const string& title) : // initializer
Window(xy, w, h, title),
next_button(Point(x_max()-150, 0), 70, 20, "Next point", cb_next),
quit_button(Point(x-max()-70, 0), 70, 20, "Quit", cb_quit),
next_x(Point(x_max()-310, 0), 50, 20, "next x:"),
next_y(Point(x_max()-210, 0), 50, 20, "next y:"),
xy_out(Point(100, 0), 100, 20, "current (x,y):"),
color_menu(Point(x_max()-70, 30), 70, 20, Menu::vertical, "color"),
menu_button(Point(x_max()-70, 30), 70, 20, cb_menu)
{
attach(next_button);
attach(quit_button);
attach(next_x);
attach(next_y);
attach(xy_out);
xy_out.put("no point");
color_menu.attach(new Button(Point(0,0), 0, 0, "red", cb_red)); // use 'new' to put button in heap; accessible after constructor is out of scope
color_menu.attach(new Button(Point(0,0), 0, 0, "blue", cb_blue));
color_menu.attach(new Button(Point(0,0), 0, 0, "black", cb_black));
attach(color_menu);
color_menu.hide();
attach(menu_button);
attach(lines);
}
void Lines_window::next() {
int x = next_x.get_int();
int y = next_y.get_int();
lines.add(Point(x,y));
stringstream ss;
ss << '(' << x << ',' << y << ')';
xy.put(ss.str());
redraw(); // inherited from Window; refreshes the screen
}
main.cpp <syntaxhighlight lang="cpp">
- include "Lines_window.h"
using namespace Graph_lib; using namespace std; int main() {
Lines_window(Point(100,100), 600, 400, "lines"); return gui_main(); // inherited in Window