2011-07-06 14 views
2

我想從表中創建一個緩衝圖像,當我將表添加到應用程序框架,並設置大小,我能夠正確地查看它,但是當我將它轉換爲圖像我只能看到表格的第一行,其餘的表格沒有標題。jtable圖像轉換不能正常發生

的代碼生成表是

table = new JTable(); 

    String[] table_header = null; 

    TextAreaRenderer textAreaRenderer = new TextAreaRenderer(); 
    table_model = new DefaultTableModel() { 

     @Override 
     public boolean isCellEditable(int row, int column) { 
      return false; 
     } 
    }; 

    table.setModel(table_model); 
    table.setSize(300, 700); 
    JScrollPane pane = new JScrollPane(table); 
    createTableDataSet(input1, input2, varient, headertype); 
    TableColumnModel cmodel = table.getColumnModel(); 
    table_header = obtainTableHeader(headertype); 
    for (int i = 0; i < table_header.length; i++) { 
     cmodel.getColumn(i).setCellRenderer(textAreaRenderer); 
    } 


    return table; 

以生成所述圖像的代碼:

JTableHeader header =table.getTableHeader(); 
    int w = Math.max(table.getWidth(), header.getWidth()); 
    int h = table.getHeight() + header.getHeight(); 
    BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); 
    Graphics2D g2 = bi.createGraphics(); 
    header.paint(g2); 
    g2.translate(0, header.getHeight()); 
    table.paint(g2); 
    g2.dispose(); 
    try { 
     ImageIO.write(bi, "png", new File("year.png")); 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

表中的圖像是here

更新1:我可能已經發現問題的原因。我正在使用下面的代碼片段爲了增加單元格的大小,以便文本被包裝到單元格中。包括引起問題的代碼 private finalTargetCellRenderer renderer = new DefaultTableCellRenderer();

// Column heights are placed in this Map 
private final Map<JTable, Map<Object, Map<Object, Integer>>> tablecellSizes = new HashMap<JTable, Map<Object, Map<Object, Integer>>>(); 

/** 
* Creates a text area renderer. 
*/ 
public TextAreaRenderer() { 
    setLineWrap(true); 
    setWrapStyleWord(true); 
} 

/** 
* Returns the component used for drawing the cell. This method is 
* used to configure the renderer appropriately before drawing. 
* 
* @param table  - JTable object 
* @param value  - the value of the cell to be rendered. 
* @param isSelected - isSelected true if the cell is to be rendered with the selection highlighted; 
*     otherwise false. 
* @param hasFocus - if true, render cell appropriately. 
* @param row  - The row index of the cell being drawn. 
* @param column  - The column index of the cell being drawn. 
* @return - Returns the component used for drawing the cell. 
*/ 
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, 
               boolean hasFocus, int row, int column) { 
    // set the Font, Color, etc. 
    renderer.getTableCellRendererComponent(table, value, 
      isSelected, hasFocus, row, column); 
    setForeground(renderer.getForeground()); 
    setBackground(renderer.getBackground()); 
    setBorder(renderer.getBorder()); 
    setFont(renderer.getFont()); 
    setText(renderer.getText()); 

    TableColumnModel columnModel = table.getColumnModel(); 
    setSize(columnModel.getColumn(column).getWidth(), 0); 
    int height_wanted = (int) getPreferredSize().getHeight(); 
    addSize(table, row, column, height_wanted); 
    height_wanted = findTotalMaximumRowSize(table, row); 
    if (height_wanted != table.getRowHeight(row)) { 
     table.setRowHeight(row, height_wanted); 
    } 
    return this; 
} 

/** 
* @param table - JTable object 
* @param row - The row index of the cell being drawn. 
* @param column - The column index of the cell being drawn. 
* @param height - Row cell height as int value 
*    This method will add size to cell based on row and column number 
*/ 
private void addSize(JTable table, int row, int column, int height) { 
    Map<Object, Map<Object, Integer>> rowsMap = tablecellSizes.get(table); 
    if (rowsMap == null) { 
     tablecellSizes.put(table, rowsMap = new HashMap<Object, Map<Object, Integer>>()); 
    } 
    Map<Object, Integer> rowheightsMap = rowsMap.get(row); 
    if (rowheightsMap == null) { 
     rowsMap.put(row, rowheightsMap = new HashMap<Object, Integer>()); 
    } 
    rowheightsMap.put(column, height); 
} 

/** 
* Look through all columns and get the renderer. If it is 
* also a TextAreaRenderer, we look at the maximum height in 
* its hash table for this row. 
* 
* @param table -JTable object 
* @param row - The row index of the cell being drawn. 
* @return row maximum height as integer value 
*/ 
private int findTotalMaximumRowSize(JTable table, int row) { 
    int maximum_height = 0; 
    Enumeration<TableColumn> columns = table.getColumnModel().getColumns(); 
    while (columns.hasMoreElements()) { 
     TableColumn tc = columns.nextElement(); 
     TableCellRenderer cellRenderer = tc.getCellRenderer(); 
     if (cellRenderer instanceof TextAreaRenderer) { 
      TextAreaRenderer tar = (TextAreaRenderer) cellRenderer; 
      maximum_height = Math.max(maximum_height, 
        tar.findMaximumRowSize(table, row)); 
     } 
    } 
    return maximum_height; 
} 

