]> Creatis software - creaContours.git/blob - lib/doxygen/bouml/buttons/new_button.html
*** empty log message ***
[creaContours.git] / lib / doxygen / bouml / buttons / new_button.html
1 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
2 <html><head>
3 <meta content="text/html; charset=ISO-8859-1" http-equiv="content-type"><title>Adding a new Button</title>
4
5 <style type="text/css">
6 .titles {
7 font-family: Geneva, Arial, Helvetica, sans-serif;
8 color: #000000;
9 font-size: large;
10 font-weight: bold;
11 }
12 .text {
13 font-family: Geneva, Arial, Helvetica, sans-serif;
14 font-size: small;
15 font-weight: normal;
16 }
17 a.el {
18 font-weight:bold;
19 text-decoration:none;
20 }
21 a {
22 color:#1A41A8;
23 }
24 .subtitles {
25 font-family: Geneva, Arial, Helvetica, sans-serif;
26 font-size: 90%;
27 font-weight: bold;
28 text-decoration: underline;
29 }
30 .listDiagrams {
31 font-family: Geneva, Arial, Helvetica, sans-serif;
32 margin-left: 25px;
33 font-size: small;
34 font-weight: bold;
35 }
36 .paragraph {
37 margin-left: 40px;
38 font-family: Geneva, Arial, Helvetica, sans-serif;
39 font-size: small;
40 }
41 .style1 {
42 text-decoration: underline;
43 font-weight: bold;
44 }
45 .style3 {
46 font-family: Geneva, Arial, Helvetica, sans-serif;
47 font-size: 21px;
48 text-decoration: underline;
49 text-align: justify;
50 }
51 .style4 {
52 font-family: Geneva, Arial, Helvetica, sans-serif;
53 color: #000000;
54 font-size: x-large;
55 font-weight: bold;
56 text-align: center;
57 }
58 </style></head>
59 <body>
60 <h2 style="text-align: left; font-family: Helvetica,Arial,sans-serif;" class="style4"><big>Adding
61 a new button to creaContours</big></h2>
62 <span style="font-family: Helvetica,Arial,sans-serif;" class="text"><big>After taking a quick look at <a class="el" href="http://www.creatis.insa-lyon.fr/site/fr/CreatoolsCreaContours">creaContours'</a>
63 interface,
64 it's easy to agree that buttons are a very important part of it!
65 Adding, editing and deleting contours; extracting statistical data;
66 performing basic and complex
67 segmentation. All this is accomplished by pressing on the right button.
68 <br><br>This guide is concerned with the process of adding a new button to <a class="el" href="http://www.creatis.insa-lyon.fr/site/fr/CreatoolsCreaContours">creaContours</a>.
69 For that purpose, a detailed how-to guide is included in this
70 documentation alongside a sequence diagram that serves as an example of
71 the process that takes place
72 once a button is pressed.</big> <big>It
73 also details the process of displaying a panel, often used alongside
74 buttons to configure the different segmentation tools offered by
75 creaContours. Finally, a short tutorial on adding a new contour-drawing
76 button is included.<br><a name="beginning"></a><br></big></span><ol><li style="font-family: Helvetica,Arial,sans-serif;"><span style="font-weight: bold;"><a href="#1._Finding_where_to_start">Finding where to star</a>t. </span>How to figure out where to start writing the code that will let you add a new button to creaContours.</li><li style="font-family: Helvetica,Arial,sans-serif;"><span style="font-weight: bold;"><a href="#2._Adding_the_button_">Adding the button</a>. </span>As soon as we've found the right place to start, we have to add the actual button. Here such process is detailed.</li><li style="font-family: Helvetica,Arial,sans-serif;"><span style="font-weight: bold;"><a href="#3._The_callback_function_">The callback function</a>. </span>It's
77 not enough to add a new button; a functionality must be associated to
78 it. Here we describe how to create the callback function, which does
79 just that.</li><li style="font-family: Helvetica,Arial,sans-serif;"><span style="font-weight: bold;"><a href="#4._The_callback_action_">The callback action</a>. </span>Once
80 the callback function is called, something must happen. To explain how
81 to assign a callback action to a button (and its respective function)
82 is the objective of this section.</li><li style="font-family: Helvetica,Arial,sans-serif;"><span style="font-weight: bold;"><a href="#5._Button-click_pipeline_sequence_">Button-click pipeline</a>. </span>The sequence diagram which shows the pipeline the program goes through when a button is clicked.</li><li><span style="font-weight: bold; font-family: Helvetica,Arial,sans-serif;"><a href="#6._Adding_a_panel_">Adding a panel</a>. </span><span style="font-family: Helvetica,Arial,sans-serif;">What
83 if the functionality associated to a button requires the user to
84 configure a few parameters? In that case, it could be useful to have a
85 panel. Here we show how to create and display one.</span></li></ol><hr style="width: 100%; height: 2px; font-family: Helvetica,Arial,sans-serif;"><h3 style="font-family: Helvetica,Arial,sans-serif;"><big><a name="1._Finding_where_to_start"></a>1. Finding where to start</big></h3><span style="font-family: Helvetica,Arial,sans-serif;">Taking
86 a cursory look at creaContours' buttons panel, one can easily see that
87 its buttons are divided into categories: "New Contour" buttons, "I/O"
88 buttons, etc. This division of the interface is not arbitrary and
89 suggests that before creating a new button one has to decide into which
90 category it'll fit! Will it let the user perform a new kind of
91 segmentation? If yes, it must be added to the "Segmentation"
92 categories. Or will it permit the serial lecture of many contour .roi
93 files? Should it be that way, "I/O" is the place to go.</span><br style="font-family: Helvetica,Arial,sans-serif;"><br style="font-family: Helvetica,Arial,sans-serif;"><div style="text-align: center; font-family: Helvetica,Arial,sans-serif;"><img style="height: 771px; width: 305px;" alt="Image which shows creaContours' button panel, in which one can find all of the buttons that form the core of the application's functionality" title="creaContours' button interface" src="buttons.png"><br><h5>Figure [1]. Button panel (creaContours).</h5></div><span style="font-family: Helvetica,Arial,sans-serif;">As
94 soon as the correct placement of the button has been decided, the next
95 step is to write the necessary code so that it is correctly added to
96 the interface. Remembering that creaContours'
97 &lt;link&gt;architecture&lt;link&gt; is divided into three main
98 components, this would mean first identifying in which one of these the
99 modifcations have to be made. </span><br style="font-family: Helvetica,Arial,sans-serif;"><br style="font-family: Helvetica,Arial,sans-serif;"><span style="font-weight: bold; font-family: Helvetica,Arial,sans-serif;">kernel_ManagerContour_NDimensions_lib</span><span style="font-family: Helvetica,Arial,sans-serif;">
100 is constituted by the building blocks of
101 &lt;link&gt;creaContours&lt;link&gt;. This is the where the most basic
102 classes of the application are and as such it's not the right place to
103 look. </span><span style="font-weight: bold; font-family: Helvetica,Arial,sans-serif;">Interface_ManagerContour_NDimensions_lib</span><span style="font-family: Helvetica,Arial,sans-serif;">
104 contains many visual elements and sembles to be a good choice to look
105 in. But in reality, this library deals with the creation and edition of
106 contours and the management of "main" interface. It is therefore a high
107 level representation of the interface. This leaves only one option...</span><br style="font-family: Helvetica,Arial,sans-serif;"><br style="font-family: Helvetica,Arial,sans-serif;"><div style="text-align: center; font-family: Helvetica,Arial,sans-serif;"><img style="width: 253px; height: 244px;" alt="Image which graphically displays the classes that are within the Interface_Icons_NDimensions_lib library" title="Classes of Interface_Icons_NDimensions_lib" src="classes.png"><br><h5>Figure [2]. Interface_Icon_NDimensions_lib, where new buttons are added</h5></div><span style="font-family: Helvetica,Arial,sans-serif;">This
108 is clearly the right place! Each of the button panel's categories is
109 represented by a class, named accordingly: "interfIOMenu" is where the
110 buttons corresponding to the "I/O" category are. Having finally found
111 where to start, we must now choose which kind of button we want to
112 create so that we modify the appropriate class. Since the process is
113 similar for each category, we will choose an arbitrary one to
114 illustrate the process; "I/O" in this case.</span><br><div style="text-align: right;"><a href="#beginning"><span style="font-family: Helvetica,Arial,sans-serif;">Back to top</span></a></div><hr style="width: 100%; height: 2px; font-family: Helvetica,Arial,sans-serif;"><h3 style="font-family: Helvetica,Arial,sans-serif;"><a name="2._Adding_the_button_"></a><big><a name="2._Adding_the_button"></a>2. Adding the button</big></h3><span style="font-family: Helvetica,Arial,sans-serif;">Now
115 that we have choosen which kind of button to add, we can take a good
116 look to the corresponding class. As we just said, we're going to add a
117 new "I/O" button. It is therefore in interfIOMenu where we have to look.</span><br style="font-family: Helvetica,Arial,sans-serif;"><br style="font-family: Helvetica,Arial,sans-serif;"><div style="text-align: center; font-family: Helvetica,Arial,sans-serif;"><img style="width: 947px; height: 426px;" alt="This image shows the code contained within the hader file of the interfIOMenu class" title="Header file of interfIOMenu" src="header_interfIOMenu.png"><br><h5>Figure [3]. Header file of interfIOMenu</h5></div><span style="font-family: Helvetica,Arial,sans-serif;">Taking
118 a quick look a it we can identify the usual constructor/destructor pair
119 and a virtual "initButtons" method. Each class that represents a button
120 category must have implimented this virtual method, where all of the
121 buttons that belong to it have to be created and added. Other than
122 that, there is a method for each of the functions performed by each of
123 the category's button. In this case, "I/O" contains the Load, Save and
124 Import buttons and therefore there is a "On" method for each function.
125 These functions receive as parameters wxCommandEvent events. This basic
126 structure is replicated in each category class (interfSegmentationMenu,
127 interfToolsMenu, etc).</span><br style="font-family: Helvetica,Arial,sans-serif;"><br style="font-family: Helvetica,Arial,sans-serif;"><span style="font-family: Helvetica,Arial,sans-serif;">Hence, in order to add the new button we must go to the initButtons method in the .cxx.</span><br style="font-family: Helvetica,Arial,sans-serif;"><br style="font-family: Helvetica,Arial,sans-serif;"><div style="text-align: center; font-family: Helvetica,Arial,sans-serif;"><div style="text-align: center;"><img style="width: 735px; height: 315px;" alt="Code where a new button is added to the category. The image also shows what's to be written when adding a new button." title="Code where a new button is added" src="code_add_button.png"><br><h5>Figure [4]. &nbsp;Where to add the new button.</h5><div style="text-align: left;">As
128 we can see, adding a new button it's just a matter or replicating the
129 code that's been already written for the previous buttons. In this
130 case, we have added a new test button, underneath the big "New Button"
131 heading. In orther for this to work as expected, it's necessary to add
132 the button's image (in this case, test.png <img style="width: 27px; height: 27px;" alt="Image which is shown over the test button once it is sucessfully added to the interface" title="Test button image" src="test.png">)
133 to the data/Icons folder of the creaContours' CMake project. It's also
134 worth nothing that once a button is being added, its callback function
135 it's specified. In this case, it's the function OnTest, as shown in
136 Figure [4], which must also be added to the header file. If we go back
137 to it in Figure [3] we'll notice that it's already there.<br><br>If we
138 run the application now, we'll see that the button's been successfully
139 added to the interface. Finally, the callback function has to be
140 written!<br><div style="text-align: right;"><div style="text-align: right;"><a href="new_button.html#beginning"><span style="font-family: Helvetica,Arial,sans-serif;">Back to top</span></a></div></div><h3><a name="3._The_callback_function_"></a><big><a name="3._The_callback_function"></a>3. The callback function</big></h3>We now have a new button in our interface.<br><div style="text-align: center;"><img style="width: 200px; height: 70px;" alt="In this image we can see the original I/O buttons alongside the new test button" title="The new button's been added" src="new_button_added.png"><br><h5>Figure [5]. The I/O buttons alongside the new test button.</h5></div>It's
141 time to create a new callback function to associate a function to it.
142 For that purpose, we take a look at the existing callback functions.<br><br><div style="text-align: center;"><img style="width: 406px; height: 244px;" alt="Image which shows the code of the existing callback functions as well as that of the new callback function. The latter is marked in red." title="Existing callback functions" src="callback_functions.png"><br><h5>Figure [6]. The callback functions for each of the buttons.</h5><div style="text-align: left;">As
143 we can see, all that this function does is call the corresponding
144 callback function on the interfMainPanel class. This mean that there
145 we'll have to define at least one more callback function! The first
146 step is to find the interfMainPanel class header file
147 (interfMainPanel.h) and include a new function, "OnTest". <br><br><div style="text-align: center;"><img style="width: 317px; height: 174px;" alt="An image which shows how in the interfMainPanel class the callback functions are defined" title="The interfMainPanel callback functions" src="interfMainPanel.png"><br></div></div><h5><span style="font-weight: bold;">Figure [7]. The callback functions in interfMainPanel.</span></h5><div style="text-align: left;">By
148 principle, interfMainPanel is not a class where the "business logic" is
149 to be defined. It can be thought of as the agglomeration of the
150 different menu categories. We can thus expect the onLoad, onSave,
151 onImport and onTest functions to simply call another function on a
152 class where it's pertinent to perform the callback action. Taking a
153 look at the interfMainPanel.cxx file, we find out that this is
154 effectively the case.<br><br><div style="text-align: center;"><img style="width: 433px; height: 394px;" alt="An image that shows the piece of code where the interfMainPanel's callback function are defined (for the I/O menu category)" title="The callback functions in interfMainPanel" src="interfMainPanel_callback.png"><br><h5><span style="font-weight: bold;">Figure [8]. &nbsp;The callback functions in the interfMainPanel class.</span></h5></div></div><div style="text-align: left;">Once
155 again, we see that we have to go deeper into
156 &lt;link&gt;creaContours'&lt;link&gt; architecture. Each callback
157 function calls another function in another class, this time the
158 wxContourMainFrame class. But we're finally getting closer!<br><div style="text-align: right;"><div style="text-align: right;"><a href="new_button.html#beginning"><span style="font-family: Helvetica,Arial,sans-serif;">Back to top</span></a></div></div><h3><a name="4._The_callback_action_"></a><big><a name="4._The_callback_action"></a>4. The callback action</big></h3>Since
159 we must define a new callback function within wxContourMainFrame, it
160 goes without saying that it's declaration must be included in this
161 class' header file. Having done that, it's time to define the actual
162 callback function. Now, as wxContourMainFrame is where all callback
163 functions eventually end up, this is where the callback action has to
164 be defined. A callback action can be many things: opening a new window,
165 showing a new panel to configure the parameters of a segmentation (and
166 then execute it by pressing on the appropiate button) or drawing a new
167 contour. For this part of the example, we'll be satisfied by just
168 showing a File Selector window.<br><br><div style="text-align: center;"><img style="width: 758px; height: 267px;" alt="The code that shows the callback action code that's necessary so that a File Selector pops up when clicking on the button" title="The callback action code" src="callback_action.png"><br><h5>Figure [9]. &nbsp;The callback action, opening a file selector window.</h5></div>&nbsp;And
169 that's it! Now, we have to run creaContours and click on the newly
170 created button... and the File Selector window will pop up!<br><div style="text-align: center;"><a href="file_selector_popsup.png"><img style="border: 0px solid ; width: 757px; height: 573px;" alt="Image which shows the file selector window being shown once one clicks on the newly created button" title="The file selector window pops up" src="file_selector_popsup.png"></a><br><h5><span style="font-weight: bold;">Figure [10]. The file selector window pops up!</span></h5><div style="text-align: right;"><div style="text-align: right;"><a href="new_button.html#beginning"><span style="font-family: Helvetica,Arial,sans-serif;">Back to top</span></a></div></div><div style="text-align: justify;"><h3><a name="5._Button-click_pipeline_sequence_"></a><big><a name="5._Button-click_pipeline_sequence"></a>5.</big> <big>Button-click pipeline (sequence diagram)</big></h3><div style="text-align: right;"><div style="text-align: right;"><a href="new_button.html#beginning"><span style="font-family: Helvetica,Arial,sans-serif;">Back to top</span></a></div></div><h3><a name="6._Adding_a_panel_"></a><big><a name="6._Adding_a_panel"></a>6. Adding a panel</big></h3>It
171 must be said that a button that shows a file selector window is not
172 really the most interesting thing that can be done. By playing around
173 for a bit with creaContours' other buttons, we'll quickly notice that
174 many of them add small panels to the space underneath all the buttons.
175 These panels let the user configure the parameters of the function
176 associated to the button's he's pressed. These panels are particularly
177 important&nbsp;when doing segmentations. As one of creaContours' main
178 functions is to let the user segment the images he's working with,
179 knowing how to create a panel and use it afterwards it's very
180 important. This part of the guide deals precisely with this process.<br><br>We'll
181 start with the button that we just created, which causes a file
182 selector window to pop up. In order to add a panel to the window, we
183 follow the same process until the onTest method in interfMainPanel.
184 This is where the process starts to diverge as it is precisely in this
185 method where we'll create the panel and add it to the window. <br><br>However, before doing that, we have created the panel that we're going to add!<br><br>At this moment we can pose ourselves the questions: where exactly do we have to add this new panel? Let's take a look at <span style="font-weight: bold;">Interface_Icons_NDimensions_lib</span>, where all of creaContours' graphical elements are to be found:<br><div style="text-align: center;"><img style="width: 244px; height: 234px;" alt="Image which shows creaContours' graphical classes, with the panel classes being highlighted" title="The panel classes highlighted" src="panels-highlighted.png"><br><h5>Figure [11]. The panel classes highlighted</h5><div style="text-align: justify;">Clearly,
186 interfSegmentationPanels.cxx and interfToolsPanels.cxx are the two
187 files we have to take a look&nbsp;at! Intuitively, we know that the
188 prefix associated to each class (<span style="font-weight: bold;">Segmentation</span>Panels and <span style="font-weight: bold;">Tools</span>Panels)
189 represents to which button category the panels belong to it. The former
190 are the panels that are displayed once we press on a segmentation
191 button; the latter are the panels that are displayed once we press on a
192 Tools button. For the purpose of this guide, we will assume that our
193 button is going to be a Segmentation Button and therefore the panel
194 associated to it will be added to interfSegmentationPanels.<br><br>As a
195 matter of fact, these two files have within them the definition of each
196 panel that makes part of each particular category. For example, if we
197 go to interfSegmentationPanels.cxx and examine which class definitions
198 are contained within it, we'll see that there's three, one for each
199 panel.<br><br><div style="text-align: center;"><img style="width: 679px; height: 125px;" alt="Image which shows that within the interfSegmentationPanels.cxx file there's 3 class definiotns" title="All the panels" src="all_panels.png"><br><h5>Figure [12]. The three classes inside the interfSegmentationPanel class</h5></div></div><div style="text-align: justify;">If
200 we know look at the interfSegmentationPanels.h file, we'll see that in
201 it there's a brief definition of each of the three aforementioned
202 classes. This is where we must start, then. To get an idea of how to
203 proceed, let's look at the class definition for interfMirrorPanel:<br><div style="text-align: center;"><img style="width: 403px; height: 503px;" alt="Fragment of code whiwh shows the definition of the interfMirrorPanel class" title="InterfMirrorPanel" src="interfMirrorPanel.png"><br><h5>Figure [13]. The definition of the interfMirrorPanel class.</h5><div style="text-align: justify;">As
204 we can see, the class in itself it's not very complicated, but this is
205 also because the panel that it represents is fairly basic. Let's take a
206 quick look at it:<br><div style="text-align: center;"><img style="width: 206px; height: 163px;" alt="Image which shows the mirroring segmentation panel, in order to give the reader a rough idea of its graphical distribution" title="The mirroring panel" src="mirroring_panel.png"><br><h5>Figure [14]. The graphical distribution of the mirroring panel.</h5><div style="text-align: justify;">What
207 we're going to try to achieve in this guide is actually a very similar
208 panel; it'll have just two buttons, each one of which will have an
209 associated functionality. We must begin by writing down the class
210 definition of our new panel, that we'll name interfTestPanel. Following
211 the pattern shown above, we'll have:<br><br><div style="text-align: center;"><img style="width: 434px; height: 306px;" alt="Fragment of code showing the declaration of the new panel" title="interfTestPanel" src="interfTestPanel.png"><br><h5><span style="font-weight: bold;">Figure [15]. The declaration of the interfTestPanel class.</span></h5></div></div></div>As
212 we can see, we have two methods, onButton1Pressed and onButton2Pressed,
213 which receive two wxCommandEvent&amp; events. These are the callback
214 methods that are called once we click on a button. <br><br>Now that we have our class definition, we proceed to declare each method of our class.<br><br><div style="text-align: center;"><img style="width: 1033px; height: 623px;" alt="The full declaration of the interfTestPanel class" title="interfTestPanel" src="interfTestPanel_final.png"><br><h5>Figure [16]. The declaration of the new interfTestPanel class</h5></div>The
215 button callback methods, as we can see, do nothing in particular; they
216 just print into std::cout a message informing the use that the
217 respective button's been pressed. Inside the constructor, we create
218 both buttons as new <span style="font-weight: bold;">wxButtons. </span>These
219 take as parameters the panel into which they're going to be added, an
220 ID, a label, and a position. Explaining in detail these parameters (as
221 well as those used in the call to the <span style="font-weight: bold;">wxPanel</span> constructor) goes beyond the scope of this guide. <br><br>We associated an event to each button with the Connect method. In this case it's a <span style="font-weight: bold;">wxEVT_COMMAND_BUTTON_CLICKED </span>event.
222 Furthermore, each button has an associated callback function, which
223 must also be specified through the Connect method. The <span style="font-weight: bold;">wxFlexGridSizer </span>which is added immediately afterwards serves as a way to organize the elements on the interface.<br><br>Having
224 done that, we must now make sure that once we click on our button the
225 panel is added to the interface. In order to make sure of this, we have
226 to remember the "pipeline" that is followed when we click on a button.
227 This time around, we will folllow it all the way to the "onTest" method
228 in <span style="font-weight: bold;">interfMainPanel</span>, as it's
229 here that we have the necessary tools to display our new panel. Before
230 getting down to it, we have to add to new parameters to the <span style="font-weight: bold;">interfMainPanel.h</span> file:<br><div style="text-align: center;"><img style="width: 329px; height: 188px;" alt="Fragment of code which shows the new parameters added to an existing class so that the new panels can be created" title="The new panel" src="interfMainPanel_newPanel.png"><br><h5>Figure [17]. The declaration of the new panel parameters.</h5><div style="text-align: justify;">The first parameter is a regular <span style="font-weight: bold;">wxPanel </span>which will contain within it the actual <span style="font-weight: bold;">interfTestPanel, </span>which is the second parameter that's been added. As soon as we have them in our header file, we can go to the <span style="font-weight: bold;">OnTest </span>method and modify it so the panel is shown in the right place. Basing ourselves on the existing <span style="font-weight: bold;">onMirrorPressed </span>method, we get the following code which does exactly what we want it to:<br><br><div style="text-align: center;"><img style="width: 836px; height: 421px;" alt="Fragment of code which shows where the panel is actually shown" title="Showing the new panel" src="interfMainPanel_onShowPanel.png"><br><h5>Figure [18]. The fragment of code that serves to show the new panel</h5><div style="text-align: justify;">What is done here is actually quite simple. The new <span style="font-weight: bold;">testPanel</span> (of object type <span style="font-weight: bold;">wxPanel</span>)
231 contains within it the panel where the actual test panel is going to be
232 added. In other words, this is where we will store an instance of the
233 space underneath &nbsp;the buttons, represented as a panel. Having
234 created it, we further configure it before creating an instance of the
235 actual <span style="font-weight: bold;">interfMirrorPanel. </span>&nbsp;This is added to the <span style="font-weight: bold;">wxFlexGridSizer </span>which in turn has been set as the <span style="font-weight: bold;">testPanel</span>'<span style="font-weight: bold;">s </span>Sizer. It is why by doing so we're adding the <span style="font-weight: bold;">interfMirrorPanel </span>to
236 the space beneath the buttons, which is exactly what we wanted to do!
237 We end by adding a little bit of text (just for the purpose of staying
238 close to the other, already existing buttons) and we end by showing our
239 panel by invoking the <span style="font-weight: bold;">showPanel </span>method&nbsp;and passing it an instance of <span style="font-weight: bold;">testPanel, </span>which now contains within it the <span style="font-weight: bold;">interfMirrorPanel.</span><br><br>If we now run the interface and click on the new button, we'll obtain the following result...<br><div style="text-align: center;"><a href="newPanel_newButtons.png"><img style="border: 0px solid ; width: 724px; height: 632px;" alt="Image which shows the new panel and the buttons it contains, as well as the result that's printed out when you click on one of the buttons" title="new panel with new buttons" src="newPanel_newButtons.png"></a><br><h5>Figure [19]. The resulting panel</h5></div></div><div style="text-align: justify;">Mission accomplished!<br><div style="text-align: right;"><div style="text-align: right;"><a href="new_button.html#beginning"><span style="font-family: Helvetica,Arial,sans-serif;">Back to top</span></a></div></div></div></div></div><div style="text-align: justify;"></div></div></div></div></div></div> </div></div></div></div></div></div></div><span style="font-family: Helvetica,Arial,sans-serif;" class="text">
240 </span>
241 </body></html>