<?xml version="1.0"?><rss version="2.0">
<channel>
  <title>Alan&#039;s Ramblings - swing tag</title>
  <link>http://bleaklow.com:80/tags/swing/</link>
  <description>My opinions may be incorrect, but they are my own</description>
  <language>en</language>
  <copyright>Alan Burlison</copyright>
  <lastBuildDate>Wed, 29 Feb 2012 20:50:00 GMT</lastBuildDate>
  <generator>Pebble (http://pebble.sourceforge.net)</generator>
  <docs>http://backend.userland.com/rss</docs>
  <image>
    <url>http://bleaklow.com/images/misc/logo.gif</url>
    <title>Alan&#039;s Ramblings</title>
    <link>http://bleaklow.com:80/</link>
  </image>
  <item>
    <title>Printing simple tabular reports with JTable</title>
    <link>http://bleaklow.com:80/2006/09/30/printing_simple_tabular_reports_with_jtable.html</link>
    <description>
          &lt;p&gt;
I&#039;ve been putting together a little Java application that required some simple tabular reports that could be both viewed on screen and printed out, the data coming from a &lt;a href=&#034;http://db.apache.org/derby/&#034;&gt;Derby&lt;/a&gt; database.  I spent quite a bit of time looking a the various libraries out there for doing this.  A lot of the libraries are commercial, which mean they were a non-starter, and to be honest I wasn&#039;t overy impressed with any of the &lt;a href=&#034;http://java-source.net/open-source/charting-and-reporting&#034;&gt;free alternatives&lt;/a&gt;.  The main ones that I looked at were &lt;a href=&#034;http://jasperforge.org/sf/projects/jasperreports&#034;&gt;Jasper Reports&lt;/a&gt; and the associated &lt;a href=&#034;http://jasperforge.org/sf/projects/ireport&#034;&gt;iReport GUI&lt;/a&gt;.  It looks OK, but although the software is free, it costs $89.95 for the documentation, which in my book makes it a commercial product, not free.  I also looked at &lt;a href=&#034;http://www.jfree.org/jfreereport/index.php&#034;&gt;JFreeReport&lt;/a&gt; and the associated &lt;a href=&#034;http://www.pentaho.com/products/reporting/&#034;&gt;Pentaho GUI&lt;/a&gt;, but it didn&#039;t support subreports and it needed an extensive list of additional libraries, which would have been much larger than my entire application.  The last one I considered was &lt;a href=&#034;http://datavision.sourceforge.net/&#034;&gt;DataVision&lt;/a&gt;, but the report building GUI was pretty awful - there was no way to align the baseline of fields for example, and you couldn&#039;t modify the generated SQL.
&lt;p&gt;
Several of the reporting tools accept a &lt;http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/table/TableModel.html&gt;TableModel&lt;/a&gt; as a source of data, so I was looking at that and the documentation for the associated &lt;a href=&#034;http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/JTable.html&#034;&gt;JTable&lt;/a&gt; Swing class, when I noticed that JTable has a &lt;a href=&#034;http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/JTable.html#print()&#034;&gt;Print()&lt;/a&gt; method, added in Java 1.5.  This takes care of all the scaling and page break management that makes Java printing such a pain, and as the data I wanted to display and print was tabular in nature, it looked like JTable might just be OK for my (admittedly simple) requirements.
&lt;p&gt;
I put together a simple form in NetBeans with a JTable in it - NetBeans wraps JTable in a JScrollPane for you when you add it to a form.  The next thing was to try to get the JTable to render as close as possible to a printed page.  I selected the JTable and modified the properties accordingly - I deselected &lt;code&gt;showHorizontalLines&lt;/code&gt; and &lt;code&gt;showVericalLines&lt;/code&gt; to remove the cell borders, and disabled &lt;code&gt;focusable&lt;/code&gt; as the table was going to be read-only I didn&#039;t want the user to be able to select cells within it.  I also didn&#039;t want the column headers that JTable displays by default - there isn&#039;t a way to disable them via the NetBeans form designer, but a call to &lt;code&gt;dataScrollPane.setColumnHeaderView(null)&lt;/code&gt; disables them.  The next problem is that if the JTable doesn&#039;t fill the entire JScrollPane which encloses it, you get a grey background in the unoccupied area.  Setting the background of the scroll pane doesn&#039;t work as there is another pane between the scroll pane and it&#039;s contained JTable, so what we need is &lt;code&gt;dataTable.getParent().setBackground(java.awt.Color.WHITE)&lt;/code&gt;.
&lt;p&gt;
The next problem is that when we display the table, all the columns are set to the default width, which means that the contents of a lot of them are truncated.  Hmm.  What we actually want is for the columns to be sized to fit the widest row that they contain, and for a horizontal scrollbar to be displayed.  Scrolling through the properties for the JTable show an property called &lt;a href=&#034;http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/JTable.html#setAutoResizeMode(int)&#034;&gt;setAutoResizeMode&lt;/a&gt; that looks like it might do what we want.  However it doesn&#039;t - there is no supported mode that sizes all columns to fit and enables the horizontal scrollbar if required.  After a lot of digging I eventually found the &lt;a href=&#034;http://www.chka.de/swing/table/cell-sizes.html&#034;&gt;answer&lt;/a&gt;.  What is required is to set the resize mode to &lt;code&gt;AUTO_RESIZE_OFF&lt;/code&gt;, which enables the horizontal scrollbar when required, and manually resize the columns so that they fit the contents.  I used a simplified version of the code provided in the above link, taking advantage of the fact that we&#039;ve already disabled the column headers:
&lt;p&gt;
&lt;pre&gt;
    private void sizeColumns(JTable table) {
        TableColumnModel columns = table.getColumnModel();
        TableModel data = table.getModel();
        int margin = columns.getColumnMargin() * 2;
        int columnCount = columns.getColumnCount();
        int rowCount = data.getRowCount();
        for (int col = 0; col &amp;lt; columnCount; col++) {
            TableColumn column = columns.getColumn(col);
            int modelCol = column.getModelIndex();
            int width = 0;
            for (int row = 0; row &amp;lt; rowCount; row++) {
                TableCellRenderer r = table.getCellRenderer(row, col);
                int w = r.getTableCellRendererComponent(
                  table, data.getValueAt(row, modelCol), false, false, row, col)
                  .getPreferredSize().width;
                if (w &amp;gt; width) {
                    width = w;
                }
            }
            column.setPreferredWidth(width + margin);
        }
    }
&lt;/pre&gt;
&lt;p&gt;
Perfect.  The resulting table looks just as I want, and printing it is a snap:
&lt;p&gt;
&lt;pre&gt;
    try {
        dataTable.print(JTable.PrintMode.FIT_WIDTH,
          new MessageFormat(title),
           new MessageFormat(&#034;Page {0}&#034;));
    } catch (PrinterException e) {
        Main.handleException(this, &#034;Printing failed&#034;, e, null, false);
    }
&lt;/pre&gt;
&lt;p&gt;
The last trick is an easy way of changing text attributes in the contents of the cells.  We can take advantage of the fact that text cells in a JTable are rendered with a JLabel, and that a JLabel&#039;s contents can be HTML.  So, if for example we want an underlined cell we can just wrap the cell&#039;s contents in &lt;code&gt;&amp;lt;html&amp;gt;&amp;lt;u&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;/u&amp;gt;&amp;lt;/html&amp;gt;&lt;/code&gt;.  We can also do the same for bold, but taking it much further isn&#039;t advisable as the height of the cells won&#039;t adjust to fit.
&lt;p&gt;</description>
      <category>Tech</category>
    <category>Java</category>
    <comments>http://bleaklow.com:80/2006/09/30/printing_simple_tabular_reports_with_jtable.html#comments</comments>
    <guid isPermaLink="true">http://bleaklow.com:80/2006/09/30/printing_simple_tabular_reports_with_jtable.html</guid>
    <pubDate>Sat, 30 Sep 2006 02:33:09 GMT</pubDate>
  </item>
  <item>
    <title>JSlider oddity - setFont() is ignored</title>
    <link>http://bleaklow.com:80/2006/02/14/jslider_oddity_setfont_is_ignored.html</link>
    <description>
          &lt;p&gt;
Despite what you might expect, the labels on a JSlider ignore any font that you specify with setFont(), at least in the Windows L&amp;F.  Most odd.
&lt;p&gt;</description>
      <category>Java</category>
    <comments>http://bleaklow.com:80/2006/02/14/jslider_oddity_setfont_is_ignored.html#comments</comments>
    <guid isPermaLink="true">http://bleaklow.com:80/2006/02/14/jslider_oddity_setfont_is_ignored.html</guid>
    <pubDate>Tue, 14 Feb 2006 03:21:11 GMT</pubDate>
  </item>
  </channel>
</rss>