/** 
* This will find the maximum row size 
* 
* @param table - JTable object 
* @param row - The row index of the cell being drawn. 
* @return row maximum height as integer value 
*/ 
private int findMaximumRowSize(JTable table, int row) { 
    Map<Object, Map<Object, Integer>> rows = tablecellSizes.get(table); 
    if (rows == null) return 0; 
    Map<Object, Integer> rowheights = rows.get(row); 
    if (rowheights == null) return 0; 
    int maximum_height = 0; 
    for (Map.Entry<Object, Integer> entry : rowheights.entrySet()) { 
     int cellHeight = entry.getValue(); 
     maximum_height = Math.max(maximum_height, cellHeight); 
    } 
    return maximum_height; 
} 

這導致單元格不能正確顯示。一旦我刪除了這個代碼,表格就是通過包含kleopatra的代碼正確生成的。但我堅持在單元格中換行的問題。

感謝, 巴維亞

附:當我的代碼中使用新的JTable(行,字段)創建表對象時,我已經使用上述相同的代碼生成圖像,並讀取序列化的散列表並將其插入到table_model中

+0

怎麼樣table.getPreferredSize()。height?它返回什麼? – SteeveDroz

+0

@Oltarus對不起,我意識到這是因爲我將表添加到應用程序框架,如果我嘗試直接創建圖像我得到一個表的高度的值,但標題和數據不正確可見tha表 – bhavs

+0

我看到header.getHeight返回0,我將這個頭添加到table_model並將table_model添加到tabel。有沒有解決這個問題的方法? – bhavs

回答

1

我可以看到幾個問題這裏。

  • 當繪製到圖像時,您應該使用printAll而不是繪畫。

  • 表格的高度是在調用pack方法時設置的,但是這是在填充表格之前設置的。如果您在生成表格後立即創建圖像,則可能無法設置尺寸。在打包框架之前,您應該填充表格 - 這應確保在需要時可以使用大小。

編輯:按照你的代碼改變我會建議取消滾動窗格(如克列奧帕特拉建議),然後使用printAll。油漆不應該用於圖像,因爲它可以使用雙緩衝。要查看標題,您需要使用kleopatra提供的代碼來設置其大小。標題的大小獨立於表,因此在表上調用setSize不會改變標題。

+0

我剛剛用printAll替換了paint並檢查過,我仍然面臨這個問題。是的,我創建表後立即創建一個圖像,我只是嘗試與應用程序框架,即使然後我得到了與上述相同的圖像。另外我不想使用JFrame或ApplicationFrame,因爲我會傳遞要由servlet顯示的表對象。 – bhavs

+0

@Russ Hayward'JTable'應該加入到'JScrollPane'中,然後可能是關於'ViewPort'的建議...,但是沒有人通過命令OP的描述知道 – mKorbel

+0

@mKorbel再次猜測;-) – kleopatra

2

基本上,您必須通過設置它們的大小(在pref被使用之下)來爲要繪製到圖像上的所有組件(即本例中的表和表頭)執行佈局工作。

順便說一句,添加到JScrollPane沒有什麼幫助(如你所見),除非當窗格被實現 - 添加頭由addNotify中的表完成。

JTable table = new JTable(new AncientSwingTeam()); 
    JTableHeader header =table.getTableHeader(); 
    table.setSize(table.getPreferredSize()); 
    header.setSize(header.getPreferredSize()); 
    int w = Math.max(table.getWidth(), header.getWidth()); 
    int h = table.getHeight() + header.getHeight(); 
    BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); 
    Graphics2D g2 = bi.createGraphics(); 
    header.paint(g2); 
    g2.translate(0, header.getHeight()); 
    table.paint(g2); 
    g2.dispose(); 
    JLabel label = new JLabel(new ImageIcon(bi)); 
    showInFrame(label, "image of table"); 

編輯:於TextAreaRenderer

評論的一般規則是永不永遠永遠改變調用表中渲染的getXXRendererComponent,給定的參數表被視爲只讀,嚴格把關。打破規則可能導致醜陋的循環(在繪畫觸發新的繪畫請求時設置新的rowHeight)或人工製品(無法保證何時調用渲染器,因此可能會或不會設置正確的rowheight),如您在此處所看到的。

而是在外面的某處測量。在檢測到可能導致更新大小的更改(模型中的f.i.)時,請走行,測量其所有單元格並更新爲最大值。簡單地從渲染器中提取所有尺寸代碼。

+0

儘可能容易,我的壞我再次複雜簡單的事情+1 – mKorbel

+0

@kleopatra感謝您的代碼片段,但只解決了我的部分問題,表頭現在可見。 – bhavs

0

我在這個位置Truncated JTable print output通過帖子,包括在那個位置的答案,它現在似乎工作正常。

感謝您的幫助

+1

答案是錯誤的,儘管它可能適用於你的特定情況。做。不。更改。 Caller's.State.In.Renderer。在這裏看到我的答案和我的評論 – kleopatra