标签页中的JScrollPanes中的MigLayout和JTable

时间:2012-04-12 23:34:54

标签: jtable miglayout jscrollbar

我本着回馈的精神提交以下实施的组件。该组件满足了我的客户的要求,所以我本身并不是在寻求帮助。但该组件提供了可能对其他人有用的有趣功能。

此外,它提出了一些关于显然必要的黑客攻击的问题,而且我的实施可能比必要的复杂得多。任何建议的替代解决方案也可能对其他人有用。

简而言之,一个大型数据表被拆分为多个JTable,每个页面中有一个JTTPane。

如果您运行程序并以各种方式调整大小,您将看到该组件应该如何表现。明确地,要求是:

  1. 将显示具有不同记录数(1到500)的表格数据集。

  2. JTabbedPane包含一个或多个标签,每个标签只包含一个JScrollPane。

  3. JScrollPanes不能有垂直滚动条,可能有水平滚动条。

  4. 每个JScrollPane都包含一个JTable。

  5. JTabbedPane中总是有足够的选项卡来共同包含其JTable中的所有数据行。

  6. JTabbedPane大小因应用程序JFrame大小而异。

  7. 可以使用鼠标拖动来自由调整应用程序的大小。

  8. 在初始化时,每当应用程序调整大小时,JTabbedPane都会重建,只有足够的标签页来保存所有记录。例如。对于100条记录,如果在特定的面板大小,标签的表可以容纳8条记录,则会创建13个标签。

  9. 如果JTabbedPane的大小减小到太小而无法容纳保存所有数据行所需的标签数量,则不显示任何内容(或仅显示警告)。

  10. 对Java,MigLayout及其互动有学术兴趣的人可能会考虑以下四点:

    1. 源代码中的某一点是以下函数调用:

      tb = tabbedPane.getBoundsAt(0);

    2. 这是一个黑客。我无法看到这个召唤有什么地球需要;但它(或其他)是必要的。

      1. 从理论上讲,ScrollPane.getViewportBorderBounds()应该为我提供计算标签页面大小的信息,但我不得不破解一个值。我错了,还是在我使用它时返回了错误的信息?

      2. 有一组令人眼花缭乱的函数 - paint(),repaint(),validate(),invalidate(),revalidate(),update()。我发现需要在恰当的时间调用特定的函数。通常,虽然并非总是显而易见,但呼叫顺序非常重要。这组函数可以真正使用严格但清晰的文档来描述它们与AWT,Swing以及彼此的交互。他们与布局管理人员以及特别是MigLayout的交互也可以使用解释。

      3. 是否有使用通用Java的要求的解决方案比我使用的方法简单得多?我是否重新发明了轮子,最后是用拖拉机踏板?

      4. make:javac -classpath ScrollTableTest.java

        用法:java -classpath ScrollTableTest [总数据行]

        import java.awt.*;
        import java.awt.event.*;
        import java.net.*;
        import java.util.*;
        import java.io.*;
        import java.text.*;
        import javax.swing.*;
        import javax.swing.event.*;
        import javax.swing.filechooser.*;
        import javax.swing.table.*;
        import javax.swing.table.AbstractTableModel;
        import javax.swing.table.TableModel;
        import javax.swing.table.TableColumn;
        import net.miginfocom.swing.MigLayout;
        
        public class ScrollTableTest
          extends    JFrame
        {
          public final static int APPWIDTH = 500; 
          public final static int APPHEIGHT = 300;
          public final static String[] CLIENT_COL_NAMES = { "Col 1", "Col 2", "Col 3", "Col 4" };
          public final static int COLS = CLIENT_COL_NAMES.length; 
          public final static int MAXTABS = 50; // arbitrary limit
          public final static int arbitraryTweek1 = 20;    
        
          String migDebugString = "";
        
          int[] dataRowsPerTabCount = new int [MAXTABS];
          JPanel topPane = null;
          DefaultTableModel clientsTableModel;
          String[][] clientData;
          JScrollPane scrollPane;
          Rectangle viewportBounds;
          JTable clientsTable;
          JTabbedPane tabbedPane;
          int dataRows, maxVisibleRow = -1;
          int rowsToShow = 1;
          int dataRowHeight;
        
          void printBasics()
          {
            if (scrollPane == null)
              return;
            System.out.println("");
            System.out.println("clientsTable height " + clientsTable.getHeight());
            System.out.println("topPane height:  " + topPane.getHeight());
            System.out.println("tabbedPane height " + tabbedPane.getHeight());
            System.out.println("scrollPane height:  " + scrollPane.getHeight());
            System.out.println("viewport bounds:  y " + viewportBounds.getY() +
                  " height " + (int)viewportBounds.getHeight());
          }
          void printDims()
          {
            printBasics();
            double diff = viewportBounds.getHeight() - clientsTable.getHeight();
            System.out.println("dataRowHeight: " + dataRowHeight);
            System.out.println("differential:  " + diff);
          }
          void getGuiMetrics()
          {
            double diff;
            Rectangle tb;
            int clientRows = 20;
            int viewable = 0;
            int bottom;
            int computedSpHeight;
            int tabIx;
            boolean scrollbarHeightSet = false;
            int scrollbarHeight = 0;
            String title;
            topPane = new JPanel(new MigLayout("fill" + migDebugString, "[100%]", "[100%]"));
            setContentPane(topPane);
            validate();
        
            tabbedPane = new JTabbedPane();
            topPane.add(tabbedPane, "cell 0 0, grow");
        
            // create a temporary table of nominal size to use for table metrics
            clientData = new String[clientRows][COLS];
            clientsTableModel = new DefaultTableModel(clientData, CLIENT_COL_NAMES);
            clientsTable = new JTable(clientRows, COLS);
            clientsTable.setModel(clientsTableModel);
            clientsTable.setPreferredScrollableViewportSize(null);
            clientsTable.getTableHeader().setReorderingAllowed(false);
            clientsTable.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
            clientsTable.getSelectionModel().setSelectionInterval(0, 0);
        
            // created scroll pane containing table, and contained in tabbed pane
            scrollPane = new JScrollPane(clientsTable);
            scrollPane.setVerticalScrollBarPolicy(scrollPane.VERTICAL_SCROLLBAR_NEVER);
            scrollPane.setHorizontalScrollBarPolicy(scrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
            tabbedPane.setMaximumSize(new Dimension(topPane.getWidth(),  topPane.getHeight() - arbitraryTweek1));
        
            // For the entire allowed range of tabbed pages, calculate the area
            // within the tabbed pane available to hold a table.
            for (tabIx = 0; tabIx < MAXTABS; ++tabIx)
            {
              JPanel panel = new JPanel(new MigLayout("fill" + migDebugString, "[100%]", "[100%]"));
              title = "Page " + (tabIx +1);
              tabbedPane.addTab(title, panel);
              panel.add(scrollPane, "cell 0 0, grow");
              if (tabIx == 0)
              {
                validate();
                dataRowHeight = clientsTable.getHeight() / clientRows;
              }
              else
                tabbedPane.revalidate();
        
              // we need to know how high the hz scrollbar is 
              if (!scrollbarHeightSet)
              {
                JScrollBar hzScrollBar = scrollPane.getHorizontalScrollBar();
                if (hzScrollBar != null)
                  scrollbarHeight = hzScrollBar.getHeight();
                else
                  scrollbarHeight = 0;
                scrollbarHeightSet = true;
              }
              // pick one
              boolean useViewport = false;
              boolean compViewport = false;
              boolean compViewport2 = true; // this one works best.
        
              // this presumptively correct method barely works
              if (useViewport)
              {
                viewportBounds = scrollPane.getViewportBorderBounds();
                viewable = ((int)viewportBounds.getHeight()) / dataRowHeight;
              }
              // this hack works better
              if (compViewport) 
              {
                tb = tabbedPane.getBoundsAt(0);
                bottom = (int)(tb.getY() + tb.getHeight());
                computedSpHeight = tabbedPane.getHeight() - (dataRowHeight + bottom);
                viewable = (computedSpHeight - scrollbarHeight) / dataRowHeight;
              }
              // this works well.  But what does JTabbedPane.getBoundsAt() have to do with it?
              if (compViewport2)
              {
                tb = tabbedPane.getBoundsAt(0); // !!! Worse Than Failure - this must be here!
                viewable = (scrollPane.getHeight() - scrollbarHeight) / dataRowHeight;
              }
              if (viewable > 0)
                viewable -= 1; // take out the title row
        
              dataRowsPerTabCount[tabIx] = viewable;
            }      
          } // getGuiMetrics
        
          void updateTable()
          {
            int tabIx, numTabs, rowsPerTab = 0, maxDisplayableRows = 0, rowsAdded, rowsThisTime;
            boolean accepted = false;
        
            getGuiMetrics();
        
            topPane = new JPanel(new MigLayout("fill" + migDebugString, "[100%]", "[100%]"));
            setContentPane(topPane);
        
            // how many tabs are needed to display all the data rows?
            for (tabIx = 0; !accepted && tabIx < MAXTABS; ++tabIx)
            {
              rowsPerTab = dataRowsPerTabCount[tabIx];
              maxDisplayableRows = rowsPerTab * (tabIx +1);
              if (maxDisplayableRows >= dataRows)
              {
                accepted = true;
                numTabs = tabIx +1;
              }
            }
            // did we find a best fit solution?
            if (!accepted)
            {
              topPane.add(new JLabel("Not enough space for all data rows"));
              return;
            }
            tabbedPane = new JTabbedPane();
            validate();
            tabbedPane.setMaximumSize(new Dimension(topPane.getWidth(),  topPane.getHeight() - arbitraryTweek1));
            topPane.add(tabbedPane, "cell 0 0, grow");
        
            // create and fill the tab pages
            for (tabIx = 0, rowsAdded = 0; rowsAdded < dataRows; ++tabIx)
            {
              if (rowsAdded + rowsPerTab > dataRows)
                rowsThisTime = dataRows - rowsAdded;
              else
                rowsThisTime = rowsPerTab;
        
              // create the table for the page
              clientData = new String[rowsThisTime][COLS];
              clientsTableModel = new DefaultTableModel(clientData, CLIENT_COL_NAMES);
              clientsTable = new JTable(rowsThisTime, COLS);
              clientsTable.setModel(clientsTableModel);
              clientsTable.setPreferredScrollableViewportSize(null);
              clientsTable.getTableHeader().setReorderingAllowed(false);
              clientsTable.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
              clientsTable.getSelectionModel().setSelectionInterval(0, 0);
        
              // fill the table with test data
              for (int row = 0; row < rowsThisTime; ++row)
              {
                for (int col = 0; col < COLS; ++col)
                {
                  String cellVal = "tab " + (tabIx +1) + " cell row " + (row+1) + " col " + (col+1);
                  clientsTableModel.setValueAt(cellVal, row, col);
                }
              }
              // create scroll pane holding table
              scrollPane = new JScrollPane(clientsTable);
              scrollPane.setVerticalScrollBarPolicy(scrollPane.VERTICAL_SCROLLBAR_NEVER);
              scrollPane.setHorizontalScrollBarPolicy(scrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
        
              // create tab panel holding the scroll pane
              JPanel panel = new JPanel(new MigLayout("fill" + migDebugString, "[100%]", "[100%]"));
              String title = "Page " + (tabIx +1);
              tabbedPane.addTab(title, panel);
              panel.add(scrollPane, "cell 0 0, grow");
        
              rowsAdded += rowsPerTab;
            }
            tabbedPane.revalidate();
          } // updateTable
        
          void init(String[] args)
          {
            //  uncomment this to see the migLayout component border highlighting
            //  migDebugString = ", debug";
        
            // total of how many data rows?
            if (args.length < 1)
            {
              dataRows = 20;
            } 
            else
            {
              dataRows = Integer.valueOf(args[0]);
              if (dataRows <= 0)
              {
                System.out.println("bad arg");
                System.exit(0);
              } 
            }
            setSize(APPWIDTH, APPHEIGHT);
            addComponentListener(new ComponentAdapter()
            {
              public void componentShown(ComponentEvent evt)
              {
              }
              public void componentHidden(ComponentEvent evt)
              {
              }
              public void componentResized(ComponentEvent evt)
              {
                updateTable();
              } // componentResized()
            }); // addComponentListener
        
            topPane = new JPanel(new MigLayout("fill" + migDebugString, "[100%]", "[100%]"));
            setContentPane(topPane);
        
            // center app window
            GraphicsConfiguration gc = getGraphicsConfiguration();
            Rectangle bounds = gc.getBounds();
            setLocation((int)((bounds.width-APPWIDTH) /2),
                                   (int)((bounds.height - APPHEIGHT) /2));
            setVisible(true);
          }
          public static void main(String[] args)
          {
            try
            {
              ScrollTableTest thisTest = new ScrollTableTest();
              thisTest.init(args);
            }
            catch (Exception e)
            {
              System.out.println("runTest caught exception:  " + e.getMessage());
              e.printStackTrace();
            }
          }
        } // class test
        

0 个答案:

没有答案