2011-02-04 9 views
5

私は、テーブルセルがワードラップを利用できるように、JTextAreaをそのTableCellRendererとして使用するJTableを持っています。 JTableは正常に表示されます。 JTableのprint method経由でテーブルをプリンタに印刷すると、出力は常にデータの約60%で切り捨てられます。私は別のコンピュータと異なるプリンタと、異なるプリンタドライバ、異なるJVMバージョン(1.5、1.6)を試しましたが、どれもそれを助けませんでした。以下は、この問題を再現する自己完結型のJavaメインクラスです。何か案は?切り捨てられたJTableプリント出力

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

答えて

0

私は根本的な原因と解決策を見つけたと思います。印刷の問題は、テーブルの高さが間違っていることに起因します。表の行の一部が間違った高さであるため、表の高さが正しくありません。 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でprintメソッドを呼び出す前に)、この回避コードを実行することができます。これにより、ユーザーがGUIを使用していて、印刷していない場合、JTableの最適化が有効になります。ラウンド

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); 
    } 
} 
+1

間違った方法::、どのような方法で、発信者の状態を決して変えないNOT_ARCHIVEDの_mustレンダラを – kleopatra

+0

@kleopatra - フィードバックいただきありがとうございます。私はあなたのコメントに応じて私の答えを更新したいと思います。しかし、私はルールのドキュメントを探しに行きました "レンダラーは発信者の状態を変更してはいけません"と私は何も見つかりませんでした。私はあなたが間違っていると言っているわけではない - ちょうどそれについてもっと読んで、検証を受けるかもしれない。この契約書がどこに文書化されているかに関するアイデアはありますか? –

0

私は少しそれが私のために動作させるためにマイククラークスソリューションを変更する必要がありました。代わりに、この記事で表示しているループにrowHeightの更新を移動してください。
関連する問題