epubjs
Version:
Render ePub documents in the browser, across many devices
319 lines (303 loc) • 89.8 kB
HTML
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>GridBagLayout</title><link rel="stylesheet" href="core.css" type="text/css"/><meta name="generator" content="DocBook XSL Stylesheets V1.74.0"/></head><body><div class="sect1" title="GridBagLayout"><div class="titlepage"><div><div><h1 class="title"><a id="learnjava3-CHP-19-SECT-6"/>GridBagLayout</h1></div></div></div><p><code class="literal">GridBagLayout</code> is a very flexible
layout manager that allows you to position components relative to one
another using constraints. With <code class="literal">GridBagLayout</code> (and a fair amount of effort), you
can create almost any imaginable layout. Components are arranged at
logical coordinates on an abstract grid. We call them “logical”
coordinates because they designate positions in the space of rows and
columns formed by the set of components. Rows and columns of the grid
stretch to different sizes, based on the sizes and constraints of the
components they hold.</p><p>A row or column in a <code class="literal">GridBagLayout</code> expands to accommodate the
dimensions and constraints of the largest component it contains.
Individual components may also be told to span more than one row or
column. Components that aren’t as large as their grid cell can be anchored
(positioned to one side) within their cell. They can also be set to fill
or expand their size in either dimension. Extra area in the grid rows and
columns can be parceled out according to the weight constraints of the
components. In this way, you can control how various components will grow
and stretch when a window is resized.</p><p><code class="literal">GridBagLayout</code> is much easier to
use in a graphical WYSIWYG GUI builder environment. That’s because working
with <code class="literal">GridBag</code> is kind of like messing
with the old rabbit-ears antennae on your television. It’s not
particularly difficult to get the results that you want through trial and
error, but writing out hard and fast rules for how to go about it is
difficult. In short, <code class="literal">GridBagLayout</code> is
complex and has some quirks. It is also simply a bit ugly both in model
and implementation. Remember that you can do a lot with nested panels and
by composing simpler layout managers within one another. If you look back
through this chapter, you’ll see some examples of composite layouts; it’s
up to you to determine how far you should go before making the break from
simpler layout managers to a more complex all-in-one layout manager like
<code class="literal">GridBagLayout</code>.</p><div class="sect2" title="The GridBagConstraints Class"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-19-SECT-6.1"/>The GridBagConstraints Class</h2></div></div></div><p><a id="idx11052" class="indexterm"/> <a id="idx11057" class="indexterm"/> <a id="idx11072" class="indexterm"/>Having stated that <code class="literal">GridBagLayout</code> is complex and a bit ugly, we’re
going to contradict ourselves a little and say that its API is
surprisingly simple. There is only one constructor with no
arguments—<code class="literal">GridBagLayout()</code>—and there
aren’t a lot of fancy methods to control how the display works.</p><p>The appearance of a grid bag layout is controlled by sets of
<code class="literal">GridBagConstraints</code>, and that’s where
things get hairy. Each component that is managed by a <code class="literal">GridBagLayout</code> is associated with a <code class="literal">GridBagConstraints</code> object. <code class="literal">GridBagConstraints</code> holds the following
variables, which we’ll describe in detail shortly:</p><div class="variablelist"><dl><dt><span class="term"><code class="literal">int gridx</code><br/></span><span class="term"><code class="literal">int gridy</code></span></dt><dd><p><a id="I_indexterm19_id806413" class="indexterm"/> <a id="I_indexterm19_id806419" class="indexterm"/>Controls the position of the component on the
layout’s grid</p></dd><dt><span class="term"><code class="literal">int weightx</code><br/></span><span class="term"><code class="literal">int weighty</code></span></dt><dd><p><a id="I_indexterm19_id806440" class="indexterm"/> <a id="I_indexterm19_id806447" class="indexterm"/>Controls how additional space in the row or column
is allotted to the component</p></dd><dt><span class="term"><code class="literal">int fill</code></span></dt><dd><p><a id="I_indexterm19_id806463" class="indexterm"/>Controls whether the component expands to fill the
allotted space</p></dd><dt><span class="term"><code class="literal">int gridheight</code><br/></span><span class="term"><code class="literal">int gridwidth</code></span></dt><dd><p><a id="I_indexterm19_id806483" class="indexterm"/> <a id="I_indexterm19_id806490" class="indexterm"/>Controls the number of rows or columns the component
spans</p></dd><dt><span class="term"><code class="literal">int anchor</code></span></dt><dd><p><a id="I_indexterm19_id806506" class="indexterm"/>Controls the position of the component if there is
extra room within the allotted space</p></dd><dt><span class="term"><code class="literal">int ipadx</code><br/></span><span class="term"><code class="literal">int ipady</code></span></dt><dd><p><a id="I_indexterm19_id806526" class="indexterm"/> <a id="I_indexterm19_id806533" class="indexterm"/>Controls padding between the component and the
borders of its area</p></dd><dt><span class="term"><code class="literal">Insets insets</code></span></dt><dd><p><a id="I_indexterm19_id806548" class="indexterm"/>Controls padding between the component and
neighboring components</p></dd></dl></div><p>To make a set of constraints for a component or components, create
a new instance of <code class="literal">GridBagConstraints</code>
and set these public variables to the appropriate values. (There is also
a large constructor that takes all 11 arguments.)</p><p>The easiest way to associate a set of constraints with a component
is to use the version of <code class="literal">add()</code> that
takes both a component object and a layout object as arguments. This
puts the component in the container and associates the <code class="literal">GridBagConstraints</code> object with it:</p><a id="I_19_tt1119"/><pre class="programlisting"> <code class="n">Container</code> <code class="n">content</code> <code class="o">=</code> <code class="n">getContentPane</code><code class="o">();</code>
<code class="n">JComponent</code> <code class="n">component</code> <code class="o">=</code> <code class="k">new</code> <code class="n">JLabel</code><code class="o">(</code><code class="s">"constrain me, please..."</code><code class="o">);</code>
<code class="n">GridBagConstraints</code> <code class="n">constraints</code> <code class="o">=</code> <code class="k">new</code> <code class="n">GridBagConstraints</code><code class="o">();</code>
<code class="n">constraints</code><code class="o">.</code><code class="na">gridx</code> <code class="o">=</code> <code class="n">x</code><code class="o">;</code>
<code class="n">constraints</code><code class="o">.</code><code class="na">gridy</code> <code class="o">=</code> <code class="n">y</code><code class="o">;</code>
<code class="o">...</code>
<code class="n">content</code><code class="o">.</code><code class="na">add</code><code class="o">(</code><code class="n">component</code><code class="o">,</code> <code class="n">constraints</code><code class="o">);</code></pre><p>You can also add a component to a <code class="literal">GridBagLayout</code> using the single argument
<code class="literal">add()</code> method and then calling the
layout’s <code class="literal">setConstraints()</code> method
directly to pass it the <code class="literal">GridBagConstraints</code> object for that
component:</p><a id="I_19_tt1120"/><pre class="programlisting"> <code class="n">add</code><code class="o">(</code><code class="n">component</code><code class="o">);</code>
<code class="o">...</code>
<code class="n">myGridBagLayout</code><code class="o">.</code><code class="na">setConstraints</code><code class="o">(</code><code class="n">component</code><code class="o">,</code> <code class="n">constraints</code><code class="o">);</code></pre><p>In either case, the set of constraints is copied when it is
applied to the component. It’s the individual constraints that apply to
the component, not the <code class="literal">GridBagConstraints</code> object. Therefore, you’re
free to create a single set of <code class="literal">GridBagConstraints</code>, modify it as needed, and
apply it as needed to different objects. You might want to create a
helper method that sets the constraints appropriately, then adds the
component with its constraints to the layout. That’s the approach we’ll
take in our examples; our helper method is called <code class="literal">addGB()</code>, and it takes a component plus a pair
of coordinates as arguments. These coordinates become the <code class="literal">gridx</code> and <code class="literal">gridy</code> values for the constraints. We could
expand upon this later and overload <code class="literal">addGB()</code> to take more parameters for other
constraints that we often change from component to component.<a id="I_indexterm19_id806672" class="indexterm"/><a id="I_indexterm19_id806679" class="indexterm"/><a id="I_indexterm19_id806686" class="indexterm"/></p></div><div class="sect2" title="Grid Coordinates"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-19-SECT-6.2"/>Grid Coordinates</h2></div></div></div><p><a id="idx11051" class="indexterm"/> <a id="idx11056" class="indexterm"/> <a id="idx11071" class="indexterm"/>One of the biggest surprises in the <code class="literal">GridBagLayout</code> is that there’s no way to
specify the size of the grid. There doesn’t have to be. The grid size is
determined implicitly by the constraints of all the objects; the layout
manager picks dimensions large enough so that everything fits. Thus, if
you put one component in a layout and set its <a id="I_indexterm19_id806749" class="indexterm"/><code class="literal">gridx</code> and <a id="I_indexterm19_id806759" class="indexterm"/><code class="literal">gridy</code> constraints each
to <code class="literal">25</code>, the layout manager creates a
virtual 25 × 25 grid, with rows and columns numbered from 0 to 24. If
you then add a second component with a <code class="literal">gridx</code> of <code class="literal">30</code>
and a <code class="literal">gridy</code> of <code class="literal">13</code>, the virtual grid’s dimensions change to 30
× 25. You don’t have to worry about setting up an appropriate number of
rows and columns. The layout manager does it automatically as you add
components.</p><p>With this knowledge, we’re ready to create some simple displays.
We’ll start by arranging a group of components in a cross shape. We
maintain explicit <code class="literal">x</code> and <code class="literal">y</code> local variables, setting them as we add the
components to our grid. This is partly for clarity, but it can be a
handy technique when you want to add a number of components in a row or
column. You can simply increment <code class="literal">gridx</code> or <code class="literal">gridy</code> before adding each component. This is a
simple and problem-free way to achieve relative placement. (Later, we’ll
describe <code class="literal">GridBagConstraints</code>’s
<code class="literal">RELATIVE</code> constant, which performs
relative placement automatically.) The following code shows the first
layout (see <a class="xref" href="ch19s06.html#learnjava3-CHP-19-FIG-7" title="Figure 19-7. A simple GridBagLayout">Figure 19-7</a>):</p><a id="I_19_tt1121"/><pre class="programlisting"> <code class="c1">//file: GridBag1.java</code>
<code class="kn">import</code> <code class="nn">java.awt.*</code><code class="o">;</code>
<code class="kn">import</code> <code class="nn">java.awt.event.*</code><code class="o">;</code>
<code class="kn">import</code> <code class="nn">javax.swing.*</code><code class="o">;</code>
<code class="kd">public</code> <code class="kd">class</code> <code class="nc">GridBag1</code> <code class="kd">extends</code> <code class="n">JPanel</code> <code class="o">{</code>
<code class="n">GridBagConstraints</code> <code class="n">constraints</code> <code class="o">=</code> <code class="k">new</code> <code class="n">GridBagConstraints</code><code class="o">();</code>
<code class="kd">public</code> <code class="nf">GridBag1</code><code class="o">()</code> <code class="o">{</code>
<code class="n">setLayout</code><code class="o">(</code><code class="k">new</code> <code class="n">GridBagLayout</code><code class="o">());</code>
<code class="kt">int</code> <code class="n">x</code><code class="o">,</code> <code class="n">y</code><code class="o">;</code> <code class="c1">// for clarity</code>
<code class="n">addGB</code><code class="o">(</code><code class="k">new</code> <code class="n">JButton</code><code class="o">(</code><code class="s">"North"</code><code class="o">),</code> <code class="n">x</code> <code class="o">=</code> <code class="mi">1</code><code class="o">,</code> <code class="n">y</code> <code class="o">=</code> <code class="mi">0</code><code class="o">);</code>
<code class="n">addGB</code><code class="o">(</code><code class="k">new</code> <code class="n">JButton</code><code class="o">(</code><code class="s">"West"</code><code class="o">),</code> <code class="n">x</code> <code class="o">=</code> <code class="mi">0</code><code class="o">,</code> <code class="n">y</code> <code class="o">=</code> <code class="mi">1</code><code class="o">);</code>
<code class="n">addGB</code><code class="o">(</code><code class="k">new</code> <code class="n">JButton</code><code class="o">(</code><code class="s">"Center"</code><code class="o">),</code> <code class="n">x</code> <code class="o">=</code> <code class="mi">1</code><code class="o">,</code> <code class="n">y</code> <code class="o">=</code> <code class="mi">1</code><code class="o">);</code>
<code class="n">addGB</code><code class="o">(</code><code class="k">new</code> <code class="n">JButton</code><code class="o">(</code><code class="s">"East"</code><code class="o">),</code> <code class="n">x</code> <code class="o">=</code> <code class="mi">2</code><code class="o">,</code> <code class="n">y</code> <code class="o">=</code> <code class="mi">1</code><code class="o">);</code>
<code class="n">addGB</code><code class="o">(</code><code class="k">new</code> <code class="n">JButton</code><code class="o">(</code><code class="s">"South"</code><code class="o">),</code> <code class="n">x</code> <code class="o">=</code> <code class="mi">1</code><code class="o">,</code> <code class="n">y</code> <code class="o">=</code> <code class="mi">2</code><code class="o">);</code>
<code class="o">}</code>
<code class="kt">void</code> <code class="nf">addGB</code><code class="o">(</code><code class="n">Component</code> <code class="n">component</code><code class="o">,</code> <code class="kt">int</code> <code class="n">x</code><code class="o">,</code> <code class="kt">int</code> <code class="n">y</code><code class="o">)</code> <code class="o">{</code>
<code class="n">constraints</code><code class="o">.</code><code class="na">gridx</code> <code class="o">=</code> <code class="n">x</code><code class="o">;</code>
<code class="n">constraints</code><code class="o">.</code><code class="na">gridy</code> <code class="o">=</code> <code class="n">y</code><code class="o">;</code>
<code class="n">add</code><code class="o">(</code><code class="n">component</code><code class="o">,</code> <code class="n">constraints</code><code class="o">);</code>
<code class="o">}</code>
<code class="kd">public</code> <code class="kd">static</code> <code class="kt">void</code> <code class="nf">main</code><code class="o">(</code><code class="n">String</code><code class="o">[]</code> <code class="n">args</code><code class="o">)</code> <code class="o">{</code>
<code class="n">JFrame</code> <code class="n">frame</code> <code class="o">=</code> <code class="k">new</code> <code class="n">JFrame</code><code class="o">(</code><code class="s">"GridBag1"</code><code class="o">);</code>
<code class="n">frame</code><code class="o">.</code><code class="na">setDefaultCloseOperation</code><code class="o">(</code> <code class="n">JFrame</code><code class="o">.</code><code class="na">EXIT_ON_CLOSE</code> <code class="o">);</code>
<code class="n">frame</code><code class="o">.</code><code class="na">setSize</code><code class="o">(</code><code class="mi">225</code><code class="o">,</code> <code class="mi">150</code><code class="o">);</code>
<code class="n">frame</code><code class="o">.</code><code class="na">setLocation</code><code class="o">(</code><code class="mi">200</code><code class="o">,</code> <code class="mi">200</code><code class="o">);</code>
<code class="n">frame</code><code class="o">.</code><code class="na">setContentPane</code><code class="o">(</code><code class="k">new</code> <code class="n">GridBag1</code><code class="o">());</code>
<code class="n">frame</code><code class="o">.</code><code class="na">setVisible</code><code class="o">(</code><code class="kc">true</code><code class="o">);</code>
<code class="o">}</code>
<code class="o">}</code></pre><div class="figure"><a id="learnjava3-CHP-19-FIG-7"/><div class="figure-contents"><div class="mediaobject"><a id="I_19_tt1122"/><img src="httpatomoreillycomsourceoreillyimages1707684.png" alt="A simple GridBagLayout"/></div></div><p class="title">Figure 19-7. A simple GridBagLayout</p></div><p>The buttons in this example are “clumped” together in the center
of their display area. Each button is displayed at its preferred size,
without stretching to fill the available space. This is how the layout
manager behaves when the “weight” constraints are left unset. We’ll talk
more about weights in the next two sections.<a id="I_indexterm19_id806894" class="indexterm"/><a id="I_indexterm19_id806901" class="indexterm"/><a id="I_indexterm19_id806908" class="indexterm"/></p></div><div class="sect2" title="The fill Constraint"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-19-SECT-6.3"/>The fill Constraint</h2></div></div></div><p><a id="idx11049" class="indexterm"/> <a id="idx11055" class="indexterm"/> <a id="idx11070" class="indexterm"/>Let’s make the buttons expand to fill the entire <code class="literal">JFrame</code> window. To do so, we must take two
steps: we must set the <a id="I_indexterm19_id806966" class="indexterm"/><code class="literal">fill</code> constraint for
each button to the value <code class="literal">BOTH</code>, and we
must set the <a id="I_indexterm19_id806983" class="indexterm"/><code class="literal">weightx</code> and <a id="I_indexterm19_id806993" class="indexterm"/><code class="literal">weighty</code> to nonzero
values, as shown in this example:</p><a id="I_19_tt1123"/><pre class="programlisting"> <code class="c1">//file: GridBag2.java</code>
<code class="kn">import</code> <code class="nn">java.awt.*</code><code class="o">;</code>
<code class="kn">import</code> <code class="nn">java.awt.event.*</code><code class="o">;</code>
<code class="kn">import</code> <code class="nn">javax.swing.*</code><code class="o">;</code>
<code class="kd">public</code> <code class="kd">class</code> <code class="nc">GridBag2</code> <code class="kd">extends</code> <code class="n">JPanel</code> <code class="o">{</code>
<code class="n">GridBagConstraints</code> <code class="n">constraints</code> <code class="o">=</code> <code class="k">new</code> <code class="n">GridBagConstraints</code><code class="o">();</code>
<code class="kd">public</code> <code class="nf">GridBag2</code><code class="o">()</code> <code class="o">{</code>
<code class="n">setLayout</code><code class="o">(</code><code class="k">new</code> <code class="n">GridBagLayout</code><code class="o">());</code>
<code class="n">constraints</code><code class="o">.</code><code class="na">weightx</code> <code class="o">=</code> <code class="mf">1.0</code><code class="o">;</code>
<code class="n">constraints</code><code class="o">.</code><code class="na">weighty</code> <code class="o">=</code> <code class="mf">1.0</code><code class="o">;</code>
<code class="n">constraints</code><code class="o">.</code><code class="na">fill</code> <code class="o">=</code> <code class="n">GridBagConstraints</code><code class="o">.</code><code class="na">BOTH</code><code class="o">;</code>
<code class="kt">int</code> <code class="n">x</code><code class="o">,</code> <code class="n">y</code><code class="o">;</code> <code class="c1">// for clarity</code>
<code class="n">addGB</code><code class="o">(</code><code class="k">new</code> <code class="n">JButton</code><code class="o">(</code><code class="s">"North"</code><code class="o">),</code> <code class="n">x</code> <code class="o">=</code> <code class="mi">1</code><code class="o">,</code> <code class="n">y</code> <code class="o">=</code> <code class="mi">0</code><code class="o">);</code>
<code class="n">addGB</code><code class="o">(</code><code class="k">new</code> <code class="n">JButton</code><code class="o">(</code><code class="s">"West"</code><code class="o">),</code> <code class="n">x</code> <code class="o">=</code> <code class="mi">0</code><code class="o">,</code> <code class="n">y</code> <code class="o">=</code> <code class="mi">1</code><code class="o">);</code>
<code class="n">addGB</code><code class="o">(</code><code class="k">new</code> <code class="n">JButton</code><code class="o">(</code><code class="s">"Center"</code><code class="o">),</code> <code class="n">x</code> <code class="o">=</code> <code class="mi">1</code><code class="o">,</code> <code class="n">y</code> <code class="o">=</code> <code class="mi">1</code><code class="o">);</code>
<code class="n">addGB</code><code class="o">(</code><code class="k">new</code> <code class="n">JButton</code><code class="o">(</code><code class="s">"East"</code><code class="o">),</code> <code class="n">x</code> <code class="o">=</code> <code class="mi">2</code><code class="o">,</code> <code class="n">y</code> <code class="o">=</code> <code class="mi">1</code><code class="o">);</code>
<code class="n">addGB</code><code class="o">(</code><code class="k">new</code> <code class="n">JButton</code><code class="o">(</code><code class="s">"South"</code><code class="o">),</code> <code class="n">x</code> <code class="o">=</code> <code class="mi">1</code><code class="o">,</code> <code class="n">y</code> <code class="o">=</code> <code class="mi">2</code><code class="o">);</code>
<code class="o">}</code>
<code class="kt">void</code> <code class="nf">addGB</code><code class="o">(</code><code class="n">Component</code> <code class="n">component</code><code class="o">,</code> <code class="kt">int</code> <code class="n">x</code><code class="o">,</code> <code class="kt">int</code> <code class="n">y</code><code class="o">)</code> <code class="o">{</code>
<code class="n">constraints</code><code class="o">.</code><code class="na">gridx</code> <code class="o">=</code> <code class="n">x</code><code class="o">;</code>
<code class="n">constraints</code><code class="o">.</code><code class="na">gridy</code> <code class="o">=</code> <code class="n">y</code><code class="o">;</code>
<code class="n">add</code><code class="o">(</code><code class="n">component</code><code class="o">,</code> <code class="n">constraints</code><code class="o">);</code>
<code class="o">}</code>
<code class="kd">public</code> <code class="kd">static</code> <code class="kt">void</code> <code class="nf">main</code><code class="o">(</code><code class="n">String</code><code class="o">[]</code> <code class="n">args</code><code class="o">)</code> <code class="o">{</code>
<code class="n">JFrame</code> <code class="n">frame</code> <code class="o">=</code> <code class="k">new</code> <code class="n">JFrame</code><code class="o">(</code><code class="s">"GridBag2"</code><code class="o">);</code>
<code class="n">frame</code><code class="o">.</code><code class="na">setDefaultCloseOperation</code><code class="o">(</code> <code class="n">JFrame</code><code class="o">.</code><code class="na">EXIT_ON_CLOSE</code> <code class="o">);</code>
<code class="n">frame</code><code class="o">.</code><code class="na">setSize</code><code class="o">(</code><code class="mi">225</code><code class="o">,</code> <code class="mi">150</code><code class="o">);</code>
<code class="n">frame</code><code class="o">.</code><code class="na">setLocation</code><code class="o">(</code><code class="mi">200</code><code class="o">,</code> <code class="mi">200</code><code class="o">);</code>
<code class="n">frame</code><code class="o">.</code><code class="na">setContentPane</code><code class="o">(</code><code class="k">new</code> <code class="n">GridBag2</code><code class="o">());</code>
<code class="n">frame</code><code class="o">.</code><code class="na">setVisible</code><code class="o">(</code><code class="kc">true</code><code class="o">);</code>
<code class="o">}</code>
<code class="o">}</code></pre><p><a class="xref" href="ch19s06.html#learnjava3-CHP-19-FIG-8" title="Figure 19-8. Making buttons fill the available space">Figure 19-8</a> shows the resulting
layout.</p><div class="figure"><a id="learnjava3-CHP-19-FIG-8"/><div class="figure-contents"><div class="mediaobject"><a id="I_19_tt1124"/><img src="httpatomoreillycomsourceoreillyimages1707685.png.jpg" alt="Making buttons fill the available space"/></div></div><p class="title">Figure 19-8. Making buttons fill the available space</p></div><p><code class="literal">BOTH</code> is one of the constants of
the <code class="literal">GridBagConstraints</code> class; it
tells the component to fill the available space in both directions. Here
are the constants you can use to set the <code class="literal">fill</code> field:</p><div class="variablelist"><dl><dt><span class="term"><code class="literal">HORIZONTAL</code></span></dt><dd><p><a id="I_indexterm19_id807076" class="indexterm"/>Fill the available horizontal space.</p></dd><dt><span class="term"><code class="literal">VERTICAL</code></span></dt><dd><p><a id="I_indexterm19_id807091" class="indexterm"/>Fill the available vertical space.</p></dd><dt><span class="term"><code class="literal">BOTH</code></span></dt><dd><p><a id="I_indexterm19_id807106" class="indexterm"/>Fill the available space in both directions.</p></dd><dt><span class="term"><code class="literal">NONE</code></span></dt><dd><p><a id="I_indexterm19_id807122" class="indexterm"/>Don’t fill the available space; display the
component at its preferred size.</p></dd></dl></div><p>We set the weight constraints to <code class="literal">1.0</code>; in this example, it doesn’t matter what
they are, provided each component has the same nonzero weight. Filling
doesn’t occur if the component’s weight in the direction you’re filling
is <code class="literal">0</code>, which is the default
value.<a id="I_indexterm19_id807146" class="indexterm"/><a id="I_indexterm19_id807154" class="indexterm"/><a id="I_indexterm19_id807161" class="indexterm"/></p></div><div class="sect2" title="Spanning Rows and Columns"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-19-SECT-6.4"/>Spanning Rows and Columns</h2></div></div></div><p><a id="idx11047" class="indexterm"/> <a id="idx11060" class="indexterm"/> <a id="idx11075" class="indexterm"/> <a id="idx11080" class="indexterm"/>One of the most important features of <code class="literal">GridBaglayout</code> is that it lets you create
arrangements in which components span two or more rows or columns. To do
so, set the <a id="I_indexterm19_id807230" class="indexterm"/><code class="literal">gridwidth</code> and
<a id="I_indexterm19_id807241" class="indexterm"/><code class="literal">gridheight</code> variables of
the <code class="literal">GridBagConstraints</code>. The following
example creates such a display; button one spans two columns vertically
and button four spans two horizontally. <a class="xref" href="ch19s06.html#learnjava3-CHP-19-FIG-9" title="Figure 19-9. Making components span rows and columns">Figure 19-9</a> shows the resulting layout.</p><a id="I_19_tt1125"/><pre class="programlisting"> <code class="c1">//file: GridBag3.java</code>
<code class="kn">import</code> <code class="nn">java.awt.*</code><code class="o">;</code>
<code class="kn">import</code> <code class="nn">java.awt.event.*</code><code class="o">;</code>
<code class="kn">import</code> <code class="nn">javax.swing.*</code><code class="o">;</code>
<code class="kd">public</code> <code class="kd">class</code> <code class="nc">GridBag3</code> <code class="kd">extends</code> <code class="n">JPanel</code> <code class="o">{</code>
<code class="n">GridBagConstraints</code> <code class="n">constraints</code> <code class="o">=</code> <code class="k">new</code> <code class="n">GridBagConstraints</code><code class="o">();</code>
<code class="kd">public</code> <code class="nf">GridBag3</code><code class="o">()</code> <code class="o">{</code>
<code class="n">setLayout</code><code class="o">(</code><code class="k">new</code> <code class="n">GridBagLayout</code><code class="o">());</code>
<code class="n">constraints</code><code class="o">.</code><code class="na">weightx</code> <code class="o">=</code> <code class="mf">1.0</code><code class="o">;</code>
<code class="n">constraints</code><code class="o">.</code><code class="na">weighty</code> <code class="o">=</code> <code class="mf">1.0</code><code class="o">;</code>
<code class="n">constraints</code><code class="o">.</code><code class="na">fill</code> <code class="o">=</code> <code class="n">GridBagConstraints</code><code class="o">.</code><code class="na">BOTH</code><code class="o">;</code>
<code class="kt">int</code> <code class="n">x</code><code class="o">,</code> <code class="n">y</code><code class="o">;</code> <code class="c1">// for clarity</code>
<code class="n">constraints</code><code class="o">.</code><code class="na">gridheight</code> <code class="o">=</code> <code class="mi">2</code><code class="o">;</code> <code class="c1">// span two rows</code>
<code class="n">addGB</code><code class="o">(</code><code class="k">new</code> <code class="n">JButton</code><code class="o">(</code><code class="s">"one"</code><code class="o">),</code> <code class="n">x</code> <code class="o">=</code> <code class="mi">0</code><code class="o">,</code> <code class="n">y</code> <code class="o">=</code> <code class="mi">0</code><code class="o">);</code>
<code class="n">constraints</code><code class="o">.</code><code class="na">gridheight</code> <code class="o">=</code> <code class="mi">1</code><code class="o">;</code> <code class="c1">// set it back</code>
<code class="n">addGB</code><code class="o">(</code><code class="k">new</code> <code class="n">JButton</code><code class="o">(</code><code class="s">"two"</code><code class="o">),</code> <code class="n">x</code> <code class="o">=</code> <code class="mi">1</code><code class="o">,</code> <code class="n">y</code> <code class="o">=</code> <code class="mi">0</code><code class="o">);</code>
<code class="n">addGB</code><code class="o">(</code><code class="k">new</code> <code class="n">JButton</code><code class="o">(</code><code class="s">"three"</code><code class="o">),</code> <code class="n">x</code> <code class="o">=</code> <code class="mi">2</code><code class="o">,</code> <code class="n">y</code> <code class="o">=</code> <code class="mi">0</code><code class="o">);</code>
<code class="n">constraints</code><code class="o">.</code><code class="na">gridwidth</code> <code class="o">=</code> <code class="mi">2</code><code class="o">;</code> <code class="c1">// span two columns</code>
<code class="n">addGB</code><code class="o">(</code><code class="k">new</code> <code class="n">JButton</code><code class="o">(</code><code class="s">"four"</code><code class="o">),</code> <code class="n">x</code> <code class="o">=</code> <code class="mi">1</code><code class="o">,</code> <code class="n">y</code> <code class="o">=</code> <code class="mi">1</code><code class="o">);</code>
<code class="n">constraints</code><code class="o">.</code><code class="na">gridwidth</code> <code class="o">=</code> <code class="mi">1</code><code class="o">;</code> <code class="c1">// set it back</code>
<code class="o">}</code>
<code class="kt">void</code> <code class="nf">addGB</code><code class="o">(</code><code class="n">Component</code> <code class="n">component</code><code class="o">,</code> <code class="kt">int</code> <code class="n">x</code><code class="o">,</code> <code class="kt">int</code> <code class="n">y</code><code class="o">)</code> <code class="o">{</code>
<code class="n">constraints</code><code class="o">.</code><code class="na">gridx</code> <code class="o">=</code> <code class="n">x</code><code class="o">;</code>
<code class="n">constraints</code><code class="o">.</code><code class="na">gridy</code> <code class="o">=</code> <code class="n">y</code><code class="o">;</code>
<code class="n">add</code><code class="o">(</code><code class="n">component</code><code class="o">,</code> <code class="n">constraints</code><code class="o">);</code>
<code class="o">}</code>
<code class="kd">public</code> <code class="kd">static</code> <code class="kt">void</code> <code class="nf">main</code><code class="o">(</code><code class="n">String</code><code class="o">[]</code> <code class="n">args</code><code class="o">)</code> <code class="o">{</code>
<code class="n">JFrame</code> <code class="n">frame</code> <code class="o">=</code> <code class="k">new</code> <code class="n">JFrame</code><code class="o">(</code><code class="s">"GridBag3"</code><code class="o">);</code>
<code class="n">frame</code><code class="o">.</code><code class="na">setDefaultCloseOperation</code><code class="o">(</code> <code class="n">JFrame</code><code class="o">.</code><code class="na">EXIT_ON_CLOSE</code> <code class="o">);</code>
<code class="n">frame</code><code class="o">.</code><code class="na">setSize</code><code class="o">(</code><code class="mi">200</code><code class="o">,</code> <code class="mi">200</code><code class="o">);</code>
<code class="n">frame</code><code class="o">.</code><code class="na">setLocation</code><code class="o">(</code><code class="mi">200</code><code class="o">,</code> <code class="mi">200</code><code class="o">);</code>
<code class="n">frame</code><code class="o">.</code><code class="na">setContentPane</code><code class="o">(</code><code class="k">new</code> <code class="n">GridBag3</code><code class="o">());</code>
<code class="n">frame</code><code class="o">.</code><code class="na">setVisible</code><code class="o">(</code><code class="kc">true</code><code class="o">);</code>
<code class="o">}</code>
<code class="o">}</code></pre><div class="figure"><a id="learnjava3-CHP-19-FIG-9"/><div class="figure-contents"><div class="mediaobject"><a id="I_19_tt1126"/><img src="httpatomoreillycomsourceoreillyimages1707686.png" alt="Making components span rows and columns"/></div></div><p class="title">Figure 19-9. Making components span rows and columns</p></div><p>The size of each element is controlled by the <code class="literal">gridwidth</code> and <code class="literal">gridheight</code> values of its constraints. For
button one, we set <code class="literal">gridheight</code> to
<code class="literal">2</code>; therefore, it is two cells high.
Its <code class="literal">gridx</code> and <code class="literal">gridy</code> positions are both <code class="literal">0</code>, so it occupies cell (0,0) and the cell
directly below it, (0,1). Likewise, button four has a <code class="literal">gridwidth</code> of <code class="literal">2</code> and a <code class="literal">gridheight</code> of <code class="literal">1</code>, so it occupies two cells horizontally. We
place this button in cell (1,1), so it occupies that cell and its
neighbor, (2,1).</p><p>In this example, we set the <code class="literal">fill</code> to <code class="literal">BOTH</code> and <code class="literal">weightx</code> and <code class="literal">weighty</code> to <code class="literal">1</code> for all components. By doing so, we tell
each button to occupy all the space available and give them all equal
weighting. Strictly speaking, this isn’t necessary. However, it makes it
easier to see exactly how much space each button occupies.<a id="I_indexterm19_id807399" class="indexterm"/><a id="I_indexterm19_id807406" class="indexterm"/><a id="I_indexterm19_id807413" class="indexterm"/><a id="I_indexterm19_id807420" class="indexterm"/></p></div><div class="sect2" title="Weighting"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-19-SECT-6.5"/>Weighting</h2></div></div></div><p><a id="idx11061" class="indexterm"/> <a id="idx11076" class="indexterm"/> <a id="idx11081" class="indexterm"/>The <a id="I_indexterm19_id807472" class="indexterm"/><code class="literal">weightx</code> and <a id="I_indexterm19_id807483" class="indexterm"/><code class="literal">weighty</code> variables of a
<code class="literal">GridBagConstraints</code> object determine
how “extra” space in the container is distributed among the columns or
rows in the layout. As long as you keep things simple, the effect these
variables have is fairly intuitive: the larger the weight, the greater
the amount of space allocated to the component, relative to its peers.
<a class="xref" href="ch19s06.html#learnjava3-CHP-19-FIG-10" title="Figure 19-10. Using weight to control component size">Figure 19-10</a> shows what happens if we
vary the <code class="literal">weightx</code> constraint from
<code class="literal">0.1</code> to <code class="literal">1.0</code> as we place three buttons in a row.</p><p>Here’s the code:</p><a id="I_19_tt1127"/><pre class="programlisting"> <code class="c1">//file: GridBag4.java</code>
<code class="kn">import</code> <code class="nn">java.awt.*</code><code class="o">;</code>
<code class="kn">import</code> <code class="nn">java.awt.event.*</code><code class="o">;</code>
<code class="kn">import</code> <code class="nn">javax.swing.*</code><code class="o">;</code>
<code class="kd">public</code> <code class="kd">class</code> <code class="nc">GridBag4</code> <code class="kd">extends</code> <code class="n">JPanel</code> <code class="o">{</code>
<code class="n">GridBagConstraints</code> <code class="n">constraints</code> <code class="o">=</code> <code class="k">new</code> <code class="n">GridBagConstraints</code><code class="o">();</code>
<code class="kd">public</code> <code class="nf">GridBag4</code><code class="o">()</code> <code class="o">{</code>
<code class="n">setLayout</code><code class="o">(</code><code class="k">new</code> <code class="n">GridBagLayout</code><code class="o">());</code>
<code class="n">constraints</code><code class="o">.</code><code class="na">fill</code> <code class="o">=</code> <code class="n">GridBagConstraints</code><code class="o">.</code><code class="na">BOTH</code><code class="o">;</code>
<code class="n">constraints</code><code class="o">.</code><code class="na">weighty</code> <code class="o">=</code> <code class="mf">1.0</code><code class="o">;</code>
<code class="kt">int</code> <code class="n">x</code><code class="o">,</code> <code class="n">y</code><code class="o">;</code> <code class="c1">// for clarity</code>
<code class="n">constraints</code><code class="o">.</code><code class="na">weightx</code> <code class="o">=</code> <code class="mf">0.1</code><code class="o">;</code>
<code class="n">addGB</code><code class="o">(</code><code class="k">new</code> <code class="n">JButton</code><code class="o">(</code><code class="s">"one"</code><code class="o">),</code> <code class="n">x</code> <code class="o">=</code> <code class="mi">0</code><code class="o">,</code> <code class="n">y</code> <code class="o">=</code> <code class="mi">0</code><code class="o">);</code>
<code class="n">constraints</code><code class="o">.</code><code class="na">weightx</code> <code class="o">=</code> <code class="mf">0.5</code><code class="o">;</code>
<code class="n">addGB</code><code class="o">(</code><code class="k">new</code> <code class="n">JButton</code><code class="o">(</code><code class="s">"two"</code><code class="o">),</code> <code class="o">++</code><code class="n">x</code><code class="o">,</code> <code class="n">y</code><code class="o">);</code>
<code class="n">constraints</code><code class="o">.</code><code class="na">weightx</code> <code class="o">=</code> <code class="mf">1.0</code><code class="o">;</code>
<code class="n">addGB</code><code class="o">(</code><code class="k">new</code> <code class="n">JButton</code><code class="o">(</code><code class="s">"three"</code><code class="o">),</code> <code class="o">++</code><code class="n">x</code><code class="o">,</code> <code class="n">y</code><code class="o">);</code>
<code class="o">}</code>
<code class="kt">void</code> <code class="nf">addGB</code><code class="o">(</code><code class="n">Component</code> <code class="n">component</code><code class="o">,</code> <code class="kt">int</code> <code class="n">x</code><code class="o">,</code> <code class="kt">int</code> <code class="n">y</code><code class="o">)</code> <code class="o">{</code>
<code class="n">constraints</code><code class="o">.</code><code class="na">gridx</code> <code class="o">=</code> <code class="n">x</code><code class="o">;</code>
<code class="n">constraints</code><code class="o">.</code><code class="na">gridy</code> <code class="o">=</code> <code class="n">y</code><code class="o">;</code>
<code class="n">add</code><code class="o">(</code><code class="n">component</code><code class="o">,</code> <code class="n">constraints</code><code class="o">);</code>
<code class="o">}</code>
<code class="kd">public</code> <code class="kd">static</code> <code class="kt">void</code> <code class="nf">main</code><code class="o">(</code><code class="n">String</code><code class="o">[]</code> <code class="n">args</code><code class="o">)</code> <code class="o">{</code>
<code class="n">JFrame</code> <code class="n">frame</code> <code class="o">=</code> <code class="k">new</code> <code class="n">JFrame</code><code class="o">(</code><code class="s">"GridBag4"</code><code class="o">);</code>
<code class="n">frame</code><code class="o">.</code><code class="na">setDefaultCloseOperation</code><code class="o">(</code> <code class="n">JFrame</code><code class="o">.</code><code class="na">EXIT_ON_CLOSE</code> <code class="o">);</code>
<code class="n">frame</code><code class="o">.</code><code class="na">setSize</code><code class="o">(</code><code class="mi">300</code><code class="o">,</code> <code class="mi">100</code><code class="o">);</code>
<code class="n">frame</code><code class="o">.</code><code class="na">setLocation</code><code class="o">(</code><code class="mi">200</code><code class="o">,</code> <code class="mi">200</code><code class="o">);</code>
<code class="n">frame</code><code class="o">.</code><code class="na">setContentPane</code><code class="o">(</code><code class="k">new</code> <code class="n">GridBag4</code><code class="o">());</code>
<code class="n">frame</code><code class="o">.</code><code class="na">setVisible</code><code class="o">(</code><code class="kc">true</code><code class="o">);</code>
<code class="o">}</code>
<code class="o">}</code></pre><div class="figure"><a id="learnjava3-CHP-19-FIG-10"/><div class="figure-contents"><div class="mediaobject"><a id="I_19_tt1128"/><img src="httpatomoreillycomsourceoreillyimages1707687.png.jpg" alt="Using weight to control component size"/></div></div><p class="title">Figure 19-10. Using weight to control component size</p></div><p>The specific values of the weights are not meaningful; it is only
their relative proportions that matter. After the preferred sizes of the
components (including padding and insets—see the next section) are
determined, any extra space is doled out in proportion to the
component’s weights. For example, if each of our three components had
the same weight, each would receive a third of the extra space. To make
this more obvious, you may prefer to express the weights for a row or
column as fractions totaling 1.0—for example: 0.25, 0.25, 0.50.
Components with a weight of <code class="literal">0</code> receive
no extra space.</p><p>The situation is a bit more complicated when there are multiple
rows or columns and when there is even the possibility of components
spanning more than one cell. In the general case, <code class="literal">GridBagLayout</code> calculates an effective overall
weight for each row and column and then distributes the extra space to
them proportionally. Note that the previous single-row example is just a
special case where the columns each have one component. The gory details
of the calculations follow.</p><div class="sect3" title="Calculating the weights of rows and columns"><div class="titlepage"><div><div><h3 class="title"><a id="learnjava3-CHP-19-SECT-6.5.1"/>Calculating the weights of rows and columns</h3></div></div></div><p>For a given row or column (“rank”), <code class="literal">GridBagLayout</code> first considers the weights of
all the components contained strictly within that rank—ignoring those
that span more than one cell. The greatest individual weight becomes
the overall weight of the row or column. Intuitively, this means that
<code class="literal">GridBagLayout</code> is trying to
accommodate the needs of the weightiest component in that rank.</p><p>Next, <code class="literal">GridBagLayout</code> considers
the components that occupy more than one cell and things get a little
weird. <code class="literal">GridbagLayout</code> wants to
evaluate them to see whether they affect the determination of the
largest weight in a row or column. However, because these components
occupy more than one cell, <code class="literal">GridBagLayout</code> divides their weight among the
ranks (rows or columns) that they span.</p><p><code class="literal">GridBagLayout</code> tries to
calculate an effective weight for the portion of the component that
occupies each row or column. It does this by trying to divide the
weight of the component among the ranks in the same proportions that
the length (or height) of the component will be shared by the ranks.
But how does it know what the proportions will be before the whole
grid is determined? That’s what it’s trying to calculate, after all.
It simply guesses based on the row or column weights already
determined. <code class="literal">GridBagLayout</code> uses the
weights determined by the first round of calculations to split up the
weight of the component over the ranks that it occupies. For each row
or column, it then considers that fraction of the weight to be the
component’s weight for that rank. That weight then contends for the
“heaviest weight” in the row or column, possibly changing the overall
weight of that row or column, as we described earlier.<a id="I_indexterm19_id807674" class="indexterm"/><a id="I_indexterm19_id807681" class="indexterm"/><a id="I_indexterm19_id807688" class="indexterm"/></p></div></div><div class="sect2" title="Anchoring"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-19-SECT-6.6"/>Anchoring</h2></div></div></div><p><a id="idx11043" class="indexterm"/> <a id="idx11053" class="indexterm"/> <a id="idx11068" class="indexterm"/>If a component is smaller than the space available for it,
it is centered by default. But centering isn’t the only possibility. The
<code class="literal">anchor</code> constraint tells a grid bag
layout how to position a component within its cell in the grid. Possible
values are <a id="I_indexterm19_id807750" class="indexterm"/><code class="literal">GridBagConstraints.CENTER</code>, <a id="I_indexterm19_id807763" class="indexterm"/><code class="l