2014-11-06 12 views
0

好吧,首先让我说,在相隔几年之后,我正在回归编程。同时事情发生了很大变化(IDE,OO),我开始第一次用Java编程。Oracle TableRenderDemo中的单元格/行格式化

我需要构建一个GUI前端,我目前正在与JTables,tableModels和Renderer一起苦苦挣扎。

我目前正在通过Oracle TableRenderDemo工作,试图准确了解它在做什么以及是否有点卡住。

我怀疑我可能会加入到这个职位,但现在...

我不明白的是第一次运行时,为什么整个行绿色约翰和简,但是当我点击Vegetarian clickBox中的任何一个,只有comboBox单元格改变颜色而不是整行?

请记住,我真的对所有这些Java的东西都陌生,可能需要一个非常简单的解释。

非常感谢,

加里

下面的代码......(感谢) 包com.novartis.adhoc.view;

/* 
* TableRenderDemo.java requires no other files. 
*/ 

import javax.swing.DefaultCellEditor; 
import javax.swing.JComboBox; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JScrollPane; 
import javax.swing.JTable; 
import javax.swing.table.AbstractTableModel; 
import javax.swing.table.DefaultTableCellRenderer; 
import javax.swing.table.TableCellRenderer; 
import javax.swing.table.TableColumn; 

import java.awt.Color; 
import java.awt.Component; 
import java.awt.Dimension; 
import java.awt.GridLayout; 

/** 
* TableRenderDemo is just like TableDemo, except that it explicitly initializes 
* column sizes and it uses a combo box as an editor for the Sport column. 
*/ 
public class TableRenderDemo extends JPanel { 

    private static final long serialVersionUID = 1L; 
    private boolean DEBUG = false; 

    public TableRenderDemo() { 
     super(new GridLayout(1, 0)); 

     JTable table = new JTable(new MyTableModel()) 
     { 
      private static final long serialVersionUID = 1L; 

      public Component prepareRenderer(TableCellRenderer renderer, 
        int row, int column) { 
       Component c = super.prepareRenderer(renderer, row, column); 
       int modelRow = convertRowIndexToModel(row); 

       // Color row based on a cell value 
       if ((Boolean) getModel().getValueAt(modelRow, 4)) { 
        c.setBackground(Color.GREEN); 
       } else { 
        c.setBackground(getBackground()); 
       } 
       return c; 
      } 
     }; 

     table.setPreferredScrollableViewportSize(new Dimension(500, 70)); 
     table.setFillsViewportHeight(true); 

     // Create the scroll pane and add the table to it. 
     JScrollPane scrollPane = new JScrollPane(table); 

     // Set up column sizes. 
     initColumnSizes(table); 

     // Fiddle with the Sport column's cell editors/renderers. 
     setUpSportColumn(table, table.getColumnModel().getColumn(2)); 

     // Add the scroll pane to this panel. 
     add(scrollPane); 
    } 

    /* 
    * This method picks good column sizes. If all column heads are wider than 
    * the column's cells' contents, then you can just use 
    * column.sizeWidthToFit(). 
    */ 
    private void initColumnSizes(JTable table) { 
     MyTableModel model = (MyTableModel) table.getModel(); 
     TableColumn column = null; 
     Component comp = null; 
     int headerWidth = 0; 
     int cellWidth = 0; 
     Object[] longValues = model.longValues; 
     TableCellRenderer headerRenderer = table.getTableHeader().getDefaultRenderer(); 

     for (int i = 0; i < 5; i++) { 
      column = table.getColumnModel().getColumn(i); 

      comp = headerRenderer.getTableCellRendererComponent(null, 
        column.getHeaderValue(), false, false, 0, 0); 
      headerWidth = comp.getPreferredSize().width; 

      comp = table.getDefaultRenderer(model.getColumnClass(i)) 
        .getTableCellRendererComponent(table, longValues[i], false, false, 0, i); 
      cellWidth = comp.getPreferredSize().width; 

      if (DEBUG) { 
       System.out.println("Initializing width of column " + i + ". " 
         + "headerWidth = " + headerWidth + "; cellWidth = " 
         + cellWidth); 
      } 

      column.setPreferredWidth(Math.max(headerWidth, cellWidth)); 
     } 
    } 

