преобразование jtable в изображение не происходит должным образом - PullRequest
2 голосов
/ 06 июля 2011

Я пытаюсь создать буферизованное изображение из таблицы, когда я добавляю таблицу в фрейм приложения и устанавливаю размер, я могу правильно его просматривать, но когда я конвертирую его в изображение, я вижу только первую строку с таблицей и остальными вне таблицы и без заголовка.

Код для генерации таблицы:

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

Из-за этого ячейка не отображается должным образом. Как только я удалю этот код, таблица будет сгенерирована правильно, включая код Клеопатры. Но я застрял с проблемой переноса слов в ячейке.

Спасибо, Бхавья

P.S. Я использовал тот же код выше для генерации изображения, когда объект таблицы создается с использованием новой JTable (строки, поля), в моем коде читается и вставляется в table_model

сериализованный хэш-файл

Ответы [ 3 ]

2 голосов
/ 06 июля 2011

По сути, вы должны выполнить макет для всех компонентов, которые вы хотите нарисовать на изображении, то есть в этом случае и table, и tableHeader, установив их размеры (ниже префиксаиспользуемый).

Кстати, добавление в 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");

Редактировать: comment to TextAreaRenderer

Общее правило: никогда и никогда не изменять вызывающую таблицу в getXXRendererComponent средства визуализации, таблица, заданная в качестве параметра, должна рассматриваться строго как доступная только для чтения.Нарушение правила может привести к появлению уродливых циклов (установка нового rowHeight во время рисования запускает новый запрос рисования) или артефактов (нет никакой гарантии, когда вызывается средство визуализации, поэтому правильная высота строки может быть установлена ​​или не установлена), как вы видите здесь.

Вместо этого сделайте измерение где-нибудь снаружи.При обнаружении изменения (например, в модели), которое может привести к обновлению размеров, пройдитесь по рядам, измерьте все его ячейки и обновите до самых больших.Просто извлеките весь свой размерный код из рендерера.

1 голос
/ 06 июля 2011

Здесь я вижу несколько проблем.

  • При рисовании на изображении вы должны использовать printAll, а не рисовать.

  • Высота таблицы задается при вызове метода pack, но это до заполнения таблицы. Если вы создаете изображение сразу после создания таблицы, размер может быть не установлен. Вы должны заполнить таблицу, прежде чем упаковать кадр - это должно гарантировать, что размер доступен, когда вам это нужно.

РЕДАКТИРОВАТЬ: После изменения вашего кода я бы предложил удалить панель прокрутки (как предложила Клеопатра) и затем использовать printAll. краска не должна использоваться для изображений, поскольку она может использовать двойную буферизацию. Чтобы увидеть заголовок, вам нужно установить его размер, используя код, предоставленный kleopatra. Размер заголовка не зависит от таблицы, поэтому вызов setSize для таблицы не меняет заголовок.

0 голосов
/ 07 июля 2011

Я просмотрел сообщение в этом месте Усеченный вывод на печать JTable и включил ответ в том месте, которое, кажется, сейчас работает нормально.

Спасибо за помощь

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...