2011-09-08 4 views
4

경계선없이 JTable에 데이터를 인쇄해야하는데 JTable의 빈 경계선을 사용하여이 작업을 수행하려고했지만 여전히 테이블 주위에 테두리를 인쇄합니다.테두리없이 JTable의 데이터 인쇄하기

dataTable = new javax.swing.JTable();  
dataTable.setBorder(BorderFactory.createEmptyBorder()); 
dataTable.setShowHorizontalLines(false); dataTable.setShowVerticalLines(false); 
dataTable.setModel(new javax.swing.table.DefaultTableModel(new Object [][] { }, new String [] { "Item ID", "Company Name", "Qty.", "Price", "Total" })); 
jScrollPane1.setViewportView(dataTable); 
jScrollPane1.setViewportBorder(BorderFactory.createEmptyBorder()); 
jScrollPane1.setBorder(BorderFactory.createEmptyBorder()); 
+0

어디 [SSCCE] (http://pscode.org/sscce.html) 가장 좋은 시도이다? (귀하의 질문은 무엇입니까?) –

+0

@Andrew Thompson 그 정기적 인 질문, 그리고 진짜로 어떻게 해결하고 해제/해제 JTable의 주위에 얇은 검은 선을 제거 (표준 내장 JTable의 인쇄 지원 의미) :-) – mKorbel

+0

dataTable = new javax.swing.JTable(); dataTable.setBorder (BorderFactory.createEmptyBorder()); dataTable.setShowHorizontalLines (false); dataTable.setShowVerticalLines (false); dataTable.setModel ( new object [] [} new String [] { "항목 ID", "회사 이름", "수량", "가격" , "Total" } )); jScrollPane1.setViewportView (dataTable); jScrollPane1.setViewportBorder (BorderFactory.createEmptyBorder()); jScrollPane1.setBorder (BorderFactory.createEmptyBorder());
이것은 내가 마지막으로 쓴 노력이다. – Harsha

답변

6

당신은 자신의 클래스 (MyPrintable)TablePrintable에서 코드를 복사 한 다음 줄을 제거 할 수 있습니다

// draw a box around the table 
    g2d.setColor(Color.BLACK); 
    g2d.drawRect(0, 0, clip.width, hclip.height + clip.height); 

을 그리고 당신의 JTablegetPrintable -Method를 재정의합니다.

dataTable = new javax.swing.JTable(){ 
     @Override 
     public Printable getPrintable(PrintMode printMode, MessageFormat headerFormat, MessageFormat footerFormat) { 
      return new MyPrintable(this, printMode, headerFormat, footerFormat); 
     } 
    }; 

MyPrintable

/* 
* @(#)TablePrintable.java 1.41 05/11/17 
* 
* Copyright 2006 Sun Microsystems, Inc. All rights reserved. 
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. 
*/ 

import java.awt.Color; 
import java.awt.Font; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.Rectangle; 
import java.awt.Shape; 
import java.awt.geom.AffineTransform; 
import java.awt.geom.Rectangle2D; 
import java.awt.print.PageFormat; 
import java.awt.print.Printable; 
import java.awt.print.PrinterException; 
import java.text.MessageFormat; 

import javax.swing.JTable; 
import javax.swing.table.JTableHeader; 
import javax.swing.table.TableColumnModel; 

