UNPKG

epubjs

Version:

Render ePub documents in the browser, across many devices

319 lines (303 loc) 89.8 kB
<?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