jtable图像转换没有正确发生

时间:2011-07-06 08:25:51

标签: java image swing 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 final DefaultTableCellRenderer 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的代码正确生成表格。但我仍然坚持单元格中的自动换行问题。

谢谢, Bhavya

P.S。我使用上面相同的代码生成图像时,在我的代码中使用新的JTable(行,字段)创建表对象时,读取序列化的hashmap并将其插入table_model

3 个答案:

答案 0 :(得分:2)

基本上,您必须为要绘制到图像的所有组件进行布局工作,在本例中是table和tableHeader,通过设置它们的大小(在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)或伪影(无法保证调用渲染器,因此可能已设置正确的行高),如此处所示。

而是在外面的某处进行测量。在检测到可能导致更新尺寸的变化(模型中的f.i.)时,走行,测量其所有单元并更新到最大。只需从渲染器中提取所有大小调整代码即可。

答案 1 :(得分:1)

我可以在这里看到一些问题。

  • 绘制到图像时,应使用printAll而不是绘画。

  • 调用pack方法时会设置表的高度,但这是在填充表之前。如果在生成表格后立即创建图像,则可能无法设置大小。您应该在打包框架之前填充表格 - 这应该确保在您需要时可以使用该尺寸。

编辑:在您的代码更改后,我建议删除滚动窗格(如kleopatra建议),然后使用printAll。油漆不应该用于图像,因为它可以使用双缓冲。要查看标题,您需要使用kleopatra提供的代码设置其大小。标题的大小独立于表,因此在表上调用setSize不会改变标题。

答案 2 :(得分:0)

我在这个位置Truncated JTable print output查看了该帖子,并在该位置包含了答案,现在似乎工作正常。

感谢您的帮助