/** 
* An implementation of <code>Printable</code> for printing 
* <code>JTable</code>s. 
* <p> 
* This implementation spreads table rows naturally in sequence 
* across multiple pages, fitting as many rows as possible per page. 
* The distribution of columns, on the other hand, is controlled by a 
* printing mode parameter passed to the constructor. When 
* <code>JTable.PrintMode.NORMAL</code> is used, the implementation 
* handles columns in a similar manner to how it handles rows, spreading them 
* across multiple pages (in an order consistent with the table's 
* <code>ComponentOrientation</code>). 
* When <code>JTable.PrintMode.FIT_WIDTH</code> is given, the implementation 
* scales the output smaller if necessary, to ensure that all columns fit on 
* the page. (Note that width and height are scaled equally, ensuring that the 
* aspect ratio remains the same). 
* <p> 
* The portion of table printed on each page is headed by the 
* appropriate section of the table's <code>JTableHeader</code>. 
* <p> 
* Header and footer text can be added to the output by providing 
* <code>MessageFormat</code> instances to the constructor. The 
* printing code requests Strings from the formats by calling 
* their <code>format</code> method with a single parameter: 
* an <code>Object</code> array containing a single element of type 
* <code>Integer</code>, representing the current page number. 
* <p> 
* There are certain circumstances where this <code>Printable</code> 
* cannot fit items appropriately, resulting in clipped output. 
* These are: 
* <ul> 
* <li>In any mode, when the header or footer text is too wide to 
*  fit completely in the printable area. The implementation 
*  prints as much of the text as possible starting from the beginning, 
*  as determined by the table's <code>ComponentOrientation</code>. 
* <li>In any mode, when a row is too tall to fit in the 
*  printable area. The upper most portion of the row 
*  is printed and no lower border is shown. 
* <li>In <code>JTable.PrintMode.NORMAL</code> when a column 
*  is too wide to fit in the printable area. The center of the 
*  column is printed and no left and right borders are shown. 
* </ul> 
* <p> 
* It is entirely valid for a developer to wrap this <code>Printable</code> 
* inside another in order to create complex reports and documents. They may 
* even request that different pages be rendered into different sized 
* printable areas. The implementation was designed to handle this by 
* performing most of its calculations on the fly. However, providing different 
* sizes works best when <code>JTable.PrintMode.FIT_WIDTH</code> is used, or 
* when only the printable width is changed between pages. This is because when 
* it is printing a set of rows in <code>JTable.PrintMode.NORMAL</code> and the 
* implementation determines a need to distribute columns across pages, 
* it assumes that all of those rows will fit on each subsequent page needed 
* to fit the columns. 
* <p> 
* It is the responsibility of the developer to ensure that the table is not 
* modified in any way after this <code>Printable</code> is created (invalid 
* modifications include changes in: size, renderers, or underlying data). 
* The behavior of this <code>Printable</code> is undefined if the table is 
* changed at any time after creation. 
* 
* @author Shannon Hickey 
* @version 1.41 11/17/05 
*/ 
class TablePrintable implements Printable { 

    /** The table to print. */ 
    private JTable table; 

    /** For quick reference to the table's header. */ 
    private JTableHeader header; 

    /** For quick reference to the table's column model. */ 
    private TableColumnModel colModel; 

    /** To save multiple calculations of total column width. */ 
    private int totalColWidth; 

    /** The printing mode of this printable. */ 
    private JTable.PrintMode printMode; 

    /** Provides the header text for the table. */ 
    private MessageFormat headerFormat; 

    /** Provides the footer text for the table. */ 
    private MessageFormat footerFormat; 

    /** The most recent page index asked to print. */ 
    private int last = -1; 

    /** The next row to print. */ 
    private int row = 0; 

    /** The next column to print. */ 
    private int col = 0; 

    /** Used to store an area of the table to be printed. */ 
    private final Rectangle clip = new Rectangle(0, 0, 0, 0); 

    /** Used to store an area of the table's header to be printed. */ 
    private final Rectangle hclip = new Rectangle(0, 0, 0, 0); 

    /** Saves the creation of multiple rectangles. */ 
    private final Rectangle tempRect = new Rectangle(0, 0, 0, 0); 

    /** Vertical space to leave between table and header/footer text. */ 
    private static final int H_F_SPACE = 8; 

    /** Font size for the header text. */ 
    private static final float HEADER_FONT_SIZE = 18.0f; 

    /** Font size for the footer text. */ 
    private static final float FOOTER_FONT_SIZE = 12.0f; 

    /** The font to use in rendering header text. */ 
    private Font headerFont; 

    /** The font to use in rendering footer text. */ 
    private Font footerFont; 