    public void setUpSportColumn(JTable table, TableColumn sportColumn) { 
     // Set up the editor for the sport cells. 
     JComboBox<String> comboBox = new JComboBox<String>(); 
     comboBox.addItem("Snowboarding"); 
     comboBox.addItem("Rowing"); 
     comboBox.addItem("Knitting"); 
     comboBox.addItem("Speed reading"); 
     comboBox.addItem("Pool"); 
     comboBox.addItem("None of the above"); 
     sportColumn.setCellEditor(new DefaultCellEditor(comboBox)); 

     // Set up tool tips for the sport cells. 
     DefaultTableCellRenderer renderer = new DefaultTableCellRenderer(); 
     renderer.setToolTipText("Click for combo box"); 
     sportColumn.setCellRenderer(renderer); 
    } 

    class MyTableModel extends AbstractTableModel { 

     private static final long serialVersionUID = 1L; 
     private String[] columnNames = { "First Name", "Last Name", "Sport", 
       "# of Years", "Vegetarian" }; 
     private Object[][] data = { 
       { "Kathy", "Smith", "Snowboarding", new Integer(5), 
         new Boolean(false) }, 
       { "John", "Doe", "Rowing", new Integer(3), new Boolean(true) }, 
       { "Sue", "Black", "Knitting", new Integer(2), 
         new Boolean(false) }, 
       { "Jane", "White", "Speed reading", new Integer(20), 
         new Boolean(true) }, 
       { "Joe", "Brown", "Pool", new Integer(10), new Boolean(false) } }; 
     public final Object[] longValues = { "Jane", "Kathy", 
       "None of the above", new Integer(20), Boolean.TRUE }; 

     public int getColumnCount() { 
      return columnNames.length; 
     } 

     public int getRowCount() { 
      return data.length; 
     } 

     public String getColumnName(int col) { 
      return columnNames[col]; 
     } 

     public Object getValueAt(int row, int col) { 
      return data[row][col]; 
     } 

     /* 
     * JTable uses this method to determine the default renderer/ editor for 
     * each cell. If we didn't implement this method, then the last column 
     * would contain text ("true"/"false"), rather than a check box. 
     */ 
     public Class<? extends Object> getColumnClass(int c) { 
      return getValueAt(0, c).getClass(); 
     } 

     /* 
     * Don't need to implement this method unless your table's editable. 
     */ 
     public boolean isCellEditable(int row, int col) { 
      // Note that the data/cell address is constant, 
      // no matter where the cell appears onscreen. 
      if (col < 2) { 
       return false; 
      } 
      return true; 
     } 

     /* 
     * Don't need to implement this method unless your table's data can 
     * change. 
     */ 
     public void setValueAt(Object value, int row, int col) { 
      if (DEBUG) { 
       System.out.println("Setting value at " + row + "," + col 
         + " to " + value + " (an instance of " 
         + value.getClass() + ")"); 
      } 

      data[row][col] = value; 
      fireTableCellUpdated(row, col); 

      if (DEBUG) { 
       System.out.println("New value of data:"); 
       printDebugData(); 
      } 
     } 

     private void printDebugData() { 
      int numRows = getRowCount(); 
      int numCols = getColumnCount(); 

      for (int i = 0; i < numRows; i++) { 
       System.out.print(" row " + i + ":"); 
       for (int j = 0; j < numCols; j++) { 
        System.out.print(" " + data[i][j]); 
       } 
       System.out.println(); 
      } 
      System.out.println("--------------------------"); 
     } 

    } 

