Right now, watching running noise is much more interesting than my work …
Friday, May 15, 2009
Wednesday, May 13, 2009
Book Fragment 84
Advanced buttons 1
In the previous chapter we created basic buttons that can be used to start and stop processes. However, we would like buttons to be much more interesting than just little squares. It would give us a much friendlier user interface if we could put some text or images on the buttons so that people know what the buttons are for.
Adding a label
Adding the following few lines of code to the program developed in the previous chapter will add the label “Bulb” to the button.
01 // little square
02 fill(button_top_colour);
03 rect(button_top_left_x + 3, button_top_left_y + 3, button_width - 6, button_width – 6);
04
05 // Place text on button
06 textMode(SCREEN);
07 textAlign(CENTER, CENTER);
08 font = loadFont("Verdana-10.vlw");
09 textFont(font);
10 fill(color(0,0,05));
11 text("Bulb", button_top_left_x + (button_width/2),
12 button_top_left_y + (button_width/2));
Before this code will work it is necessary to generate the font that will be used for the text. Processing can do this for you. On the Processing menu, click Tools and then Create Font as in the illustration below:
Illustration 1: Select Create Font on the menu
Select the font you wish to use and the size. For our code samples we selected Verdana with a size of 10 pixels:
Illustration 2: Select the font and enter a font size.
When you click OK, Processing will create a sub-directory called data in the directory where your program is stored. In the data directory it will create the font file. By default the file is named after the font and its size. So if you, like us, selected Verdana with a size of 10, then the file name will be Verdana-10.vlw.
Drawing a rectangular button
The code above still draws a square button. We often require rectangular buttons, especially if we are going to place text on them. Illustration 3 shows a button and the illustration 4 shows the shapes used to create the button:
Illustration 3: A rectangular button
Illustration 4: The shapes used to create a rectangular button
The listing below shows how we draw and colour these shapes, using the method rect for the rectangle and the method quad for the polygons that make the bevel. The mouse event handlers are in place to switch the light bulb on and also notice that the label on the button will change. The bold lines show the code required to generate and place the label on the button:
001 int button_top_left_x = 10;
002 int button_top_left_y = 10;
003 int button_width = 150;
004 int button_height = 40;
005 int bevel_size = 3;
006 int bevel_up_colour = color(0xD0, 0xD0, 0xD0);
007 int bevel_down_colour = color(0x88, 0x88, 0x88);
008 int bevel_colour_left = bevel_up_colour;
009 int bevel_colour_right = bevel_down_colour;
010 boolean bulb_on = false;
011 int button_up_colour = color(0xD0, 0xD0, 0xD0); // grey
012 int button_over_colour = color(0xB0, 0xB0, 0xB0);
013 int button_down_colour = color(0xA0, 0xA0, 0xA0); // white
014 int button_colour_top = button_up_colour;
015 String button_label = "Switch Bulb On";
016 // Declare the variable that will hold the font
017 PFont font;
019 void setup() {
020 size(300,300);
021 // Load the font to be used for the label
022 font = loadFont("Verdana-10.vlw");
023 }
025 void draw() {
026 rectMode(CORNER);
027 // top and left bevels
028 fill(bevel_colour_left);
029 quad(button_top_left_x,
030 button_top_left_y,
031 button_top_left_x + button_width + (bevel_size * 2),
032 button_top_left_y,
033 button_top_left_x + button_width + bevel_size,
034 button_top_left_y + bevel_size,
035 button_top_left_x + bevel_size,
036 button_top_left_y + bevel_size);
038 quad(button_top_left_x,
039 button_top_left_y,
040 button_top_left_x + bevel_size,
041 button_top_left_y + bevel_size,
042 button_top_left_x + bevel_size,
043 button_top_left_y + button_height + bevel_size,
044 button_top_left_x,
045 button_top_left_y + button_height + (bevel_size * 2));
047 // bottom and right bevels
048 fill(bevel_colour_right);
049 quad(button_top_left_x,
050 button_top_left_y + button_height + (bevel_size * 2),
051 button_top_left_x + button_width + (bevel_size * 2),
052 button_top_left_y + button_height + (bevel_size * 2),
053 button_top_left_x + button_width + bevel_size,
054 button_top_left_y + button_height + bevel_size,
055 button_top_left_x + bevel_size,
056 button_top_left_y + button_height + bevel_size);
058 quad(button_top_left_x + button_width + (bevel_size * 2),
059 button_top_left_y,
060 button_top_left_x + button_width + (bevel_size * 2),
061 button_top_left_y + button_height + (bevel_size * 2),
062 button_top_left_x + button_width + bevel_size,
063 button_top_left_y + button_height + bevel_size,
064 button_top_left_x + button_width + bevel_size,
065 button_top_left_y + bevel_size);
067 // top of button
068 fill(button_colour_top);
069 rect(button_top_left_x + bevel_size,
070 button_top_left_y + bevel_size,
071 button_width,
072 button_height);
073
074 // Place text on button
075 textMode(SCREEN);
076 textAlign(CENTER, TOP);
077 textFont(font);
078 fill(color(0x00, 0x00, 0x00));
079 text(button_label, (button_top_left_x + button_width + (bevel_size * 2)) / 2,
080 (button_top_left_y + button_height + (bevel_size * 2)) / 2);
081
082 // draw bulb
083 if (bulb_on) {
084 bulb_on();
085 } else {
086 bulb_off();
087 }
088 }
090 void bulb_on() {
091 bulb_on = true;
092 // Change the text to be displayed on the button
093 button_label = "Switch Bulb Off";
094 // draw the light bulb base
095 fill(0x40, 0x40, 0x40);
096 rectMode(CENTER);
097 rect(100,100,15,20);
098 fill(0xFF, 0xCC, 0x33); // an orange fill when the bulb is on
099 ellipseMode(CENTER);
100 ellipse(100,80,30,30);
101 }
103 void bulb_off() {
104 bulb_on = false;
105 // Change the text to be displayed on the button
106 button_label = "Switch Bulb On";
107 // draw the light bulb base
108 fill(0x40, 0x40, 0x40);
109 rectMode(CENTER);
110 rect(100,100,15,20);
111 fill(0xFF, 0xFf, 0xFF); // a white fill when the bulb is off
112 ellipseMode(CENTER);
113 ellipse(100,80,30,30);
114 }
116 void mousePressed() {
117 if (mouseX >= button_top_left_x &&
118 mouseX <= (button_top_left_x + button_width + (bevel_size * 2)) &&
119 mouseY >= button_top_left_y &&
120 mouseY <= (button_top_left_y + button_height + (bevel_size * 2))) {
121 button_colour_top = button_down_colour;
122 bevel_colour_left = bevel_down_colour;
123 bevel_colour_right = bevel_up_colour;
124 } else {
125 button_colour_top = button_up_colour;
126 bevel_colour_left = bevel_up_colour;
127 bevel_colour_right = bevel_down_colour;
128 }
129 }
131 void mouseMoved() {
132 if (mouseX >= button_top_left_x &&
133 mouseX <= (button_top_left_x + button_width + (bevel_size * 2)) &&
134 mouseY >= button_top_left_y &&
135 mouseY <= (button_top_left_y + button_height + (bevel_size * 2))) {
136 button_colour_top = button_over_colour;
137 } else {
138 button_colour_top = button_up_colour;
139 }
140 }
142 void mouseReleased() {
143 if (mouseX >= button_top_left_x &&
144 mouseX <= button_top_left_x + button_width + (bevel_size * 2) &&
145 mouseY >= button_top_left_y &&
146 mouseY <= (button_top_left_y + button_height + (bevel_size * 2))) {
147 if (bulb_on) bulb_on = false; else bulb_on = true;
148 // When the mouse button is released, switch the button bevel colours
149 // so that the button displays in its upper position
150 button_colour_top = button_over_colour;
151 bevel_colour_left = bevel_up_colour;
152 bevel_colour_right = bevel_down_colour;
153 } else {
154 button_colour_top = button_up_colour;
155 bevel_colour_left = bevel_up_colour;
156 bevel_colour_right = bevel_down_colour;
157 }
158 }
Adding an icon
Although text on buttons could be a requirement in some cases, it does take up a great deal of space. So often it is advantageous to have a fairly small button with only an image on it. Modern software often give the user the choice to use buttons with text only, text and images or images only.
To add an icon to the button we can move the text in the button to the right and add an icon to the left as is shown in illustrations 5 and 6.
Illustration 5: Button to switch bulb on
Illustration 6: Button to switch bulb off
All we need to do to achieve the above is add the following snippet of code to draw():
01 // draw icon on button
02 fill(0x00, 0x00, 0x00);
03 rect(button_top_left_x + bevel_size + 10,
04 button_top_left_y + bevel_size + 20,
05 10, 10);
06 if (bulb_on) {
07 fill(0xFF, 0xFF, 0xFF);
08 } else {
09 fill(0xFF, 0xCC, 0x33);
10 }
11 ellipseMode(CENTER);
12 ellipse(button_top_left_x + bevel_size + 15,
13 button_top_left_y + bevel_size + 15,
14 20, 20);
Listing 1: Drawing an icon on the button
Drawing icons in this way could become tedious and complex, especially if we want good looking images. An easier alternative would be to use a pre-prepared image for the icon.
Processing can work with four image types, i.e..gif, .jpg, .tga, .png. If you browse the web you will find thousands of free buttons or you can create your own. We found these two buttons on the web1:
Using these images we can now create a slightly better looking button than before:
Firstly we need to declare a variable to hold the images. This is done in the section before setup():
1 PImage img_stop, img_play;
3 In setup(), we then load the images into the variables:
4 img_stop = loadImage("stop.png");
5 img_play = loadImage("play.png");
Replace the code in listing 1 with the code to load the images:
1 // draw icon on button
2 imageMode(CORNERS);
3 if (bulb_on) {
4 image(img_stop, button_top_left_x + bevel_size + 5,
5 button_top_left_y + bevel_size + 5);
6 } else {
7 image(img_play, button_top_left_x + bevel_size + 5,
8 button_top_left_y + bevel_size + 5);
9 }
Using images for buttons
We could, of course, use only images for buttons. There is nothing new to doing this. Everything you need to know to do this has already been covered. The only changes we need to make to the code is to remove all the instructions which are used to draw the button. The button dimensions need to be adjusted to conform to that of the images we are using. The resulting code will actually be a little simpler than before. To make things slightly more interesting we will add a tint to the image when the mouse is hovering over the button.
01 int button_top_left_x = 10;
02 int button_top_left_y = 10;
03 int button_width;
04 int button_height;
05 boolean bulb_on = false;
06 PImage img_stop, img_play;
07 int gray = 255;
08 int alpha = 255;
10 void setup() {
11 size(300,300);
12 background(0xFF, 0xFF, 0xFF);
13 img_stop = loadImage("stop.png");
14 img_play = loadImage("play.png");
15 // Make sure both images have the same width and height when creating them
16 button_width = img_stop.width;
17 button_height = img_stop.height;
18 }
20 void draw() {
21 // draw icon on button
22 imageMode(CORNERS);
23 tint(gray, alpha);
24 if (bulb_on) {
25 image(img_stop, button_top_left_x + 5, button_top_left_y + 5);
26 } else {
27 image(img_play, button_top_left_x + 5 ,button_top_left_y + 5);
28 }
29
30 // draw bulb
31 if (bulb_on) {
32 bulb_on();
33 } else {
34 bulb_off();
35 }
36 }
38 void bulb_on() {
39 bulb_on = true;
40 // draw the light bulb base
41 fill(0x40, 0x40, 0x40);
42 rectMode(CENTER);
43 rect(100,100,15,20);
44 fill(0xFF, 0xCC, 0x33); // an orange fill when the bulb is on
45 ellipseMode(CENTER);
46 ellipse(100,80,30,30);
47 }
49 void bulb_off() {
50 bulb_on = false;
51 // draw the light bulb base
52 fill(0x40, 0x40, 0x40);
53 rectMode(CENTER);
54 rect(100,100,15,20);
55 fill(0xFF, 0xFf, 0xFF); // a white fill when the bulb is off
56 ellipseMode(CENTER);
57 ellipse(100,80,30,30);
58 }
60 void mouseMoved() {
61 if (mouseX >= button_top_left_x &&
62 mouseX <= (button_top_left_x + button_width) &&
63 mouseY >= button_top_left_y &&
64 mouseY <= (button_top_left_y + button_height)) {
65 // Give the button a tint when the mouse is hovering over it
66 gray = color(0xFD, 0xD0, 0x17);
67 alpha =100;
68 } else {
69 gray = 255;
70 alpha = 255;
71 }
72 }
74 void mouseReleased() {
75 if (mouseX >= button_top_left_x &&
76 mouseX <= (button_top_left_x + button_width) &&
77 mouseY >= button_top_left_y &&
78 mouseY <= (button_top_left_y + button_height)) {
79 if (bulb_on) bulb_on = false; else bulb_on = true;
80 }
81 }
Illustration 7: Image button to switch light bulb on
Illustration 8: Image button with orange tint when mouse hovering
Illustration 9: Image button to switch light bulb off
Illustration 10: Image button with orange tint when mouse hovering
Adding tool tips
Tool tips are informative messages displayed when the mouse hovers over an item. These are usually used when additional information about the item, over which the mouse is hovering, needs to be conveyed to the user. The illustrations below show a tool tip being displayed when the mouse is hovering over the buttons:
To add the tool tips to our previous program, add the following pieces of code. Firstly declare a string variable before setup() to hold the text for the tool tip:
1 String tooltip = "";
2 PFont font;
Remember that you need to generate a font if you haven't done so yet. Then add these lines to the setup() method:
1 font = loadFont("Verdana-10.vlw");
2 textFont(font);
3 textMode(SCREEN);
Add the following line as the first line in draw(). This clears the tool tip when the mouse is moved off the button area:
code> 1 background(0x8B, 0xB3, 0x81);Add the next chunk of code to the end of draw(). If the tooltip string is empty then the code does nothing. If a tool tip is set then a rectangle containing the tool tip is drawn below the button.
01 // Tooltip
02 if (tooltip.equals("")) {
03 //
04 } else {
05 fill(0xFF, 0xF8, 0xC6);
06 rectMode(CORNER);
07 rect(button_top_left_x + 3, button_top_left_y + button_height + 5, 100, 10);
08 textAlign(LEFT, TOP);
09 fill(0x00, 0x00, 0x00);
10 text(tooltip, button_top_left_x + 5, button_top_left_y + button_height + 6);
11 }
Amend the mouse events as follows. The added code is displayed in bold. If the bulb is switched on the tool tip is set to “Switch bulb off” but if the bulb is switched off the tool tip is set to “Switch bulb on”.
01 void mouseMoved() {
02 if (mouseX >= button_top_left_x &&
03 mouseX <= (button_top_left_x + button_width) &&
04 mouseY >= button_top_left_y &&
05 mouseY <= (button_top_left_y + button_height)) {
06 gray = color(0xFD, 0xD0, 0x17);
07 alpha =100;
08 if (bulb_on) {
09 tooltip = "Switch bulb off";
10 } else {
11 tooltip = "Switch bulb on";
12 }
13 } else {
14 tooltip = "";
15 gray = 255;
16 alpha = 255;
17 }
18 }
20 void mouseReleased() {
21 if (mouseX >= button_top_left_x &&
22 mouseX <= (button_top_left_x + button_width) &&
23 mouseY >= button_top_left_y &&
24 mouseY <= (button_top_left_y + button_height)) {
25 // Give the button a tint when the mouse is hovering over it
26 if (bulb_on) bulb_on = false; else bulb_on = true;
27 if (bulb_on) {
28 tooltip = "Switch bulb off";
29 } else {
30 tooltip = "Switch bulb on";
31 }
32 } else {
33
34 }
Using combinations of the techniques we have covered in chapter 83 and 84 you should now be able to create very attractive user interfaces with buttons. You will find though, that the code can once again get very complex if you have to draw each button individually. So at this point it would make sense to start using objects which are re-usable. The next chapter will cover this in more detail.
1http://itweek.deviantart.com/art/Knob-Buttons-Toolbar-icons-73463960