    /** 
    * Create a new <code>TablePrintable</code> for the given 
    * <code>JTable</code>. Header and footer text can be specified using the 
    * two <code>MessageFormat</code> parameters. When called upon to provide 
    * a String, each format is given the current page number. 
    * 
    * @param table   the table to print 
    * @param printMode  the printing mode for this printable 
    * @param headerFormat a <code>MessageFormat</code> specifying the text to 
    *      be used in printing a header, or null for none 
    * @param footerFormat a <code>MessageFormat</code> specifying the text to 
    *      be used in printing a footer, or null for none 
    * @throws IllegalArgumentException if passed an invalid print mode 
    */ 
    public TablePrintable(JTable table, 
          JTable.PrintMode printMode, 
          MessageFormat headerFormat, 
          MessageFormat footerFormat) { 

     this.table = table; 

     header = table.getTableHeader(); 
     colModel = table.getColumnModel(); 
     totalColWidth = colModel.getTotalColumnWidth(); 

     if (header != null) { 
      // the header clip height can be set once since it's unchanging 
      hclip.height = header.getHeight(); 
     } 

     this.printMode = printMode; 

     this.headerFormat = headerFormat; 
     this.footerFormat = footerFormat; 

     // derive the header and footer font from the table's font 
     headerFont = table.getFont().deriveFont(Font.BOLD, 
               HEADER_FONT_SIZE); 
     footerFont = table.getFont().deriveFont(Font.PLAIN, 
               FOOTER_FONT_SIZE); 
    } 

