Probleme bei JTable-Drucken

Athro

Mitglied
Hallo,
Nach dem ich die folgende JTable-Print-Klasse aufrufe, bekomme ich zwei Druckdialoge (das Seiteneinrichtungsdialog und das Druckdialog), dann bleibt die Anwendung hängen.
Code:
public final class JTablePrintable implements Printable, Pageable{

          private JTable table;
          private JTableHeader header;
          private int printWidth;
          private int headerHeight;
          private int rowHeight;
          private PageFormat defaultPageFormat = new PageFormat();

          private JTablePrintable(JTable t) {
                          table = t;
                          header = table.getTableHeader();
                          printWidth = table.getWidth();
                          headerHeight = header.getPreferredSize().height;
                          rowHeight = table.getRowHeight();
                  }

                  private int getNumberOfRowsByPage() {
                          double tableAvailableSpaceByPage = defaultPageFormat.getImageableHeight()-headerHeight;
                          return((int)Math.floor(tableAvailableSpaceByPage/rowHeight));
                  }

                  private int getTableVerticalShiftForIndex(int index) {
                          int shiftY = (getNumberOfRowsByPage()*rowHeight*index);
                          return(shiftY);
                  }

                  public int getNumberOfPages() {
                          int nbPages = (int)Math.ceil(table.getRowCount()/(double)getNumberOfRowsByPage());
                          return(nbPages);
                  }

                  public PageFormat getPageFormat(int pageIndex) throws IndexOutOfBoundsException {
                          if (pageIndex<1 && pageIndex>getNumberOfPages()) {
                                  throw new IndexOutOfBoundsException("Page "+pageIndex+" doesn't exist!");
                          }
                          else {
                                  return(defaultPageFormat);
                          }
                  }

                  public Printable getPrintable(int pageIndex) throws IndexOutOfBoundsException {
                          if (pageIndex<1 && pageIndex>getNumberOfPages()) {
                                  throw new IndexOutOfBoundsException("Page "+pageIndex+" doesn't exist!");
                          }
                          else {
                                  return(this);
                          }
                  }

                  public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
                          if (pageIndex<1 && pageIndex>getNumberOfPages()) {
                                  return Printable.NO_SUCH_PAGE;
                          }
                          Graphics2D g = (Graphics2D)graphics;
                          double scaleX = pageFormat.getImageableWidth()/printWidth;
                          boolean needScale = scaleX < 1;
                  g.translate(pageFormat.getImageableX(),pageFormat.getImageableY());
                          if (needScale) {
                                  g.scale(scaleX,1);
                          }
                          g.setClip(0,0,printWidth,headerHeight);
                          header.printAll(g);
                          g.translate(0,headerHeight);
                          g.setClip(0,0,printWidth, getNumberOfRowsByPage()*rowHeight);
                          g.translate(0,-getTableVerticalShiftForIndex(pageIndex));
                          table.printAll(g);
                          return Printable.PAGE_EXISTS;
                  }

                  private void startPrinting() {
                          PrinterJob printerJob = PrinterJob.getPrinterJob();
                          printerJob.setJobName("Printing table");
                          defaultPageFormat = printerJob.defaultPage();
                          defaultPageFormat.setOrientation(defaultPageFormat.LANDSCAPE);
                          defaultPageFormat = printerJob.pageDialog(defaultPageFormat);
                          printerJob.setPageable(this);
                          if (printerJob.printDialog()) {
                                  try {
                                          printerJob.print();
                                  }
                                  catch (PrinterException e) {
                                          System.out.println(e);
                                  }
                          }
                  }

                  public static void printTable(JTable t) {
                          JTablePrintable utility = new JTablePrintable(t);
                          utility.startPrinting();
                  }
}
diese Print-Klasse wird von der Hauptprogramm aufgerufen:
Code:
private String data[zeile][spalte];
private String[] spaltenNamen {"aaa", „bbb“, „…“};
…
meinTabelle = new JTable(data, spaltenNamen);
…
      jPanelUnten.add(jButtDruck);
      jButtDruck.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        // Druck die akteulle Tabelle
        JTablePrintable.printTable( (meinTabelle);
      }
    });
 
Hallo Athro,

