jtable图像转换没有正确发生 [英] jtable to image conversion not happening properly

查看:109
本文介绍了jtable图像转换没有正确发生的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试从表中创建缓冲图像,当我将表添加到应用程序框架并设置大小时我能够正确查看它但是当我将其转换为图像时我只能看到第一行表格和其他表格之外没有标题。

I am trying to create a buffered image from a table, when i add the table to a application frame and set the size I am able to view it properly but when I convert it into an image I can only see the first row with the table and the rest outside the table and without the header.

生成表格的代码是

  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();
    }

表的图像是

更新1:我可能已找到问题的原因。我正在使用以下代码片段来增加单元格的大小,以便将文本包装到单元格中。包括导致问题的代码
private final DefaultTableCellRenderer renderer = new DefaultTableCellRenderer();

update 1 :I may have found the cause of the problem . I am using the following code snippet in order to increase the size of the cell so that the text gets wrapped into the cell. Including the code which is causing the problem 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的代码正确生成表格。但我坚持单元格中的自动换行问题。

This is causing the cell not to be displayed properly. Once I remove this code the table is beig generated properly by including kleopatra's code. But I am stuck with the problem of word wrap in the cell.

谢谢,
Bhavya

Thanks, Bhavya

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

P.S. I have used the same code above to generate an image when the table object is created using new JTable(row,fields) in my code the serialized hashmap is read and inserted into the table_model

推荐答案

基本上,您必须为要绘制到图像的所有组件进行布局工作,在这种情况下,无论是表格还是tableHeader,通过设置它们的大小(使用pref以下)。

Basically, you have to do the layout work for all components you want to paint to the image, that is in this case both the table and the tableHeader, by setting their sizes (below the pref is used).

BTW,添加到JScrollPane没有帮助(如您所见),除非实现窗格时 - 添加标题由addNotify中的表完成。 / p>

BTW, adding to a JScrollPane is not helpful (as you have seen), except when the pane is realized - adding the header is done by the table in 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

comment on TextAreaRenderer

一般规则是永远不会改变渲染器的getXXRendererComponent中的调用表,作为参数给出的表将被视为只读,严格。破坏规则可能导致丑陋的循环(在绘制时触发新的绘制请求时设置新的rowHeight)或伪影(无法保证调用渲染器,因此可能已设置正确的行高),如此处所示。

The general rule is to never-ever-ever change the calling table in the renderer's getXXRendererComponent, the table given as parameter is to be regarded read-only, strictly. Breaking the rule can lead to ugly loops (setting a new rowHeight while painting triggers a new painting request) or artefacts (there is no guarantee when the renderer is called, so the correct rowheight might or not have been set) as you see here.

而是在外面的地方进行测量。检测到可能导致更新大小的更改(模型中的f.i.),遍历行,测量其所有单元格并更新为最大单元格。只需从渲染器中提取所有大小调整代码即可。

Instead do the measuring somewhere outside. On detecting a change (f.i. in the model) which might lead to updating the sizes, walk the rows, measure all its cells and update to the largest. Simply extract all your sizing code from the renderer.

这篇关于jtable图像转换没有正确发生的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