    /** 
    * Prints the specified page of the table into the given {@link Graphics} 
    * context, in the specified format. 
    * 
    * @param graphics the context into which the page is drawn 
    * @param pageFormat the size and orientation of the page being drawn 
    * @param pageIndex the zero based index of the page to be drawn 
    * @return PAGE_EXISTS if the page is rendered successfully, or 
    *   NO_SUCH_PAGE if a non-existent page index is specified 
    * @throws PrinterException if an error causes printing to be aborted 
    */ 
    @Override 
    public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) 
                 throws PrinterException { 

     // for easy access to these values 
     final int imgWidth = (int)pageFormat.getImageableWidth(); 
     final int imgHeight = (int)pageFormat.getImageableHeight(); 

     if (imgWidth <= 0) { 
      throw new PrinterException("Width of printable area is too small."); 
     } 

     // to pass the page number when formatting the header and footer text 
     Object[] pageNumber = new Object[]{new Integer(pageIndex + 1)}; 

     // fetch the formatted header text, if any 
     String headerText = null; 
     if (headerFormat != null) { 
      headerText = headerFormat.format(pageNumber); 
     } 

     // fetch the formatted footer text, if any 
     String footerText = null; 
     if (footerFormat != null) { 
      footerText = footerFormat.format(pageNumber); 
     } 

     // to store the bounds of the header and footer text 
     Rectangle2D hRect = null; 
     Rectangle2D fRect = null; 

     // the amount of vertical space needed for the header and footer text 
     int headerTextSpace = 0; 
     int footerTextSpace = 0; 

     // the amount of vertical space available for printing the table 
     int availableSpace = imgHeight; 

     // if there's header text, find out how much space is needed for it 
     // and subtract that from the available space 
     if (headerText != null) { 
      graphics.setFont(headerFont); 
      hRect = graphics.getFontMetrics().getStringBounds(headerText, 
                   graphics); 

      headerTextSpace = (int)Math.ceil(hRect.getHeight()); 
      availableSpace -= headerTextSpace + H_F_SPACE; 
     } 

     // if there's footer text, find out how much space is needed for it 
     // and subtract that from the available space 
     if (footerText != null) { 
      graphics.setFont(footerFont); 
      fRect = graphics.getFontMetrics().getStringBounds(footerText, 
                   graphics); 

      footerTextSpace = (int)Math.ceil(fRect.getHeight()); 
      availableSpace -= footerTextSpace + H_F_SPACE; 
     } 

     if (availableSpace <= 0) { 
      throw new PrinterException("Height of printable area is too small."); 
     } 

     // depending on the print mode, we may need a scale factor to 
     // fit the table's entire width on the page 
     double sf = 1.0D; 
     if (printMode == JTable.PrintMode.FIT_WIDTH && 
       totalColWidth > imgWidth) { 

      // if not, we would have thrown an acception previously 
      assert imgWidth > 0; 

      // it must be, according to the if-condition, since imgWidth > 0 
      assert totalColWidth > 1; 

      sf = (double)imgWidth/(double)totalColWidth; 
     } 

     // dictated by the previous two assertions 
     assert sf > 0; 

     // This is in a loop for two reasons: 
     // First, it allows us to catch up in case we're called starting 
     // with a non-zero pageIndex. Second, we know that we can be called 
     // for the same page multiple times. The condition of this while 
     // loop acts as a check, ensuring that we don't attempt to do the 
     // calculations again when we are called subsequent times for the 
     // same page. 
     while (last < pageIndex) { 
      // if we are finished all columns in all rows 
      if (row >= table.getRowCount() && col == 0) { 
       return NO_SUCH_PAGE; 
      } 

      // rather than multiplying every row and column by the scale factor 
      // in findNextClip, just pass a width and height that have already 
      // been divided by it 
      int scaledWidth = (int)(imgWidth/sf); 
      int scaledHeight = (int)((availableSpace - hclip.height)/sf); 

      // calculate the area of the table to be printed for this page 
      findNextClip(scaledWidth, scaledHeight); 

      last++; 
     } 

     // translate into the co-ordinate system of the pageFormat 
     Graphics2D g2d = (Graphics2D)graphics; 
     g2d.translate(pageFormat.getImageableX(), pageFormat.getImageableY()); 

     // to save and store the transform 
     AffineTransform oldTrans; 

     // if there's footer text, print it at the bottom of the imageable area 
     if (footerText != null) { 
      oldTrans = g2d.getTransform(); 

      g2d.translate(0, imgHeight - footerTextSpace); 

      printText(g2d, footerText, fRect, footerFont, imgWidth); 

      g2d.setTransform(oldTrans); 
     } 

     // if there's header text, print it at the top of the imageable area 
     // and then translate downwards 
     if (headerText != null) { 
      printText(g2d, headerText, hRect, headerFont, imgWidth); 

      g2d.translate(0, headerTextSpace + H_F_SPACE); 
     } 

     // constrain the table output to the available space 
     tempRect.x = 0; 
     tempRect.y = 0; 
     tempRect.width = imgWidth; 
     tempRect.height = availableSpace; 
     g2d.clip(tempRect); 

     // if we have a scale factor, scale the graphics object to fit 
     // the entire width 
     if (sf != 1.0D) { 
      g2d.scale(sf, sf); 

     // otherwise, ensure that the current portion of the table is 
     // centered horizontally 
     } else { 
      int diff = (imgWidth - clip.width)/2; 
      g2d.translate(diff, 0); 
     } 

     // store the old transform and clip for later restoration 
     oldTrans = g2d.getTransform(); 
     Shape oldClip = g2d.getClip(); 

     // if there's a table header, print the current section and 
     // then translate downwards 
     if (header != null) { 
      hclip.x = clip.x; 
      hclip.width = clip.width; 

      g2d.translate(-hclip.x, 0); 
      g2d.clip(hclip); 
      header.print(g2d); 

      // restore the original transform and clip 
      g2d.setTransform(oldTrans); 
      g2d.setClip(oldClip); 

      // translate downwards 
      g2d.translate(0, hclip.height); 
     } 

     // print the current section of the table 
     g2d.translate(-clip.x, -clip.y); 
     g2d.clip(clip); 
     table.print(g2d); 

     // restore the original transform and clip 
     g2d.setTransform(oldTrans); 
     g2d.setClip(oldClip); 

     // draw a box around the table 
     g2d.setColor(Color.BLACK); 
     g2d.drawRect(0, 0, clip.width, hclip.height + clip.height); 

     return PAGE_EXISTS; 
    } 

    /** 
    * A helper method that encapsulates common code for rendering the 
    * header and footer text. 
    * 
    * @param g2d  the graphics to draw into 
    * @param text  the text to draw, non null 
    * @param rect  the bounding rectangle for this text, 
    *     as calculated at the given font, non null 
    * @param font  the font to draw the text in, non null 
    * @param imgWidth the width of the area to draw into 
    */ 
    private void printText(Graphics2D g2d, 
          String text, 
          Rectangle2D rect, 
          Font font, 
          int imgWidth) { 

      int tx; 

      // if the text is small enough to fit, center it 
      if (rect.getWidth() < imgWidth) { 
       tx = (int)((imgWidth - rect.getWidth())/2); 

      // otherwise, if the table is LTR, ensure the left side of 
      // the text shows; the right can be clipped 
      } else if (table.getComponentOrientation().isLeftToRight()) { 
       tx = 0; 

      // otherwise, ensure the right side of the text shows 
      } else { 
       tx = -(int)(Math.ceil(rect.getWidth()) - imgWidth); 
      } 

      int ty = (int)Math.ceil(Math.abs(rect.getY())); 
      g2d.setColor(Color.BLACK); 
      g2d.setFont(font); 
      g2d.drawString(text, tx, ty); 
    } 

    /** 
    * Calculate the area of the table to be printed for 
    * the next page. This should only be called if there 
    * are rows and columns left to print. 
    * 
    * To avoid an infinite loop in printing, this will 
    * always put at least one cell on each page. 
    * 
    * @param pw the width of the area to print in 
    * @param ph the height of the area to print in 
    */ 
    private void findNextClip(int pw, int ph) { 
     final boolean ltr = table.getComponentOrientation().isLeftToRight(); 

     // if we're ready to start a new set of rows 
     if (col == 0) { 
      if (ltr) { 
       // adjust clip to the left of the first column 
       clip.x = 0; 
      } else { 
       // adjust clip to the right of the first column 
       clip.x = totalColWidth; 
      } 

      // adjust clip to the top of the next set of rows 
      clip.y += clip.height; 

      // adjust clip width and height to be zero 
      clip.width = 0; 
      clip.height = 0; 

      // fit as many rows as possible, and at least one 
      int rowCount = table.getRowCount(); 
      int rowHeight = table.getRowHeight(row); 
      do { 
       clip.height += rowHeight; 

       if (++row >= rowCount) { 
        break; 
       } 

       rowHeight = table.getRowHeight(row); 
      } while (clip.height + rowHeight <= ph); 
     } 

     // we can short-circuit for JTable.PrintMode.FIT_WIDTH since 
     // we'll always fit all columns on the page 
     if (printMode == JTable.PrintMode.FIT_WIDTH) { 
      clip.x = 0; 
      clip.width = totalColWidth; 
      return; 
     } 

     if (ltr) { 
      // adjust clip to the left of the next set of columns 
      clip.x += clip.width; 
     } 

     // adjust clip width to be zero 
     clip.width = 0; 

     // fit as many columns as possible, and at least one 
     int colCount = table.getColumnCount(); 
     int colWidth = colModel.getColumn(col).getWidth(); 
     do { 
      clip.width += colWidth; 
      if (!ltr) { 
       clip.x -= colWidth; 
      } 

      if (++col >= colCount) { 
       // reset col to 0 to indicate we're finished all columns 
       col = 0; 

       break; 
      } 

      colWidth = colModel.getColumn(col).getWidth(); 
     } while (clip.width + colWidth <= pw); 

    } 

} 
+0

하지만 사용자 인터페이스를 만들기 위해 netbeans IDE를 사용하고 있는데, 어떻게 거기에서 할 수 있을까? – Harsha

+0

그냥 똑같은, 위의 코드를 사용하여 이름이 'MyPrintable' 인 새 클래스를 만듭니다. 그리고 당신의'dataTable = new javax.swing.JTable()'을 JTable snippet – oliholz

+0

으로 바꿔라. printable misbehaves가 그렇게 대단히 믿을 수는 없을 것이다 :-) 그냥 조심하라. 변호사는 사방에 ... – kleopatra