hab eine Klasse geschrieben die ein JTable sowohl Seitenweise als JPGs speichert und auch druckt. Allerdings habe ich das drucken noch nicht ausprobiert. Das Abspeichern als Bilder scheint OK zu sein. Allerdings ist es nicht grad so einfach ein JTable ordentlich zu drucken. Es kann sowohl von der Breite her als auch von der Höhe größer als eine Seite sein. D.h. die Tabelle muss seitenweise gesplittet werden. Das nächste Problem wäre, das man an den Rändern keine halben Spalten oder Zeilen möchte. Dieses Beispiel soll nur ein erster Ansatz sein, ohne die oben angedeuteten Probleme gänzlich zu lösen.

Java:
import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.awt.print.*;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.table.AbstractTableModel;

public class TablePrinting extends JFrame implements Printable, ActionListener {

	private JTable tabel = new JTable();

	private JScrollPane sPane = new JScrollPane(tabel);

	private JButton btn1 = new JButton("Save as Images");

	private JButton btn2 = new JButton("Print");

	private BufferedImage bImage;

	private List<BufferedImage> bImageList = new ArrayList<BufferedImage>();

	private PageFormat pf = new PageFormat();

	private PrinterJob printerJob = PrinterJob.getPrinterJob();

	private static final int CONS = 1;

	public TablePrinting() {
		super("Print JTable");
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.setLocationByPlatform(true);

		tabel.setModel(new TableModelSimple());
		tabel.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
		btn1.addActionListener(this);
		btn2.addActionListener(this);

		this.add(btn1, BorderLayout.NORTH);
		this.add(sPane, BorderLayout.CENTER);
		this.add(btn2, BorderLayout.SOUTH);

		this.pack();
		this.setVisible(true);
	}

	public static void main(String[] args) {
		new TablePrinting();
	}

	public void actionPerformed(ActionEvent e) {
		bImage = new BufferedImage(tabel.getWidth(), tabel.getHeight(),
				BufferedImage.TYPE_INT_BGR);

		tabel.paint(bImage.getGraphics());

		int wT = bImage.getWidth();
		int hT = bImage.getHeight();

		int w = (int) pf.getImageableWidth();
		int h = (int) pf.getImageableHeight();

		int x = (int) (wT / w);
		int y = (int) (hT / h);

		for (int i = 0; i <= x; i++) {
			for (int j = 0; j <= y; j++) {
				if (i == x && j == y)
					bImageList.add(bImage.getSubimage(i * w, j * h, wT - x * w,
							hT - y * h));
				else if (i == x)
					bImageList.add(bImage.getSubimage(i * w, j * h, wT - x * w,
							h));
				else if (j == y)
					bImageList.add(bImage.getSubimage(i * w, j * h, w, hT - y
							* h));
				else
					bImageList.add(bImage.getSubimage(i * w, j * h, w, h));
			}
		}
		
		if (e.getActionCommand().equals("Print"))
			printAll();
		else saveAll();
	}
	
	public void saveAll(){
		for (int i = 0; i < bImageList.size(); i++) {
			try {
				ImageIO.write(bImageList.get(i), "JPEG", new File("table" + i
						+ ".jpg"));
			} catch (IOException ex) {
				ex.printStackTrace();
			}
		}
	}
	