    /** 
    * Create the GUI and show it. For thread safety, this method should be 
    * invoked from the event-dispatching thread. 
    */ 
    private static void createAndShowGUI() { 
     // Create and set up the window. 
     JFrame frame = new JFrame("TableRenderDemo"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     // Create and set up the content pane. 
     TableRenderDemo newContentPane = new TableRenderDemo(); 
     newContentPane.setOpaque(true); // content panes must be opaque 
     frame.setContentPane(newContentPane); 

     // Display the window. 
     frame.pack(); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     // Schedule a job for the event-dispatching thread: 
     // creating and showing this application's GUI. 
     javax.swing.SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
       createAndShowGUI(); 
      } 
     }); 
    } 

} 

好了,我真的很想加入到岗位,而不是编辑原始的一个,但我不知道如何做到这一点(目前感觉真的很厚)。无论如何,我期待在此刻的以下部分...

TableCellRenderer headerRenderer = table.getTableHeader().getDefaultRenderer(); 

for (int i = 0; i < 5; i++) { 
    column = table.getColumnModel().getColumn(i); 

    comp = headerRenderer.getTableCellRendererComponent(
         null, column.getHeaderValue(), 
         false, false, 0, 0); 
    headerWidth = comp.getPreferredSize().width; 

    comp = table.getDefaultRenderer(model.getColumnClass(i)). 
        getTableCellRendererComponent(
         table, longValues[i], 
         false, false, 0, i); 
    cellWidth = comp.getPreferredSize().width; 
} 

所以我在此假设头有从表中的其余部分不同的渲染正确吗?

另外,我没有得到headerRenderer.getTableCellRendererComponent的参数... table = null,row = 0,column = 0。这是怎么回事?

而且,如果column.getHeaderValue()返回对象在头列我,为什么我们不能只说:

comp = column.getHeaderValue(); 
headerWidth = comp.getPreferredSize().width; 

感谢,

加里

+0

尝试不同的[外观和感觉](http://docs.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html)实现来查看效果。 – trashgod 2014-11-06 20:09:23

+0

Render's用于渲染多个单元格(通常用于同一列),如果不完全重新配置它们,它们会将状态从一个单元转移到另一个单元。发布一个可运行的示例 – MadProgrammer 2014-11-06 23:51:15

回答

0

好,第一件事是代码是由一位同事提供给我的(我认为这是Oracle网站上的确切代码),但不是,他一直在玩它。

总之...

我不明白的是第一次运行时,为什么整个行绿色 约翰和简,但是当我点击素食clickBox对他们的任何 只comboBox单元格改变颜色而不是整行?

我想我已经想通了,为什么会这样 - 下面的代码是该行中的每个单元执行:

if ((Boolean) getModel().getValueAt(modelRow, 4)) { 
    c.setBackground(Color.GREEN); 
} else { 
    c.setBackground(getBackground()); 

所以,当表首先绘制...的第列,它检查列4中的值,如果它是'真',它将列0中的单元格设置为绿色(和列1至3)。但是,当列4中的值更改为'假'时,呈现器未在列0(等)中的单元格上运行,因此它不知道再次执行此检查,因此颜色不能更改为其他列。

无论如何,我已经得到了解决此通过...

if ((Boolean) getModel().getValueAt(modelRow, 4)) { 
    c.setBackground(Color.GREEN); 
    repaint(); 
} else { 
    c.setBackground(getBackground()); 

四处逛逛!

+0

奇怪...这种方式与我希望的完全相同,但我不明白为什么它应该在我将“Vegetarian”设置为false时正常工作 - 代码不执行重绘,但它会设置所有的单元格背景变成白色。 实际上,这引发了另一个问题,如果免费为绿色,为什么c.setBackground(getBackground())将它设置为白色?当然getBackground()返回绿色,c.setBackground只是将它设置为绿色? – Cooperman 2014-11-07 15:20:35

相关问题