package javacodebook.media.print.text; import java.awt.*; import java.awt.geom.*; import java.awt.print.*; import java.io.*; import javax.swing.*; /** * Die Klasse TextPrinter stellt einen einfachen Rahmen für das Ausdrucken von * Texten zur Verfügung. Eine JEditorPane wird in einer JScrollPane angezeigt, * mit einem einfachen Menü kann eine Datei geöffnet und angezeigt sowie * gedruckt werden. */ public class TextPrinter extends javax.swing.JFrame { private javax.swing.JScrollPane jScrollPane1; private javax.swing.JMenuItem jMenuItem2; private javax.swing.JEditorPane textEditorPane; private javax.swing.JFileChooser fileChooser; private javax.swing.JMenuItem jMenuItem1; private javax.swing.JMenu jMenu1; private javax.swing.JMenuBar jMenuBar1; private String fileName; /** * Der Konstruktor ruft die Methode initComponents() auf und gibt * eine DefaultCloseOperation an. */ public TextPrinter() { initComponents(); setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); } /** * Hier werden die Komponenten auf dem Frame angeordnet. Das Menü wird * aufgebaut und Aktionen für die Menüpunkte angegeben. */ private void initComponents() { fileChooser = new javax.swing.JFileChooser(); jScrollPane1 = new javax.swing.JScrollPane(); textEditorPane = new javax.swing.JEditorPane(); jMenuBar1 = new javax.swing.JMenuBar(); jMenu1 = new javax.swing.JMenu(); jMenuItem1 = new javax.swing.JMenuItem(); jMenuItem2 = new javax.swing.JMenuItem(); setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); addWindowListener(new java.awt.event.WindowAdapter() { public void windowClosing(java.awt.event.WindowEvent evt) { exitForm(evt); } }); textEditorPane.setPreferredSize(new java.awt.Dimension(640, 480)); jScrollPane1.setViewportView(textEditorPane); getContentPane().add(jScrollPane1, java.awt.BorderLayout.CENTER); jMenu1.setText("Datei"); jMenuItem1.setText("\u00d6ffnen"); jMenuItem1.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { showOpenFileDialog(evt); } }); jMenu1.add(jMenuItem1); jMenuItem2.setText("Drucken"); jMenuItem2.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { printDocument(evt); } }); jMenu1.add(jMenuItem2); jMenuBar1.add(jMenu1); setJMenuBar(jMenuBar1); pack(); } /** * Die printDocument-Methode erzeugt einen PrinterJob und eine anonyme * Klasse, die das Interface Printable implementiert. Hier werden alle * Berechnungen für den Ausdruck des Textes vorgenommen. */ private void printDocument(java.awt.event.ActionEvent evt) { try { PrinterJob job = PrinterJob.getPrinterJob(); job.setJobName("Textausdruck - " + fileName); job.setCopies(1); job.setPrintable(new Printable() { /** * Die print()-Methode wird für jede einzelne Seite des Ausdrucks * aufgerufen. Der Parameter pageIndex gibt jeweils an, welche * Seite gedruckt werden soll. Dementsprechend wird der * Grafikbereich gewählt, der ausgedruckt wird. */ public int print(Graphics g, PageFormat pf, int pageIndex) { //Das Graphics-Objekt wird in ein Graphics2D-Objekt gecastet //um auf dessen Methoden zugreifen zu können. Graphics2D g2 = (Graphics2D)g; //Schriftfarbe schwarz g2.setColor(Color.black); //DoubleBuffering in der EditorPane ausschalten textEditorPane.setDoubleBuffered(false); //Jetzt wird die Größe des Druckbereichs berechnet. //Zunächst werden die Maße des Dokuments ermittelt (in Pixel) Dimension d = textEditorPane.getSize(); double editorWidth = d.width; double editorHeight = d.height; //Jetzt werden die Papiermaße ermittelt, die das Papierformat //vorgibt double pageWidth = pf.getImageableWidth(); double pageHeight = pf.getImageableHeight(); //Da die Papiermaße und die EditorPane-Maße wohl selten //übereinstimmen werden, ist ein Skalierungsfaktor notwendig //Die Breite des Textes ist meist größer als die Papierbreite double xScale = pageWidth/editorWidth; //Über die Schriftgröße wird die Zeilenhöhe ermittelt. Damit //keine Zeilen am unteren Rand abgeschnitten werden, muss //eine max. Anzahl Zeilen pro Blatt berechnet werden. Daraus //ergibt sich ein Skalierungsfaktor in der Y-Achse, der etwa //zwischen 1.0 und 1.05 liegt. double fontSize = (double)textEditorPane.getFont().getSize(); int linesPerPage = 1+(int)Math.ceil(pageHeight/fontSize); //Die Zahl 4 ist ein experimentell ermittelter Wert, der //eine minimale zusätzliche Korrektur bewirkt double yScale = (4 + linesPerPage * fontSize) / pageHeight; //Die Anzahl der Seiten für den Druck wird berechnet. Dabei //wird der Skalierungsfaktor berücksichtigt, mit dem die //Breite des Dokuments auf die Papierbreite angepasst wird. int totalNumPages = (int)Math.ceil(xScale*yScale*editorHeight / pageHeight); //Da die Voreinstellung beim Druck gerne "Seite 1 - 9999" //lautet, werden die vielen Leerseiten weggelassen. if(pageIndex >= totalNumPages) return NO_SUCH_PAGE; // Der zu druckende Grafikbereich wird in die linke obere //Ecke des Druckbereichs der Papierseite verschoben, damit //werden die Seitenränder berücksichtigt g2.translate(pf.getImageableX(), pf.getImageableY()); // Der jeweils aktuell zu zeichnende Grafikbereich wird an //den oberen Rand verschoben -> Seitenzahl*Seitenhöhe //Verschiebung also nur in Y-Richtung nach unten g2.translate(0d, -pageIndex*pageHeight); // Der auszugebende Grafikbereich wird so skaliert, dass er //auf das Papier passt g2.scale(xScale, xScale*yScale); //Der Grafikbereich wird für den Druck neu gezeichnet textEditorPane.paint(g2); //DoubleBuffering in der EditorPane wieder einschalen textEditorPane.setDoubleBuffered(true); //Dem Druckjob mitteilen, dass eine Seite für den Druck //existiert return Printable.PAGE_EXISTS; //NO_SUCH_PAGE; // } }); if(job.printDialog() == false) return;//kein Druck, da abgebrochen job.print();//sonst ausdrucken } catch(PrinterException e) { //Fehler in einem Nachrichtenfenster anzeigen JOptionPane.showMessageDialog(this, "Fehler beim Druck" + e, "Druckerfehler", JOptionPane.ERROR_MESSAGE); } } /** * Nach Auswahl einer Datei per Dateidialog wird diese von der JEditorPane * geladen. */ private void showOpenFileDialog(java.awt.event.ActionEvent evt) { int pressedButton = fileChooser.showOpenDialog(this); if(pressedButton == JFileChooser.APPROVE_OPTION) { try { File f = fileChooser.getSelectedFile(); this.fileName = f.getName(); BufferedInputStream in = new BufferedInputStream( new FileInputStream(f)); textEditorPane.read(in, null); in.close(); } catch(IOException e) { e.printStackTrace(System.out); } } } /** Beenden */ private void exitForm(java.awt.event.WindowEvent evt) { System.exit(0); } public static void main(String args[]) { new TextPrinter().show(); } }