SimpleJXTableDemo.java
上传用户:zhengdagz
上传日期:2014-03-06
资源大小:1956k
文件大小:16k
源码类别:

xml/soap/webservice

开发平台:

Java

  1. /*
  2.  * SimpleJXTableDemo.java is a 1.4 application that requires no other files. It is derived from
  3.  * SimpleTableDemo in the Swing tutorial.
  4.  */
  5. package org.jdesktop.demo.sample;
  6. import java.awt.BorderLayout;
  7. import java.awt.Color;
  8. import javax.swing.JFrame;
  9. import javax.swing.JPanel;
  10. import javax.swing.JScrollPane;
  11. import java.awt.Dimension;
  12. import java.awt.FlowLayout;
  13. import java.awt.event.ActionEvent;
  14. import java.beans.PropertyChangeEvent;
  15. import java.beans.PropertyChangeListener;
  16. import java.io.InputStreamReader;
  17. import java.io.LineNumberReader;
  18. import java.net.URL;
  19. import java.util.Comparator;
  20. import java.util.Enumeration;
  21. import java.util.Iterator;
  22. import java.util.regex.Pattern;
  23. import javax.swing.AbstractAction;
  24. import javax.swing.JButton;
  25. import javax.swing.JCheckBox;
  26. import javax.swing.JTextField;
  27. import javax.swing.ListSelectionModel;
  28. import javax.swing.table.DefaultTableModel;
  29. import javax.swing.table.TableColumn;
  30. import org.jdesktop.swingx.JXTable;
  31. import org.jdesktop.swingx.action.AbstractActionExt;
  32. import org.jdesktop.swingx.decorator.AlternateRowHighlighter;
  33. import org.jdesktop.swingx.decorator.Filter;
  34. import org.jdesktop.swingx.decorator.FilterPipeline;
  35. import org.jdesktop.swingx.decorator.Highlighter;
  36. import org.jdesktop.swingx.decorator.HighlighterPipeline;
  37. import org.jdesktop.swingx.decorator.PatternFilter;
  38. import org.jdesktop.swingx.decorator.RolloverHighlighter;
  39. import org.jdesktop.swingx.decorator.Sorter;
  40. import org.jdesktop.swingx.table.TableColumnExt;
  41. /**
  42.  * This SimpleJXTableDemo is a very simple example of how to use the extended features of the
  43.  * JXTable in the SwingX project. The major features are covered, step-by-step. You can run
  44.  * this demo from the command-line without arguments
  45.  * java org.jdesktop.demo.sample.SimpleJXTableDemo
  46.  *
  47.  * If looking at the source, the interesting code is in configureJXTable().
  48.  *
  49.  * This is derived from the SimpleTableDemo in the Swing tutorial.
  50.  *
  51.  * @author Patrick Wright (with help from the Swing tutorial :))
  52.  */
  53. public class SimpleJXTableDemo extends JPanel {
  54.     public SimpleJXTableDemo() {
  55.         super(new BorderLayout());
  56.         initUI();
  57.     }
  58.     
  59.     private void initUI() {
  60.         JXTable jxTable = initTable();
  61.         configureJXTable(jxTable);
  62.         
  63.         //Create the scroll pane and add the table to it.
  64.         JScrollPane scrollPane = new JScrollPane(jxTable);
  65.         
  66.         //Add the scroll pane to this panel.
  67.         add(scrollPane, BorderLayout.CENTER);
  68.         
  69.         // add our search panel
  70.         // TODO: not ready yet
  71.         // add(initSearchPanel(jxTable), BorderLayout.NORTH);
  72.         add(initConfigPanel(jxTable), BorderLayout.NORTH);
  73.     }
  74.     
  75.     /** Initialize our JXTable; this is standard stuff, just as with JTable */
  76.     private JXTable initTable() {
  77.         // boilerplate table-setup; this would be the same for a JTable
  78.         SampleTableModel model = new SampleTableModel();
  79.         JXTable table = new JXTable(model);
  80.         model.loadData();
  81.         table.setPreferredScrollableViewportSize(new Dimension(500, 70));
  82.         
  83.         table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
  84.         return table;
  85.     }
  86.     
  87.     /** For demo purposes, the special features of the JXTable are configured here. There is
  88.      * otherwise no reason not to do this in initTable().
  89.      */
  90.     private void configureJXTable(JXTable jxTable) {
  91.         // This shows the column control on the right-hand of the header.
  92.         // All there is to it--users can now select which columns to view
  93.         jxTable.setColumnControlVisible(true);
  94.         
  95.         // our data is pulling in too many columns by default, so let's hide some of them
  96.         // column visibility is a property of the TableColumnExt class; we can look up a
  97.         // TCE using a column's display name or its index
  98.         TableColumnExt latitude = jxTable.getColumnExt("LATITUDE");
  99.         latitude.setVisible(false);
  100.         jxTable.getColumnExt("LONGITUDE").setVisible(false);
  101.         jxTable.getColumnExt("DEWPOINT").setVisible(false);
  102.         jxTable.getColumnExt("VISIBILITY").setVisible(false);
  103.         jxTable.getColumnExt("WIND_SPEED").setVisible(false);
  104.         jxTable.getColumnExt("GUST_SPEED").setVisible(false);
  105.         jxTable.getColumnExt("VISIBILITY_QUAL").setVisible(false);
  106.         jxTable.getColumnExt("WIND_DIR").setVisible(false);
  107.         jxTable.getColumnExt("WIND_DEG").setVisible(false);
  108.         jxTable.getColumnExt("REGION").setVisible(false);
  109.         
  110.         
  111.         // note that now, getColumnExt() will fail for any of these columns we have hidden
  112.         // JW: changed to api to not fail
  113.         try {
  114.             jxTable.getColumnExt("LATITUDE");
  115.         } catch (Exception e) {
  116.             // we expect this to happen
  117.             // ignore
  118.         }
  119.         
  120.         // however, if we still have the TableColumnExt we can change our mind
  121.         latitude.setVisible(true);
  122.         
  123.         // now we can change the remaining column titles. This is a convenience for calling
  124.         // setHeaderValue() on a TableColumn.
  125.         //
  126.         // We'll do a trick, though, and that is to set the identifiers of each column
  127.         // to their current header value, so we can still use the same names for identifiers
  128.         // in the rest of our code
  129.         
  130.         // First, a trick: by default, the "identifier" for a TableColumn is actually null
  131.         // unless we specifically set it; the header value is used instead. By doing this get,
  132.         // we're pulling the header value, and setting that as the identifier; then we can
  133.         // change the header value independently. This could also be done in creating the
  134.         // TableModel, of course.
  135. //        Enumeration en = jxTable.getColumnModel().getColumns();
  136. //        while ( en.hasMoreElements() ) {
  137. //            TableColumn tc = (TableColumn)en.nextElement();
  138. //            tc.setIdentifier(tc.getIdentifier());
  139. //        }
  140. //        
  141. //
  142. //        // ...and now change the titles
  143. //        int c = jxTable.getColumnCount();
  144. //        for ( int i=0; i < c; i++ ) {
  145. //            TableColumnExt tce = jxTable.getColumnExt(i);
  146. //            String title = tce.getTitle();
  147. //            title = title.substring(0,1).toUpperCase() + title.substring(1).toLowerCase();
  148. //            title.replace('_', ' ');
  149. //            tce.setTitle(title);
  150. //        }
  151.         //JW: use new api to access visible and invisible columns
  152.         // there's a slight catch: the getColumns does not (cannot) guarantee
  153.         // that the elements are of type TableColumnExt
  154.         for (Iterator iter = jxTable.getColumns(true).iterator(); iter.hasNext();) {
  155.             TableColumnExt column = (TableColumnExt) iter.next();
  156.             column.setIdentifier(column.getIdentifier());
  157.             // ...and now change the title
  158.             String title = column.getTitle();
  159.             title = title.substring(0,1).toUpperCase() + title.substring(1).toLowerCase();
  160.             title.replace('_', ' ');
  161.             column.setTitle(title);
  162.         }
  163.         // Sorting by clicking on column headers is on by default. However, the comparison
  164.         // between rows uses a default compare on the column's type, and elevations
  165.         // are not sorting how we want.
  166.         //
  167.         // We will override the Comparator assigned to the Sorter instance assigned
  168.         // to the elevation column. Every column has a Sorter using a default Comparator.
  169.         // By using a custom Comparator we can control how sorting in any column takes place
  170.         Comparator numberComparator = new Comparator() {
  171.             public int compare(Object o1, Object o2) {
  172.                 Double d1 = Double.valueOf(o1 == null ? "0" : (String)o1);
  173.                 Double d2 = Double.valueOf(o2 == null ? "0" : (String)o2);
  174.                 return d1.compareTo(d2);
  175.             }
  176.         };
  177.         // First, the long way to assign--just to show there's a Sorter involved
  178.         Sorter sorter = jxTable.getColumnExt("ELEVATION").getSorter();
  179.         sorter.setComparator(numberComparator);
  180.         
  181.         // and, shorthand
  182.         jxTable.getColumnExt("TEMPERATURE").getSorter().setComparator(numberComparator);
  183.         
  184.         // comparators are good for special situations where the default comparator doesn't
  185.         // understand our data.
  186.         
  187.         // This turns horizontal scrolling on or off. If the table is too large for the scrollpane,
  188.         // and horizontal scrolling is off, columns will be resized to fit within the pane, which can
  189.         // cause them to be unreadable. Setting this flag causes the table to be scrollable right to left.
  190.         jxTable.setHorizontalScrollEnabled(false);
  191.         
  192.         // We'll add a highlighter to offset different row numbers
  193.         // Note the setHighlighters() takes an array parameter; you can chain these together.
  194.         jxTable.setHighlighters(new HighlighterPipeline(new Highlighter[]{ AlternateRowHighlighter.classicLinePrinter }));
  195.         
  196.         // ...oops! we forgot one
  197.         jxTable.getHighlighters().addHighlighter(new RolloverHighlighter(Color.BLACK, Color.WHITE ));
  198.         jxTable.setRolloverEnabled(true);
  199.         
  200.         // add a filter: include countries starting with a only
  201.         int col = jxTable.getColumn("COUNTRY").getModelIndex();
  202.         jxTable.setFilters(new FilterPipeline(new Filter[] { new PatternFilter("^A", 0, col) }));
  203.         
  204.         // resize all the columns in the table to fit their contents
  205.         // this is available as an item in the column control drop down as well, so the user can trigger it.
  206.         int margin = 5;
  207.         jxTable.packTable(margin);
  208.         
  209.         // we want the country name to always show, so we'll repack just that column
  210.         // we can set a max size; if -1, the column is forced to be as large as necessary for the
  211.         // text
  212.         margin = 10;
  213.         int max = -1;
  214.         // JW: don't - all column indices are view coordinates
  215.         // JW: maybe we need xtable api to take a TableColumn as argument?
  216.         //jxTable.packColumn(jxTable.getColumnExt("COUNTRY").getModelIndex(), margin, max);
  217.         int viewIndex = jxTable.convertColumnIndexToView(jxTable.getColumnExt("COUNTRY").getModelIndex());
  218.         jxTable.packColumn(viewIndex, margin, max);
  219.     }
  220.     
  221.     /** This shows off some additional JXTable configuration, controlled by checkboxes in a Panel. */
  222.     private JPanel initConfigPanel(final JXTable jxTable) {
  223.         JPanel config = new JPanel();
  224.         FlowLayout fll = (FlowLayout)config.getLayout();
  225.         fll.setAlignment(FlowLayout.LEFT);
  226.         fll.setHgap(30);
  227.         
  228.         
  229.         // This shows or hides the column control--note this is possible at runtime
  230.         final JCheckBox control = new JCheckBox();
  231.         control.setSelected(jxTable.isColumnControlVisible());
  232.         control.setAction(new AbstractAction("Show column control") {
  233.             public void actionPerformed(ActionEvent e) {
  234.                 jxTable.setColumnControlVisible(control.isSelected());
  235.             }
  236.         });
  237.         
  238.         
  239.         // turn sorting by column on or off
  240.         // bug: there is no API to read the current value! we will assume it is false
  241.         final JCheckBox sorting = new JCheckBox();
  242.         
  243.         sorting.setSelected(jxTable.isSortable());
  244.         sorting.setAction(new AbstractAction("Sortable") {
  245.             public void actionPerformed(ActionEvent e) {
  246.                 jxTable.setSortable(sorting.isSelected());
  247.             }
  248.         });
  249.         
  250.         // add checkbox for horizontal scrolling. basically, the table has an action for this,
  251.         // and we need to link the checkbox up in both directions--so that if the property changes
  252.         // the checkbox is updated, and vice-versa. we use an AbstractActionExt to make this easier.
  253.         // you aren't supposed to understand this :) and yes, it will be refactored
  254.         final JCheckBox horiz = new JCheckBox();
  255.         
  256.         AbstractActionExt hA = (AbstractActionExt)jxTable.getActionMap().get(jxTable.HORIZONTALSCROLL_ACTION_COMMAND);
  257.         hA.addPropertyChangeListener(new PropertyChangeListener(){
  258.             public void propertyChange(PropertyChangeEvent evt) {
  259.                 String propertyName = evt.getPropertyName();
  260.                 
  261.                 if (propertyName.equals("selected")) {
  262.                     Boolean selected = (Boolean)evt.getNewValue();
  263.                     horiz.setSelected(selected.booleanValue());
  264.                 }
  265.             }
  266.         });
  267.         horiz.addItemListener(hA);
  268.         horiz.setAction(hA);
  269.         
  270.         config.add(control);
  271.         config.add(sorting);
  272.         config.add(horiz);
  273.         return config;
  274.     }
  275.     /** TODO: this is not working, need to figure out how PatternFilter is applied. */
  276.     private JPanel initSearchPanel(final JXTable jxTable) {
  277.         JPanel search = new JPanel();
  278.         final JButton filter = new JButton("Show");
  279.         final JButton reset = new JButton("Clear");
  280.         
  281.         final JTextField text = new JTextField("");
  282.         text.setColumns(30);
  283.         
  284.         filter.setAction(new AbstractAction("Show") {
  285.             FilterPipeline fp = null;
  286.             PatternFilter pf = new PatternFilter();
  287.             boolean isAdded = false;
  288.             
  289.             public void actionPerformed(ActionEvent e) {
  290.                 
  291.                 String searchString = text.getText().trim();
  292.                 if ( searchString.length() > 0 ) {
  293.                     pf.setPattern(Pattern.compile(searchString));
  294.                     if ( ! isAdded ) {
  295.                         fp = new FilterPipeline(new Filter[]{ pf });
  296.                         jxTable.setFilters(fp);
  297.                         isAdded = true;
  298.                     }
  299.                 }
  300.             }
  301.         });
  302.         
  303.         
  304.         search.add(text);
  305.         search.add(filter);
  306.         search.add(reset);
  307.         
  308.         return search;
  309.     }
  310.     
  311.     /**
  312.      * Create the GUI and show it.  For thread safety,
  313.      * this method should be invoked from the
  314.      * event-dispatching thread.
  315.      */
  316.     private static void createAndShowGUI() {
  317.         //Make sure we have nice window decorations.
  318.         JFrame.setDefaultLookAndFeelDecorated(true);
  319.         
  320.         //Create and set up the window.
  321.         JFrame frame = new JFrame("SimpleTableDemo");
  322.         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  323.         
  324.         //Create and set up the content pane.
  325.         SimpleJXTableDemo newContentPane = new SimpleJXTableDemo();
  326.         newContentPane.setOpaque(true); //content panes must be opaque
  327.         frame.setContentPane(newContentPane);
  328.         
  329.         //Display the window.
  330.         frame.pack();
  331.         frame.setSize(1024, 768);
  332.         frame.setVisible(true);
  333.     }
  334.     
  335.     public static void main(String[] args) {
  336.         //Schedule a job for the event-dispatching thread:
  337.         //creating and showing this application's GUI.
  338.         javax.swing.SwingUtilities.invokeLater(new Runnable() {
  339.             public void run() {
  340.                 createAndShowGUI();
  341.             }
  342.         });
  343.     }
  344.     
  345.     class SampleTableModel extends DefaultTableModel {
  346.         void loadData() {
  347.             try {
  348.                 URL url = SampleTableModel.class.getResource("/org/jdesktop/demo/sample/resources/weather.txt");
  349.                 loadDataFromCSV(url);
  350.             } catch ( Exception e ) {
  351.                 e.printStackTrace();
  352.                 loadDefaultData();
  353.             }
  354.         }
  355.         
  356.         private void loadDataFromCSV(URL url) {
  357.             try {
  358.                 LineNumberReader lnr = new LineNumberReader(new InputStreamReader(url.openStream()));
  359.                 String line = lnr.readLine();
  360.                 String[] cols = line.split("t");
  361.                 for ( String col : cols ) {
  362.                     addColumn(col);
  363.                 }
  364.                 while (( line = lnr.readLine()) != null ) {
  365.                     addRow(line.split("t"));
  366.                 }
  367.             } catch ( Exception e ) {
  368.                 e.printStackTrace();
  369.                 loadDefaultData();
  370.             }
  371.         }
  372.         
  373.         private void loadDefaultData() {
  374.             int colCnt = 6;
  375.             int rowCnt = 10;
  376.             for ( int i=0; i < colCnt; i++ ) {
  377.                 addColumn("Column-" + (i + 1));
  378.             }
  379.             for ( int i=0; i <= rowCnt; i++ ) {
  380.                 String[] row = new String[colCnt];
  381.                 for ( int j=0; j < colCnt; j++ ) {
  382.                     row[j] = "Row-" + i + "Column-" + (j + 1);
  383.                 }
  384.                 addRow(row);
  385.             }
  386.         }
  387.     }
  388. }