Hallo liebes Java-Forum,
ich habe ein Problem beim Drucken von Grafik-Objekten.
Folgende Aufgabe: Eine ArrayList<String> mit Textzeilen soll ausgedruckt werden. Eine Textzeile besteht aus mehreren Informationen, die durch ### getrennt sind. Die erste Info ist immer der Typ der Zeile (es gibt 7-8 verschiedene Typen, die sich in Fettdruck, Schriftgröße, Tabelle usw. unterscheiden).
Mein Versuche (s.u.) generiert auch schon Seiten mit den Zeilen (bisher habe ich nur die Tabellenzeilen getestet, ist auch das Komplizierteste). Es sollten zwei Seiten mit je 50 Zeilen sein, von 0 bis 99. Das Ergebnis sieht jedoch so aus, dass die erste Seite einfach ein zweites Mal angehängt wird.
Ich habe in der Javadoc von Printable gelesen, dass die Methode print() eine Seite mehrmals aufrufen kann. Ich denke hier liegt der Fehler, ich finde ihn aber nicht.
Javadoc von Printable: "The printing system may request a page index more than once. On each occasion equal PageFormat parameters will be supplied."
Kann mir jemand helfen? Danke im Voraus!
Darkwall
Hier der Code. Ist eine einzige Datei, die ich mit Netbeans erstellt habe und die so lauffähig ist.
ich habe ein Problem beim Drucken von Grafik-Objekten.
Folgende Aufgabe: Eine ArrayList<String> mit Textzeilen soll ausgedruckt werden. Eine Textzeile besteht aus mehreren Informationen, die durch ### getrennt sind. Die erste Info ist immer der Typ der Zeile (es gibt 7-8 verschiedene Typen, die sich in Fettdruck, Schriftgröße, Tabelle usw. unterscheiden).
Mein Versuche (s.u.) generiert auch schon Seiten mit den Zeilen (bisher habe ich nur die Tabellenzeilen getestet, ist auch das Komplizierteste). Es sollten zwei Seiten mit je 50 Zeilen sein, von 0 bis 99. Das Ergebnis sieht jedoch so aus, dass die erste Seite einfach ein zweites Mal angehängt wird.
Ich habe in der Javadoc von Printable gelesen, dass die Methode print() eine Seite mehrmals aufrufen kann. Ich denke hier liegt der Fehler, ich finde ihn aber nicht.
Javadoc von Printable: "The printing system may request a page index more than once. On each occasion equal PageFormat parameters will be supplied."
Kann mir jemand helfen? Danke im Voraus!
Darkwall
Hier der Code. Ist eine einzige Datei, die ich mit Netbeans erstellt habe und die so lauffähig ist.
Java:
package drucken;
import java.awt.Graphics;
import java.awt.print.Book;
import java.awt.print.PageFormat;
import java.awt.print.Paper;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.util.ArrayList;
import java.awt.Font;
import java.awt.FontMetrics;
import javax.swing.JOptionPane;
public class DruckerTest {
private ArrayList<String> inhalt;
private PrinterJob pjob;
int zeilenAbstand = 10;
int sizeHeading1 = 18;
int sizeHeading2 = 14;
int sizeSubtext = 12;
int sizeDefault = 12;
int sizeCopyright = 8;
int sizeLicence = 8;
int sizePrinttime = 8;
int paddingLeft = 2;
private Font headerfont1 = new Font("Arial", Font.BOLD, sizeHeading1);
private Font headerfont2 = new Font("Arial", Font.BOLD, sizeHeading2);
private Font subtextfont = new Font("Arial", Font.PLAIN, sizeSubtext);
private Font textfont = new Font("Arial", Font.PLAIN, sizeDefault);
private Font copyrightfont = new Font("Arial", Font.PLAIN, sizeCopyright);
private Font licencefont = new Font("Arial", Font.PLAIN, sizeLicence);
private Font printtimefont = new Font("Arial", Font.PLAIN, sizePrinttime);
double paperWidth = 8.26; // Breite in inch
double paperHeight = 11.69; // Höhe in inch
double leftMargin = 0.6; // 0.3 in --> 0.762 cm
double rightMargin = 0.6;
double topMargin = 0.6;
double bottomMargin = 0.6;
int letzteZeile = 0;
public int getLetzteZeile() {
return letzteZeile;
}
public void setLetzteZeile(int letzteZeile) {
this.letzteZeile = letzteZeile;
}
private int counter = 0;
private int[] spaltenbreiten;
public static void main(String[] args) {
// Beispiel Spaltenbreiten in %
int[] spaltenbreiten = new int[5];
spaltenbreiten[0] = 20;
spaltenbreiten[1] = 10;
spaltenbreiten[2] = 10;
spaltenbreiten[3] = 20;
spaltenbreiten[4] = 40;
new DruckerTest(spaltenbreiten);
}
public DruckerTest(int[] spaltenbreiten) {
this.spaltenbreiten = spaltenbreiten;
inhalt = new ArrayList<String>();
// Das Array inhalt wird mit 100 Beispielzeilen gefüllt.
// Die Zellinhalte werden mit ### getrennt.
// In der ersten Zelle steht der Typ der Zeile, hier: def
for (int i = 0; i < 100; i++) {
String test = "def###Zeile: " + i+"###Zeläögggle2###Zelle3###Zelgggle4###Zelle5";
System.out.println(test);
inhalt.add(test);
}
try {
getPrinter();
} catch (Exception e) {
JOptionPane.showMessageDialog(null, "Keine Verbindung zum Drucker", "Fehler", JOptionPane.ERROR_MESSAGE);
e.printStackTrace();
}
}
private void getPrinter() throws PrinterException {
System.out.println("GET PRINTER");
pjob = PrinterJob.getPrinterJob();
Paper a4Paper = new Paper();
PageFormat pf = new PageFormat();
a4Paper.setSize(paperWidth * 72.0, paperHeight * 72.0);
a4Paper.setImageableArea(leftMargin * 72.0, topMargin * 72.0,
(paperWidth - leftMargin - rightMargin) * 72.0,
(paperHeight - topMargin - bottomMargin) * 72.0);
pf.setPaper(a4Paper);
System.out.println("+++ PAGESIZE : Höhe: "+ (paperHeight) * 72.0 + " Breite: "+(paperWidth) * 72.0);
System.out.println("+++ PAGEFORMAT: Höhe="+pf.getImageableHeight()+" Breite="+pf.getImageableWidth());
Book book = new Book();
ArrayList<String> temp = new ArrayList<String>();
setLetzteZeile(0);
counter = 0;
int i = 0;
int anzZeilen = 0;
ArrayList<TextPrintable> tpList = new ArrayList<TextPrintable>();
while(i < inhalt.size() && getLetzteZeile() <= inhalt.size()){
// berechne, wie viele Zeilen auf eine Seite passen
anzZeilen = berechneAnzahlZeilen(inhalt, pf);
// erstelle eine ArrayList mit den zu druckenden Zeilen der Seite
i = getLetzteZeile();
while(i < getLetzteZeile()+anzZeilen && inhalt.get(i) != null){
System.out.println("--- Füge hinzu: "+inhalt.get(i));
temp.add(inhalt.get(i));
i++;
}
System.out.println("--- Setze letzte Zeile: "+(getLetzteZeile()+anzZeilen));
setLetzteZeile(getLetzteZeile()+anzZeilen);
// Füge die Seite in die ArrayList der Seiten ein
tpList.add(new TextPrintable(temp));
}
// Füge alle Seiten dem book-Objekt hinzu
for (int j = 0; j < tpList.size(); j++) {
System.out.println("+++ hänge Seite an: "+j);
book.append(tpList.get(j), pf);
}
pjob.setPageable(book);
if (pjob.printDialog()) {
try {
pjob.print();
} catch (Exception PrintException) {
PrintException.printStackTrace();
}
} else {
System.out.println("Printing aborted...");
}
}
private int berechneAnzahlZeilen(ArrayList<String> inhalt, PageFormat pf) {
int i = getLetzteZeile();
int sumHeight = 0;
int zeilenAnzahl = 0;
System.out.println("### berechneAnzahlZeilen ab: "+i+" ImageableHeight="+pf.getImageableHeight());
// Je nach Typ wird die Zeilenhöhe aufsummiert (wegen des obigen Beispiels ist
// nur der letzte Fall (DEF) relevant
while(i < inhalt.size() && sumHeight < pf.getImageableHeight()) { // 40 --> Puffer
if(i < inhalt.size()){
System.out.println("### UNTERSUCHE: "+inhalt.get(i).split("###")[0]+" i="+i);
if(inhalt.get(i).split("###")[0].equalsIgnoreCase("h1")){
System.out.println("### H1 ###");
sumHeight += 22;
} else if(inhalt.get(i).split("###")[0].equalsIgnoreCase("h2")){
System.out.println("### H2 ###");
sumHeight += 17;
} else if(inhalt.get(i).split("###")[0].equalsIgnoreCase("sub")){
System.out.println("### SUB ###");
sumHeight += 15;
} else if(inhalt.get(i).split("###")[0].equalsIgnoreCase("copy")){
System.out.println("### COPY ###");
sumHeight += 10;
} else if(inhalt.get(i).split("###")[0].equalsIgnoreCase("print")){
System.out.println("### PRINT ###");
sumHeight += 10;
} else if(inhalt.get(i).split("###")[0].equalsIgnoreCase("licence")){
System.out.println("### LICENCE ###");
sumHeight += 10;
} else {
System.out.println("### DEF ###");
sumHeight += 15;
}
zeilenAnzahl++;
i++;
}
}
if(sumHeight >= pf.getImageableHeight())
zeilenAnzahl -= 1;
System.out.println("### Zeilenanzahl: "+zeilenAnzahl+" Höhe: "+sumHeight);
return zeilenAnzahl;
}
int lastPageIndex = 0;
class TextPrintable implements Printable {
int[] spaltenbreitenPixel;
FontMetrics fm;
ArrayList<String> list;
public TextPrintable(ArrayList<String> list) {
System.out.println("TEXTPRINTABLE");
this.list = list;
}
public int print(Graphics g, PageFormat pageFormat, int pageIndex) {
System.out.println("PAINT Seite: "+pageIndex + " Lastpageindex="+lastPageIndex);
setLetzteZeile(0);
spaltenbreitenPixel = prozent2pixel(pageFormat, spaltenbreiten);
// Startkoordinaten auf Seite
int x = (int) pageFormat.getImageableX();
int y = (int) pageFormat.getImageableY();
// Rechteck nur zum sehen, wo gedruckt werden kann:
g.drawRect(x, y, (int) pageFormat.getImageableWidth(), (int) pageFormat.getImageableHeight());
System.out.println("Startkoordinaten X="+x+" Y="+y);
// Schleife, die alle Zeilen des Arrays zeichnet:
for (int i = 0; i < list.size(); i++) {
System.out.println("### Zeichne Zeile: "+(getLetzteZeile()+i) + " ###");
y += makeRow(list.get(i), g, x, y);
}
return Printable.PAGE_EXISTS;
}
private int makeRow(String zeile, Graphics g, int x, int y){
// Die Zeilen werden je nach Typ gezeichnet.
String[] temp = zeile.split("###");
if(temp[0].equalsIgnoreCase("h1")){
g.setFont(getFont(temp[0]));
fm = g.getFontMetrics();
y += fm.getAscent() + fm.getDescent() - fm.getLeading();
g.drawString(zeile, x, y);
} else if(temp[0].equalsIgnoreCase("h2")){
g.setFont(getFont(temp[0]));
fm = g.getFontMetrics();
y += fm.getAscent() + fm.getDescent() - fm.getLeading();
g.drawString(zeile, x, y);
} else if(temp[0].equalsIgnoreCase("sub")){
g.setFont(getFont(temp[0]));
fm = g.getFontMetrics();
y += fm.getAscent() + fm.getDescent() - fm.getLeading();
g.drawString(zeile, x, y);
} else if(temp[0].equalsIgnoreCase("copy")){
g.setFont(getFont(temp[0]));
fm = g.getFontMetrics();
y += fm.getAscent() + fm.getDescent() - fm.getLeading();
x = (int) pjob.defaultPage().getImageableWidth()/2 - (int)fm.stringWidth(temp[0])/2;
g.drawString(zeile, x, y);
} else if(temp[0].equalsIgnoreCase("print")){
g.setFont(getFont(temp[0]));
fm = g.getFontMetrics();
y += fm.getAscent() + fm.getDescent() - fm.getLeading();
x = (int) pjob.defaultPage().getImageableWidth()/2 - (int)fm.stringWidth(temp[0])/2;
g.drawString(zeile, x, y);
} else if(temp[0].equalsIgnoreCase("licence")){
g.setFont(getFont(temp[0]));
fm = g.getFontMetrics();
y += fm.getAscent() + fm.getDescent() - fm.getLeading();
x = (int) pjob.defaultPage().getImageableWidth()/2 - (int)fm.stringWidth(temp[0])/2;
g.drawString(zeile, x, y);
} else {
g.setFont(getFont(temp[0]));
fm = g.getFontMetrics();
y += fm.getAscent() + fm.getDescent() - fm.getLeading();
makeTableRow(g, zeile, x, y);
}
return fm.getHeight();
}
private Font getFont(String rowType){
if(rowType.equalsIgnoreCase("h1")){
return headerfont1;
} else if(rowType.equalsIgnoreCase("h2")){
return headerfont2;
} else if(rowType.equalsIgnoreCase("sub")){
return subtextfont;
} else if(rowType.equalsIgnoreCase("copy")){
return copyrightfont;
} else if(rowType.equalsIgnoreCase("print")){
return printtimefont;
} else if(rowType.equalsIgnoreCase("licence")){
return licencefont;
} else {
return textfont;
}
}
/**
* Diese Methode verkürzt den übergebenen String, wenn er länger als die spaltenbreite ist.
* @param ttemp - zu kürzender String
* @param fm - FontMetrics
* @param spaltenbreite - die Spaltenbreite
* @return gekürzter String
*/
private String verkuerzeString (String ttemp, FontMetrics fm, int spaltenbreite) {
String ttemp2 = ttemp;
if(fm.stringWidth(ttemp) >= spaltenbreite){
// String verkürzen
int b = 0;
do {
ttemp2 = ttemp.substring(0, ttemp.length() - b).trim() + "...";
b++;
} while (fm.stringWidth(ttemp2) >= spaltenbreite);
}
ttemp = ttemp2;
return ttemp;
}
/**
* Diese Methode zeichnet eine Tabellenzeile.
* @param g - Graphics
* @param zeile - die Zeile
* @param x - x-Koordinate
* @param y - y-Koordinate
*/
private void makeTableRow(Graphics g, String zeile, int x, int y) {
String[] temp = zeile.split("###");
System.out.println("### ERSTELLE TABELLENZEILE: "+zeile+" temp="+temp.length);
// g.setFont(getFont(temp[0]));
// System.out.println("Schriftart für Tabellenzeile: " + g.getFont().getFamily());
// fm = g.getFontMetrics();
for(int i = 1; i < temp.length; i++){
System.out.println("RECHTECK: x="+x+" y="+y+" b="+spaltenbreitenPixel[i-1]+" h="+fm.getHeight()+" Text: "+temp[i]);
//y = y - fm.getAscent()-fm.getDescent();
g.drawRect(x, y-fm.getHeight()+fm.getLeading()+fm.getDescent()+1, spaltenbreitenPixel[i-1], fm.getHeight());
g.drawString(verkuerzeString(temp[i], fm, spaltenbreitenPixel[i-1]-paddingLeft), x+paddingLeft, y);
x += spaltenbreitenPixel[i-1];
}
}
/**
* Diese Methode wandelt die spaltenbreiten gegeben in % in die Pixel
* der aktuellen ImageableWidth um.
* @param pf - PageFormat
* @param spaltenbreiten - Array mit den Spaltenbreiten in %
* @return Array mit den Spaltenbreiten in Pixeln
*/
private int[] prozent2pixel(PageFormat pf, int[] spaltenbreiten){
int[] pixels = new int[spaltenbreiten.length];
int sum = 0;
for(int i = 0; i < spaltenbreiten.length; i++){
pixels[i] = (int) Math.ceil((pf.getImageableWidth()-leftMargin*72)*1.0*spaltenbreiten[i]*1.0/100.0);
System.out.print(pixels[i]+" ");
sum += pixels[i];
}
// Rundungsfehler beheben
int diff = sum - (int) pf.getImageableWidth();
if(diff > 0)
pixels[pixels.length-1] -= diff;
System.out.println("");
System.out.println("SUMME: "+(sum-diff)+ " BREITE GESAMT: "+pf.getImageableWidth());
return pixels;
}
}
}