index.html
来自「《Big C++ 》Third Edition电子书和代码全集-Part1」· HTML 代码 · 共 620 行 · 第 1/2 页
HTML
620 行
</blockquote>
</font> </li>
</ul>
<hr><h2><font color='#009999'>27.6 Layout Management (cont.)</font></h2>
<ul>
<li><font size="+1">The problem is making user the buttons are placed correctly
inside the frame.</font></li>
<li><font size="+1">Some user interface toolkits supply a graphical layout tool
to define the placement of buttons, text controls, and other user interface
elements in a frame.</font></li>
<li><font size="+1">Such tools make designing a user interface simple, but the
design tends to be fragile.</font></li>
<li><font size="+1">If a component size changes (perhaps the button text is
translated to another language: "Goodbye" to "Auf Wiedersehen")
the entire layout needs to be rebuilt. </font></li>
<li><font size="+1">More robust layouts require a description of the logic behind
the placement of the interface elements.</font></li>
</ul>
<hr><h2><font color='#009999'>27.6 Layout Management (cont.)</font></h2>
<ul>
<li><font size="+1">In wxWindows, use objects of the <tt>wxSizer</tt> class
or one of its derived classes (such as <tt>wxBoxSizer</tt>) to specify the
layout of user interface elements. </font></li>
<li><font size="+1">These buttons would be lined up horizontally:
<blockquote>
<pre>wxBoxSizer* button_sizer = new wxBoxSizer(wxHORIZONTAL);
button_sizer->Add(hello_button);
button_sizer->Add(goodbye_button);</pre>
</blockquote>
</font></li>
<li><font size="+1">A second sizer places the text control on top of the button
row.
<blockquote>
<pre>wxBoxSizer* frame_sizer = new wxBoxSizer(wxVERTICAL);
frame_sizer->Add(text, 1, wxGROW);
frame_sizer->Add(button_sizer, 0, wxALIGN_CENTER);</pre>
</blockquote></font></li>
<blockquote><img src="images/button_frame.png"></blockquote>
</ul>
<hr><h2><font color='#009999'>27.6 Layout Management (cont.)</font></h2>
<ul>
<li><font size="+1">You must include commands to turn on auto layout and tell
the frame which sizer to use.
<blockquote>
<pre>SetAutoLayout(true);
SetSizer(frame_sizer);</pre>
</blockquote></font></li>
<li><font size="+1">The additional parameters in the <tt>Add</tt> function explain
how the layout is maintained when the user resizes.
<blockquote>
<pre>wxBoxSizer* frame_sizer = new wxBoxSizer(wxVERTICAL);
frame_sizer->Add(text, 1, wxGROW);
frame_sizer->Add(button_sizer, 0, wxALIGN_CENTER);</pre>
</blockquote></font></li>
<li><font size="+1">The second parameter indicates the ratio of size used in
vertical components.</font>
<ul>
<li><font size="+1">0 means don't resize.</font></li>
<li><font size="+1">If you had a component with parameter 1, and another
with parameter 2, the second would always use twice as much (vertical)
space as the first.</font></li>
</ul>
</li>
<li><font size="+1">The third parameter describes horizontal growth behavior.</font>
<ul>
<li><font size="+1">The text control grows with the window.</font></li>
<li><font size="+1">The button bar doesn't grow, but should be centered.</font></li>
</ul>
</li>
</ul>
<hr><h2><font color='#009999'>27.6 Layout Management (<tt>button.cpp)</tt></font></h2>
<iframe src="code/button.cpp.html" width="80%" height="80%">Your browser does not
support the <iframe> tag.</iframe>
<hr><h2><font color='#009999'>27.7 Painting</font></h2>
<ul>
<li><font size="+1">Drawing images in a windowing environment is not quite as
straightforward as you might think.</font>
<ul>
<li><font size="+1">What happens when a user re-sizes the window? ... minimizes
the window? ... restores the window?</font></li>
<li><font size="+1">What happens when another frame pops up over the image
and then vanishes?</font></li>
</ul>
</li>
<li><font size="+1">The program has no idea when these events will happen.</font></li>
<li><font size="+1">When they do happen, the window manager knows the contents
of the window have been corrupted and sends a paint event to the program.</font></li>
<li><font size="+1">The program needs to draw the image not just once, but <i>every
time a paint even occurs</i>.</font></li>
<li><font size="+1">All drawing instructions must be placed into a function
that is is the target of paint events.
<blockquote><pre>EVT_PAINT(EllipseWindow::OnPaint)</pre></blockquote></font></li>
</ul>
<hr><h2><font color='#009999'>27.7 Painting (cont.)</font></h2>
<ul>
<li><font size="+1">The paint function obtains a <i>device context</i>, which
is an object that represents the surface of the window.</font></li>
<li><font size="+1">The device context class has drawing functions such as <tt>DrawLine</tt>,
<tt>DrawEllipse</tt>, and <tt>DrawText</tt>.
<blockquote>
<pre>void EllipseWindow::OnPaint(wxPaintEvent& event)
{
wxPaintDC dc(this);
dc.SetBrush(*wxTRANSPARENT_BRUSH);
wxSize size = GetSize();
int x = 0;
int y = 0;
int width = size.GetWidth();
int height = size.GetHeight();
dc.DrawEllipse(x, y, width, height);
}</pre>
</blockquote></font></li>
</ul>
<hr><h2><font color='#009999'>27.7 Painting (cont.)</font></h2>
<ul>
<li><font size="+1">The <tt>DrawEllipse</tt> function requires you specify the
top left corner of the bounding box. </font></li>
<li><font size="+1">The device context coordinates are in pixels, with the point
(0, 0) in the top left corner.</font></li>
<img src="images/EllipseCoordinates.png">
</ul>
<hr><h2><font color='#009999'>27.7 Painting (cont.)</font></h2>
<ul>
<li><font size="+1">The <tt>OnPaint</tt> function does not draw on the application
frame, but on a separate window of type <tt>EllipseWindow</tt>, derived from
<tt>wxWindow</tt>.</font></li>
<li><font size="+1">We believe that an "ellipse window" is a user
interface element, just like a text control or button, and deserves it's own
class.</font></li>
<li><font size="+1">We will see another example later.</font></li>
</ul>
<blockquote><img src="images/ellipse_inheritance.png"></blockquote>
<hr><h2><font color='#009999'>27.7 Painting (<tt>paint.cpp</tt>)</font></h2>
<iframe src="code/paint.cpp.html" width="80%" height="80%">Your browser does not
support the <iframe> tag.</iframe>
<hr><h2><font color='#009999'>27.8 Mouse Events</font></h2>
<ul>
<li><font size="+1">To handle mouse input in a graphical window, you install
a function that is notified when mouse events occur.</font></li>
<li><font size="+1">There are several kinds of mouse events:</font>
<ul>
<li><font size="+1">motion</font></li>
<li><font size="+1">dragging (moving while depressing a mouse button)</font></li>
<li><font size="+1">mouse button going down</font></li>
<li><font size="+1">mouse button going up</font></li>
<li><font size="+1">clicking (mouse button going up and down within a short
period)</font></li>
<li><font size="+1">double clicking</font></li>
</ul>
</li>
<li><font size="+1">You install the mouse handler with the <tt>EVT_MOUSE_EVENTS</tt>
macros.
<blockquote>
<pre>BEGIN_EVENT_TABLE(TriangleWindow, wxWindow)
EVT_MOUSE_EVENTS(TriangleWindow::OnMouseEvent)
. . .</pre>
</blockquote> </font></li>
</ul>
<hr><h2><font color='#009999'>27.8 Mouse Events (cont.)</font></h2>
<ul>
<li><font size="+1">In the notification functions, you can query the <tt>wxMouseEvent</tt>
about the event type (e.g. <tt>ButtonDown()</tt> returns <tt>true</tt> or
<tt>false</tt>, <tt>GetX()</tt> returns the <i>x</i>-position of the mouse,
etc.).
<blockquote>
<pre>void TriangleWindow::OnMouseEvent(wxMouseEvent& event)
{
if (event.ButtonDown() && corners < 3)
{
x[corners] = event.GetX();
y[corners] = event.GetY();
corners++;
Refresh();
}
}</pre>
</blockquote>
</font></li>
<li><font size="+1">In our program, we allow the user to specify a triangle
by clicking on the three corners.</font></li>
<li><font size="+1">With each press, we record the mouse position.</font></li>
<li><font size="+1">All drawing should happen in the paint handler.</font></li>
<li><font size="+1">The <tt>Refresh</tt> function generates a paint event, which
eventually causes the paint function to be called.</font></li>
<li><font size="+1">Calling the paint function directly should never be done
- always refresh instead.</font></li>
</ul>
<hr><h2><font color='#009999'>27.8 Mouse Events (cont.)</font></h2>
<ul>
<li><font size="+1">Depending on the number of corners that have already been
specified, the paint handler draws </font>
<ul>
<li><font size="+1">a small circle for the first mouse click</font></li>
<li><font size="+1">a line after the first two mouse clicks</font></li>
<li><font size="+1">a triangle after three mouse clicks</font></li>
</ul>
</li>
<font size="+1">
<blockquote>
<pre>void TriangleWindow::OnPaint(wxPaintEvent & event)
{
const int RADIUS = 2;
wxPaintDC(this);
if (corners == 1)
dc.DrawEllpse(x[0] - RADIUS, y[0] - RADIUS,
2 * RADIUS, 2 * RADIUS);
if (corners >= 2)
dc.DrawLine(x[0], y[0], x[1], y[1]);
if (corners >= 3)
{
dc.DrawLine(x[1], y[1], x[2], y[2]);
dc.DrawLine(x[2], y[2], x[0], y[0]);
}
}
</pre>
</blockquote>
</font>
</ul>
<hr><h2><font color='#009999'>27.8 Mouse Events (<tt>mouse.cpp</tt>)</font></h2>
<iframe src="code/mouse.cpp.html" width="80%" height="80%">Your browser does not
support the <iframe> tag.</iframe>
<hr><h2><font color='#009999'>27.9 Dialogs</font></h2>
<ul>
<li><font size="+1">A <i>mode</i> restricts what a user can do at any given
time, or interprets a user in a way that depends on the mode.</font></li>
<li><font size="+1">Example: In over type mode in a word processor, the typed
characters replace existing characters instead of inserting themselves before
the cursor.</font></li>
<li><font size="+1">Experience has shown that modes burden program users - the
user must expend some mental effort and keep track of the current mode.</font></li>
<li><font size="+1">When designing a user interface, it is generally preferred
to minimize modes.</font></li>
</ul>
<hr><h2><font color='#009999'>27.9 Dialogs (cont.)</font></h2>
<ul>
<li><font size="+1">Another example of a special program mode is a dialog box
that requires immediate input from the user.</font></li>
<li><font size="+1">Because the user can do nothing else except fill or cancel
the dialog, it can be a burden.</font></li>
<li><font size="+1">Nevertheless, modal dialog boxes are necessary whenever
a program simply cannot proceed with user intervention.</font></li>
<li><font size="+1">The wxWindows toolkit makes is easy to program several kinds
of dialogs.
<blockquote>
<pre>wxMessageDialog* dialog = new wxMessageDialog(parent, message);
dialog->ShowModal();
dialog->Destroy();</pre>
</blockquote></font></li>
<li><font size="+1">The dialog pops up and is displayed until the user clicks
the "OK" button.
<blockquote><img src="images/Dialog1.png"></blockquote></font></li>
</ul>
<hr><h2><font color='#009999'>27.9 Dialogs (cont.)</font></h2>
<ul>
<li><font size="+1">The parent parameter is a pointer to the parent window,
over which the dialog box is placed.</font></li>
<li><font size="+1">The message parameter is of type <tt>wxString</tt>, a class
that is similar to the standard <tt>string</tt> type.</font></li>
<li><font size="+1">We recommend you use the standard string class for all string
computations, then use the <tt>c_str</tt> function to convert to a C string,
which is then automatically converted to a <tt>wxString</tt>.
<blockquote>
<pre>string message = "Hello, " + name;
dialog = new wxMessageDialog(this, message.c_str());</pre>
</blockquote></font></li>
<li><font size="+1">When you are done with a dialog, you should destroy it.</font></li>
</ul>
<hr><h2><font color='#009999'>27.9 Dialogs (cont.)</font></h2>
<ul>
<li><font size="+1">Another convenient dialog is the text entry dialog that
asks the user to supply a single line of text.
<blockquote>
<pre>wxTextEntryDialog* dialog = new wxTextEntryDialog(this,
"What is your name?";
dialog->ShowModal();
string name = dialog->GetValue().c_str();
dialog->Destroy();</pre>
</blockquote>
<P><blockquote><img src="images/Dialog2.png"></blockquote></font></li>
<li><font size="+1">The <tt>GetValue</tt> function returns a <tt>wxString</tt>.
That class also has a <tt>c_str</tt> function to convert to a C string.</font></li>
</ul>
<hr><h2><font color='#009999'>27.10 Case Study: A GUI for the Clock Game</font></h2>
<ul>
<li><font size="+1">The final example is a wxWindows version of the clock game
of Chapter 13.</font></li>
<li><font size="+1">Because of the event-driven nature of GUI programming, several
modifications had to be made to the program logic.</font></li>
<li><font size="+1">In this program, each guess is communicated to the program
in the handler of the "Guess" button.</font></li>
<li><font size="+1">A data field <tt>tries</tt> has been added to keep track
of whether the guess is a first or second guess.</font></li>
<li><font size="+1">The user selects menu options that lead to dialog boxes
to enter the user name and choose level.</font></li>
<li><font size="+1">Now the user can change level at any time during the game.</font></li>
<li><font size="+1">To simplify compilation, the nonstandard Point and Time
classes have been eliminated from the program.</font></li>
</ul>
<hr><h2><font color='#009999'>27.10 Case Study: A GUI for the Clock Game (cont.)</font></h2>
<ul>
<li><font size="+1">Classes of the Clock Game </font></li>
</ul>
<blockquote><img src="images/game_classes.png"></blockquote>
<hr><h2><font color='#009999'>27.10 Case Study: (<tt>game.cpp</tt>)</font></h2>
<iframe src="code/game.cpp.html" width="80%" height="80%">Your browser does not
support the <iframe> tag.</iframe>
</body>
</html>
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?