Усеченный вывод на печать JTable - PullRequest
5 голосов
/ 04 февраля 2011

У меня есть JTable, который использует JTextArea в качестве TableCellRenderer, так что ячейки таблицы могут использовать перенос слов.JTable отображает нормально.Когда я печатаю таблицу на принтере с помощью метода печати JTable , вывод всегда обрезается примерно до 60% данных.Я пробовал разные компьютеры и разные принтеры и разные драйверы принтеров, разные версии JVM (1.5, 1.6), но ничего из этого не помогло.Ниже приведен автономный основной класс Java, который воспроизводит проблему.Есть идеи?

import java.awt.*;
import java.awt.event.*;
import java.awt.print.*;
import java.util.*;
import javax.swing.*;
import javax.swing.table.*;

public class JTextAreaJTableTest extends javax.swing.JFrame {

    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                JTextAreaJTableTest frame = new JTextAreaJTableTest();
                frame.setSize(640, 480);
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    JButton jButtonPrint;
    JScrollPane jScrollPane;
    JTable jTable;
    JToolBar jToolBar;

    public JTextAreaJTableTest() {
        initComponents();

        DefaultTableModel dtm = (DefaultTableModel) jTable.getModel();
        Vector<Vector<String>> data = new Vector<Vector<String>>();
        for (int i = 0; i < 50; i++) {
            Vector<String> rowData = new Vector<String>();
            rowData.add("Entry " + i);
            rowData.add("Lorem ipsum dolor sit amet, consectetur adipisicing"
                    + " elit, sed do eiusmod tempor incididunt ut labore et"
                    + " dolore magna aliqua. Ut enim ad minim veniam, quis"
                    + " nostrud exercitation ullamco laboris nisi ut aliquip"
                    + " ex ea commodo consequat. Duis aute irure dolor in"
                    + " reprehenderit in voluptate velit esse cillum dolore"
                    + " eu fugiat nulla pariatur. Excepteur sint occaecat"
                    + " cupidatat non proident, sunt in culpa qui officia"
                    + " deserunt mollit anim id est laborum. " + i);
            data.add(rowData);
        }
        Vector<String> columnNames = new Vector<String>();
        columnNames.add("Key");
        columnNames.add("Value");
        dtm.setDataVector(data, columnNames);
        jTable.setDefaultRenderer(String.class, null);
        jTable.getColumnModel().getColumn(0).setCellRenderer(
                new TextAreaCellRenderer());
        jTable.getColumnModel().getColumn(1).setCellRenderer(
                new TextAreaCellRenderer());
    }

    private void initComponents() {
        jToolBar = new JToolBar();
        jButtonPrint = new JButton();
        jScrollPane = new JScrollPane();
        jTable = new JTable();

        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

        jToolBar.setRollover(true);

        jButtonPrint.setText("Print");
        jButtonPrint.setFocusable(false);
        jButtonPrint.setHorizontalTextPosition(SwingConstants.CENTER);
        jButtonPrint.setVerticalTextPosition(SwingConstants.BOTTOM);
        jButtonPrint.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                jButtonPrintActionPerformed(evt);
            }
        });
        jToolBar.add(jButtonPrint);

        getContentPane().add(jToolBar, BorderLayout.NORTH);

        jScrollPane.setViewportView(jTable);

        getContentPane().add(jScrollPane, BorderLayout.CENTER);
    }

    private void jButtonPrintActionPerformed(ActionEvent evt)                                             
    {                                                 
        try {
            jTable.print();
        } catch (PrinterException ex) {
            ex.printStackTrace();
        }
    }                                            

    public static class TextAreaCellRenderer extends JTextArea implements
            TableCellRenderer {

        public TextAreaCellRenderer() {
            this.setLineWrap(true);
            this.setWrapStyleWord(true);
        }

        public Component getTableCellRendererComponent(JTable table, 
                Object value, boolean isSelected, boolean hasFocus,
                int row, int column) {
            this.setText(String.valueOf(value));
            TableColumnModel columnModel = table.getColumnModel();
            this.setSize(columnModel.getColumn(column).getWidth(), 1);
            int newHeight = this.getPreferredSize().height;
            if (newHeight > table.getRowHeight(row)) {
                table.setRowHeight(row, this.getPreferredSize().height);
            }
            return this;
        }
    }
}

Ответы [ 2 ]

0 голосов
/ 11 ноября 2013

Мне пришлось немного изменить решение Майка Кларкса, чтобы оно заработало для меня:

for (int colIdx = 0; colIdx < jTable.getColumnCount(); colIdx++) {
    for (int rowIdx = 0; rowIdx < jTable.getRowCount(); rowIdx++) {
        TableCellRenderer renderer = jTable.getCellRenderer(rowIdx, colIdx);
        Object cellValue = jTable.getValueAt(rowIdx, colIdx);
        renderer.getTableCellRendererComponent(jTable, cellValue,
                false, false, rowIdx, colIdx);
    }
}
0 голосов
/ 09 февраля 2011

Я считаю, что нашел основную причину и решение. Проблема печати связана с тем, что таблица имеет неправильную высоту. Таблица имеет неправильную высоту, потому что некоторые строки таблицы имеют неправильную высоту. Некоторые строки имеют неправильную высоту, потому что их средства визуализации ячеек не были вызваны JTable (то есть их метод getTableCellRendererComponent не был вызван). Причина, по которой JTable пропускает некоторые средства визуализации ячеек, заключается в оптимизации - средства визуализации ячеек он пропускается для ячеек, которые находятся за пределами экрана - вне экрана означает, что рендеринг не нужен; Оптимизация JTable в этой области имеет смысл.

Тем не менее, рендеры являются единственным местом в программе, где установлена ​​правильная высота каждой отдельной строки. Мой выбор установки высоты строки в средстве визуализации ячеек несколько понятен, потому что средство визуализации ячеек находится в лучшем положении, чтобы знать, какой должна быть высота строки.

Кажется, самый простой способ исправить эту примерную программу - это вручную вызвать getTableCellRendererComponent для каждого средства визуализации ячеек (это следует делать после изменения данных модели таблицы.) Это дает средствам визуализации возможность устанавливать каждый строка в таблице до его правильной индивидуальной высоты. Когда каждая строка имеет правильную высоту, общая таблица JTable оказывается правильной высотой, что, похоже, решает проблему усечения печати. Следующий код показывает посещение всех средств визуализации, чтобы сделать именно это:

for (int colIdx = 0; colIdx < jTable.getColumnCount(); colIdx++)
{
    for (int rowIdx = 0; rowIdx < jTable.getRowCount(); rowIdx++)
    {
        TableColumnModel columnModel = jTable.getColumnModel();
        TableColumn column = columnModel.getColumn(colIdx);
        TableCellRenderer renderer = column.getCellRenderer();
        Object cellValue = jTable.getValueAt(rowIdx, colIdx);
        renderer.getTableCellRendererComponent(jTable, cellValue, 
                    false, false, rowIdx, colIdx);
    }
}

Это ручное посещение всех средств визуализации ячеек обходит оптимизацию JTable, состоящую только в том, чтобы вызывать средства визуализации ячеек на экране. Таким образом, вы можете захотеть выполнить этот обходной код только после того, как пользователь запросил печать (но до вызова метода печати в JTable). Это позволяет оптимизации JTable оставаться в силе, если пользователь просто использует графический интерфейс и не печатает.

...