	public boolean printAll() {
		printerJob.setPrintable(this, pf);
		try {
			printerJob.print();
		} catch (PrinterException e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

	public int print(Graphics g, PageFormat pFormat, int pageIndex)
			throws PrinterException {

		int page = 0;

		Graphics2D g2 = (Graphics2D) g;

		g2.translate((int) pFormat.getImageableX(), (int) pFormat
				.getImageableY());
		g2.scale(1.0 / CONS, 1.0 / CONS);

		g2.drawImage(bImageList.get(page), 0, 0, this);

		page++;

		return page > bImageList.size() ? Printable.PAGE_EXISTS
				: Printable.NO_SUCH_PAGE;
	}

	class TableModelSimple extends AbstractTableModel {
		public int getRowCount() {
			return 100;
		}

		public int getColumnCount() {
			return 20;
		}

		public Object getValueAt(int row, int col) {
			return row + " " + col;
		}
	}
}


Vg Erdal
 
Hallo Erdal,
meine Klasse (die ich eigentlich von Sun-Beispiel kopierte) hat vor einer Woche funktioniert, später habe ich die Spaltennamen mit Zeilenumbruch zerlegt. mit dem Debugger kann man in der JTablePrintable-Klasse die richtigen Spaltennamen und die Zellenwerte finden, aber es wird zu lange in der Warteschlange des Druckers, das Status des Dokumentes wird auf Niedrig gesetzt.
Danke
V.G. Athro
 
der Link wurde nachdem Bestätigung mit "Antworten" geändert ich hoffe klappt es jetzt so:
http://forum.java.sun.com/thread.jspa?forumID=57&threadID=343334
mfg
Athro
 
Hallo Athro,

ich werds mir (vorraussichtlich) heute im Laufe des Tages mal anschauen.

Noch ein Frage vielleicht: Wie sehen denn deine Tabellen aus. Sind sie von der Breite kleiner oder gleich groß wie eine Seite. Oder hast du riesengroße Tabellen.


Vg Erdal
 
Hallo Athro,

poste hier bitte noch eine Beispieltabelle mit den gebrochenen Spaltennamen, das ich dies auch entsprechend ausprobieren kann.


Vg Erdal
 
Hallo Erdal,
Danke für Deine Hilfsbereitschaft.
Da meine Tabellen breit sind, werden die Seite mit Querformat gedruckt, deshalb: „default-PageFormat.setOrientation(defaultPageFormat.LANDSCAPE);“.

Um die Spalten der Tabelle zu berechnen habe ich folgendes implementiert:
PHP:
     /**
      * speichert die Spaltenbreite
      */
 private void setDefaultTableColumn(){
  ...
 for (int i = 0; i < zahlSpalten; ++i) {
         spaltName = spaltenNamen[i];
         // 5.5 Pixel in der Breite = 1 Stelle (bzw. eine Buchstab)
         // int[]spalteBreite = {14, 28, 12, 13, 12, 11, 15, 17, 15, 14, 14, 14, 28};
         SpaltePix =  Math.round(spalteBreite[i] * pixelProStelle);
         // füge ein Zeilenumbruch in der Spaltennamen ein.
         spaltenNamen[i] = spaltName.replaceAll("\n","<BR>");
         // setze die Breite der Spalten bzw. die Tabellenzellenbreite
         meinTabelle.getColumnModel().getColumn(i).setPreferredWidth(SpaltePix);
      }
PHP:
    // Ein Component-Event wird generiert,
    // wenn die Komponentegröße verändert wurde oder wenn sich der
    // Anzeigezustand einer Komponente verändert hat.
    // Da sowohl Fenster als auch alle Dialogelemente aus der Klasse Component abgeleitet sind,
    // haben die hier erwähnten Ereignisse für nahezu alle GUI-Elemente des AWT Gültigkeit.
    this.addComponentListener(new ComponentAdapter() {
      public void componentResized(ComponentEvent e) {
        tableHeaders();
      }
    });
PHP:
  /**
   * erzeugt die Tabellen-Headers bzw. Spaltennamen
   */
  public void tableHeaders(){
    int heightofTableHeader = 0, zahlUmbruch = 1, spHoch = 1;
    setDefaultTableColumn();
    int zahlSpalten = spaltenNamen.length;
    String ColumenName = "";
    int zahlZeilenUmbruch = 0;
    StringTokenizer st;
    spHoch = meinTabelle.getFontMetrics(meinTabelle.getFont()).getHeight();
    for (int i = 0; i < zahlSpalten; ++i) {
      st = new StringTokenizer(spaltenNamen[i], "<BR>");
      zahlZeilenUmbruch = st.countTokens();
      if (zahlZeilenUmbruch > zahlUmbruch){
        heightofTableHeader = spHoch * zahlZeilenUmbruch;
        zahlUmbruch = zahlZeilenUmbruch;
      }
      ColumenName = "<HTML><P ALIGN=\"CENTER\">" + spaltenNamen[i] + "</P><HTML>";
      meinTabelle.getColumnModel().getColumn(i).setHeaderValue(ColumenName);
    }
    // erzeuge die höchste Spaltennamehohe
    meinTabelle.getTableHeader().setPreferredSize(new Dimension(meinTabelle.getTableHeader().getWidth()+1,heightofTableHeader));
    meinTabelle.updateUI();
  }

Danke nochmal
Athro
 
Zurück