2014-11-06 14 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

相關問題