ich möchte einen text oder eine textdatei in java mit einem druckdialog ausdrucken.
hätte da jemand einen beispielcode?
danke.
Ihr seid ja nur neidisch, weil ich der einzige bin, zu dem die leisen Stimmen sprechen! TweakPC IRC Channel: #tweakpc im Quakenet (irc.quakenet.org) Satzzeichen folgen direkt hinter einem Wort. Es ist kein Leerzeichen dazwischen!
Ich will auch von einer Java Applikation aus drucken. Genauer gesagt: Ich hab ne Textarea "taContent" mit einem mehrzeiligen Text. Wie kann ich diesen nun ausdrucken. Hab es schon über die Klasse DocPrint versucht, indem ich als PrintObject einen String übergeben habe, in dem der ganze Text drinsteht. Hat aber nicht geklappt. Er kompiliert zwar alles ohne Fehler, aber wenn ich Auf den Button "Drucken" drücke, dann tut sich nix. Hier der Code:
Auch über die Klasse Print hab ich es versucht. Hier hat er sogar den Inhalt gedruckt, allerdings ohne Leerzeichen und ohne Absätze, also alle Zeichen zusammenhängend. Hier der Code:
also der Code von Dir, tele, hat mir sehr geholfen. Zwar kann ich noch nicht drucken, aber ich denke mit deinem Code bin ich viel näher dran als vorher. Hab nur ein/zwei Konstanten geändert.
(tele & co können jetzt unten weiterlesen)
public void printJob() throws PrinterException {
String content = taContent.getText();
DocFlavor flavor = DocFlavor.INPUT_STREAM.TEXT_PLAIN_US_ASCII;
PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();
aset.add(MediaSizeName.ISO_A4);
PrintService[] pservices =
PrintServiceLookup.lookupPrintServices(flavor, aset);
if (pservices.length > 0) {
DocPrintJob pj = pservices[0].createPrintJob();
// InputStreamDoc is an implementation of the Doc interface //
Doc doc = new InputStreamDoc(content, flavor);
try {
pj.print(doc, aset);
} catch (PrintException e) {
}
}
}
Und dann noch meine neue Klasse inputStreamDoc:
Code:
import javax.print.*;
import javax.print.DocFlavor.STRING;
import javax.print.attribute.*;
import javax.print.attribute.standard.*;
import java.io.*;
class InputStreamDoc implements Doc {
private String filename;
private DocFlavor docFlavor;
private InputStream stream;
public InputStreamDoc(String name, DocFlavor flavor) {
filename = name;
docFlavor = flavor;
}
public DocFlavor getDocFlavor() {
return docFlavor;
}
/* No attributes attached to this Doc - mainly useful for MultiDoc */
public DocAttributeSet getAttributes() {
return null;
}
/* Since the data is to be supplied as an InputStream delegate to
* getStreamForBytes().
*/
public Object getPrintData() throws IOException {
return getStreamForBytes();
}
/* Not possible to return a GIF as text */
public Reader getReaderForText()
throws UnsupportedEncodingException, IOException {
return null;
}
/* Return the print data as an InputStream.
* Always return the same instance.
*/
public InputStream getStreamForBytes() throws IOException {
synchronized(this) {
if (stream == null) {
stream = new FileInputStream(filename);
}
return stream;
}
}
}
Wie gesagt, es funktioniert noch nicht, aber ich denke es müsste schon ungefähr so laufen *hoff*
------------------------------------------------------------------------------------------------------
Aber noch ne Frage (sorry falls die dumm klingt):
In der Methode printJob() hab ich folgende Zeile:
Code:
Doc doc = new InputStreamDoc(content, flavor);
Die Variable content ist ja der String der den Text enthält. Aber der ist doch da falsch stimmts? Ich denke ich kann da keinen String übergeben. tele macht es ja mit einer Datei "test.ps".
Frage: Ich muss also den Text aus der Textarea erst in einem neuen File (z.B. "printTemp.txt") abspeichern und dann dieses File in der Anweisung angeben, oder?
PrintService[] pservices =
PrintServiceLookup.lookupPrintServices(flavor, aset);
if (pservices.length > 0) {
Wenn ich mir dann mal pservices.length ausgeben lasse:
Code:
System.out.println(pservices.length);
dann ist das Ergebnis 0.
Tja klar dass er dann nicht anfängt zu drucken. Dann wollen wir mal schaun wie sich das Prob lösen lässt.
Achja, in der API steht dazu folgendes:
Code:
lookupPrintServices
public static final PrintService[] lookupPrintServices(DocFlavor flavor,
AttributeSet attributes) Locates print services capable of printing the specified DocFlavor.
Parameters:
flavor - the flavor to print. If null, this constraint is not used.
attributes - attributes that the print service must support. If null this constraint is not used.
Returns:
array of matching PrintService objects representing print services that support the specified flavor attributes. If no services match, the array is zero-length.
Also erstmal danke nochmal für eure Hilfe und die supi Codebeispiele .
@ Smash: Ich hab deinen Code grad mal eingebunden und durchrattern lassen --> Ergebnis:
Compiler hat nicht gemeckert
Programm wurde ordnungsgemäß ausgeführt.
Als ich dann auf den Drucken Button geklickt habe, kam der bekannte Druckerauswahl-Dialog. Dann geh ich auf "OK" und es passiert sogar was: Es wird ein Druckauftrag erstellt, allerdings mit dem Status "In Warteschlange". Und dabei bleibt es auch. Er wird nicht ausgedruckt.
Aber immerhin, das ist auch schon was. Bin echt happy, denn vor paar Tagen kam ich nicht mal halb so weit. Ich bleib dran und such weiter nach ner Lösung. Falls ihr das Prob kennt, dann könnt ihr ja 1 oder 2 Zeilen schreiben .
Versuche grad den Fehler zu finden. Hab dabei ein Verständnisproblem bei "Eventlog". Es ist anscheinend eine Möglichkeit Exceptions auszugeben, allerdings meckert mich der Compiler an und sagt: "Eventlog cannot be resolved". Ich muss es also irgendwie noch einbinden. Finde aber keine Möglichkeit wie:
Um den Code zu testen hab ich es mal auskommentiert. Ich brauch doch Eventlog auch nicht zwingend oder?
@ Smash: Konntest du mit diesem Code drucken und wenn ja, wie sieht Dein Aufruf der Methode "static void drucken (PrintJob pjob, Graphics pg, String s)" aus?
Eventlog ist ne Eigenimplementierung. Ne ganz billige Klasse, die nur Strings speichert.
Code:
import java.io.*;
import java.io.File;
/**
* Diese Klasse fängt alle Exceptions und sonstige Ausgaben auf und
* schreibt sie am Ende des Programms in ein Event-Log.
* Sie speichert außerdem den Fortschritt des Parse-Vorgangs.
*
* @author _Smash_
*/
public class Eventlog {
public static StringBuffer fehler = new StringBuffer();
public static StringBuffer log = new StringBuffer();
// Hinzufügen eines Events
public static void add(String string)
{
fehler.append(string);
}
// Hinzufügen eines Logs
public static void addlog(String string)
{
log.append(string);
System.out.print(string);
}
// Erzeugen der Log-Datei
public static void print()
{
try
{
PrintWriter w = new PrintWriter(new FileWriter("eventlog.txt"));
w.print(fehler.toString().replaceAll("\n",System.getProperty("line.separator")));
w.flush();
w.close();
}
catch (IOException ioe)
{;} // Kein Handling, da es selber die Exceptions abspeichert
}
}
Die Imports wirst du nicht alle brauchen.
Sorry, daß ich nicht gleich alles dabei hatte, aber das ist immerhin 2 Jahre her und das stammt auch nicht von mir (von nem Kommilitonen mit dem ich das gemacht habe)
Das Drucken klappt jetzt, allerdings mit einer Einschränkung. Wenn ich über die DIN A4 Seitenbreite hinauskomme, dann hängt sich das Programm beim drucken auf. Also horizontal klappts nicht, aber mehrere Seiten druckt er ohne Probleme.
Ich hab jetzt mal versucht die JTextArea auf DIN A4 zu verkleinern, so dass er automatisch eine neue Zeile beginnt, wenn er an den Rand von DIN A4 kommt. Allerdings hab ich bis jetzt nur den Weg über den Konstruktor der JTextArea gefunden.
Code:
public JTextArea(int rows, int columns)
Constructs a new empty TextArea with the specified number of
rows and columns. A default model is created, and the initial
string is null.
Hat aber leider nicht funktioniert. Weder das Drucken noch die Begrenzung im Programm selbst.
--------------------------------
EDIT:
@ tele: Ich würd dich ja auch gerne pos. bewerten, aber ich "muss leider erst einige andere Benutzer bewerten, bevor ich dich wieder bewerten kann".
Hast du in deinem jetztigen Programm eine Zeile ähnlich derer:
Code:
// kompletter Code siehe erste Seite/Thread
aset.add(MediaSizeName.ISO_A4);
drin?
ÜBer die JTextArea wird das nicht gehen, da die ja nicht dafür da ist - die ist ein Gui Element und hat eigentlich nur über das Toolkit eine Verbindung zur Druckfunktionalität
vielleicht mal in den links stöbern, die ich zu Beginn gepostet hatte, da war eine Preview demo dabei - die könnte helfen
Hm, jo, habs versucht, aber das Prob ist, dass ich ja die Klassen Graphics und PrintJob (nicht mit PrinterJob verwechseln) verwende. Ich kann also aset meines Erachtens nach nicht übergeben, da die 2 Klassen keine Möglichkeit anbieten, Attribute wie aset zu "akzeptieren".
Aber ich versuchs natürlich weiter.
PS:
Im Code wird die Seitenbreite ja auch abgefragt
Code:
int pageWidth = pjob.getPageDimension().width;
Aber das gibt die Breite nur in Pixeln an, was wohl zu dem Fehler führen könnte.
Später im Code steht dann:
Code:
while (fm.stringWidth(nextLine) > (pageWidth - 100)) {...
Ich hab mal den Wert 100 auf 200 hochgesetzt, und dann hat er sogar gedruckt. Allerdings hat er keine neue Zeile angefangen, sondern quasi den Rest einfach abgeschnitten.
habe das Problem gelöst. Vielen Dank an Smash & tele für die super Hilfe.
Geholfen hat mir folgendes Tutorial: LINK
Wer es nicht durcharbeiten will, der kann es ja mit meiner Lösung versuchen. Diese ist aus diesem Tutorial (Listing 4), wobei ich den Code an mein Programm angepasst habe.
Um einen Text zu drucken, könnt ihr folgendes tun:
1. Implementiert die Klasse "Print" in euer Projekt:
Code:
/**
* @author Jean-Pierre Dube <jpdube@videotron.ca>
* @version 1.0
* @since 1.0
*/
import java.awt.*;
import java.awt.font.*;
import java.awt.geom.*;
import java.awt.print.*;
import java.text.*;
public class Print {
//--- Private instances declarations
private final static int POINTS_PER_INCH = 72;
private static String text = new String();
/**
* Constructor
*
*/
public Print(String content) {
//--- String content includes the Text, which should be printed
text = content;
//--- Create a new PrinterJob object
PrinterJob printJob = PrinterJob.getPrinterJob ();
//--- Create a new book to add pages to
Book book = new Book ();
//--- Add the document page using a landscape page format
PageFormat documentPageFormat = new PageFormat ();
documentPageFormat.setOrientation (PageFormat.PORTRAIT);
book.append (new Document (), documentPageFormat);
//--- Tell the printJob to use the book as the pageable object
printJob.setPageable (book);
//--- Show the print dialog box. If the user click the
//--- print button we then proceed to print else we cancel
//--- the process.
if (printJob.printDialog()) {
try {
printJob.print();
} catch (Exception PrintException) {
PrintException.printStackTrace();
}
}
}
private class Document implements Printable {
/**
* Method: print <p>
*
* @param g a value of type Graphics
* @param pageFormat a value of type PageFormat
* @param page a value of type int
* @return a value of type int
*/
public int print (Graphics g, PageFormat pageFormat, int page) {
//--- Create the Graphics2D object
Graphics2D g2d = (Graphics2D) g;
//--- Translate the origin to 0,0 for the top left corner
g2d.translate (pageFormat.getImageableX (), pageFormat.getImageableY ());
//--- Set the drawing color to black
g2d.setPaint (Color.black);
//--- Create a point object to set the top left corner of the TextLayout object
Point2D.Double pen = new Point2D.Double (0.25 * POINTS_PER_INCH, 0.25 * POINTS_PER_INCH);
//--- Set the width of the TextLayout box
double width = 6.0 * POINTS_PER_INCH;
//--- Create an attributed string from the text string. We are creating an
//--- attributed string because the LineBreakMeasurer needs an Iterator as
//--- parameter.
AttributedString paragraphText = new AttributedString (text);
//--- Set the font for this text
paragraphText.addAttribute (TextAttribute.FONT, new Font ("serif", Font.PLAIN, 12));
//--- Create a LineBreakMeasurer to wrap the text for the TextLayout object
//--- Note the second parameter, the FontRendereContext. I have set the second
//--- parameter antiAlised to true and the third parameter useFractionalMetrics
//--- to true to get the best possible output
LineBreakMeasurer lineBreaker = new LineBreakMeasurer (paragraphText.getIterator(), new FontRenderContext (null, true, true));
//--- Create the TextLayout object
TextLayout layout;
//--- LineBreakMeasurer will wrap each line to correct length and
//--- return it as a TextLayout object
while ((layout = lineBreaker.nextLayout ((float) width)) != null) {
//--- Align the Y pen to the ascend of the font, remember that
//--- the ascend is origin (0, 0) of a font. Refer to figure 1
pen.y += layout.getAscent ();
//--- Draw the line of text
layout.draw (g2d, (float) pen.x, (float) pen.y);
//--- Move the pen to the next position adding the descent and
//--- the leading of the font
pen.y += layout.getDescent () + layout.getLeading ();
}
//--- Validate the page
return (PAGE_EXISTS);
}
}
} // Print
2. Nun noch die aufrufende Methode in euer Programm einbinden
Meine sieht so aus:
Code:
public void printJob() {
// content wird der Text der JTextArea "taContent" zugewiesen
String content = taContent.getText();
//Nun wird dieser String an die Klasse "Print" übergeben, die diesen ausdruckt
Print printdoc = new Print(content);
}