Ausdruck einer JTextArea bringt mieses Ergebnis


#1

Hallo zusammen,
ich hänge hier seit geraumer Zeit an einem Problem. Ich habe eine Art Textverarbeitung erstellt. Aus verschiedenen Tabellen einer Datenbank werden Textfelder einer GUI befüllt.
Die Textfelder sollen dann entsprechend zusammengesetzt werden und ausgedruckt. Das mit dem Ausdrucken u.s.w. funktioniert auch hervorragend.
Das größte Problem bereitet mir eine JTextArea, die ich erst zeichnen lasse und dann mit drawImage() in den Ausdruck einbinde.

Code (Java):

scrollPaneText.setBounds(23, 335, 520, 200);
contentPane.add(scrollPaneText);
Haupttext = new JTextArea();
Haupttext.setLineWrap(true);
Haupttext.setWrapStyleWord(true);
scrollPaneText.setViewportView(Haupttext);

//...
bufferedHaupttext = new BufferedImage(Haupttext.getWidth(), Haupttext.getHeight(),
    BufferedImage.TYPE_BYTE_BINARY);
Haupttext.paint(bufferedHaupttext.getGraphics());
g.drawImage(bufferedHaupttext, 30, 390, Haupttext);

Angezeigt wir der Text nun, die Qualität ist allerdings mies.
Ich habe auch andere Optionen wie “TYPE_BYTE_BINARY” ausprobiert, dann wird das Schriftbild zwar besser, aber die Farbe geht mehr ins graue, statt schwarz (ist aber immer noch verschwommen).
Gibt es eine Möglichkeit die paint() - Funktion mit einer höheren Auflösung auszuführen oder ergibt es Sinn die einzelnen Strings in JasperReports zu überführen?

LG Frank


#2

Verstehe ich das richtig: die Darstellung im Ausdruck ist OK, nur am Bildschirm ist’s mies?

Was für eine Auflösung hat denn Dein Bildschirm?

bye
TT


#3

Nein, der Ausdruck der TextArea ist verschwommen. Die Ansicht auf dem Bildschirm ist deutlich.


#4

Ja dann…

Swing-Komponenten sind eben für die Bildschirmausgabe gedacht, nicht für den Druck.

Aus welchem Grund nutzt Du denn überhaupt diese Komponente? Nur um dir das Wordwrapping machen zu lassen? Soll das so 'ne Art WYSIWYG-Ansatz sein?

bye
TT


#5

Drucken ist in Java ein komplizierte Sache vl liegt das ganze an dem Code mit dem du druckst?

Primär druckt Java mit einer 72 Dpi Auflösung.
das könnte das Problem schon erklären


#6

Ich weiß, dass mit 72 dpi eingelesen wird. Die JTextAre wird für die Texteingabe genutzt. Meine Frage war, ob es möglich ist mit höherer Auflösung einzulesen, um dir Qualität des Ausdruck zu erhöhen.


#7

So ganz ist nicht klar, was du machen willst … also, die Details. Es sieht im Moment auch aus, als ob du nicht die Component selbst, sondern nur ihr Bild auf den Bildschirm zeichnest… das wirkt etwas seltsam.

Wie auch immer: Das Graphics, das man von einem BufferedImage bekommt, ist ein Graphics2D, und das kann man beliebig skalieren. Das könnte schon helfen, je nachdem, wie das dann weiterverarbeitet wird.

Hier mal ein Beispiel: Es zeigt eine JTextArea, und hat unten einen JSlider. Mit dem JSlider kann man eine Skalierung einstellen, und rechts wird ein Bild von der text area (mit der entsprechenden Skalierung) gezeichnet:

package bytewelt;

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.image.BufferedImage;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;

public class ScaledComponentPainting
{
    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }

    private static void createAndShowGui()
    {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.getContentPane().setLayout(new BorderLayout());
        
        JPanel panel = new JPanel(new GridLayout(1,2));
        
        JTextArea textArea = new JTextArea();
        textArea.setLineWrap(true);
        textArea.setWrapStyleWord(true);
        for (int i=0; i<100; i++)
        {
            textArea.append("All work and no play makes Marco13 a dull boy. ");    
        }
        panel.add(textArea);

        ImagePanel imagePanel = new ImagePanel();
        panel.add(imagePanel);
        
        f.getContentPane().add(panel, BorderLayout.CENTER);
        
        JPanel controlPanel = new JPanel(new FlowLayout());
        JSlider slider = new JSlider(0, 100, 0);
        slider.addChangeListener(e -> 
        {
            int value = slider.getValue();
            double alpha = value / 100.0;
            double scaling = 1.0 + alpha * 2.0;
            BufferedImage image = createImage(textArea, scaling);
            imagePanel.setImage(image);
        });
        controlPanel.add(slider);
        SwingUtilities.invokeLater(() -> slider.setValue(50));
        
        f.getContentPane().add(controlPanel, BorderLayout.SOUTH);
        
        f.setSize(1000, 500);
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }
    
    private static class ImagePanel extends JPanel
    {
        private BufferedImage image;
        
        public void setImage(BufferedImage image)
        {
            this.image = image;
            repaint();
        }
        
        @Override
        protected void paintComponent(Graphics g)
        {
            super.paintComponent(g);
            if (image != null)
            {
                g.drawImage(image, 0, 0, null);
            }
        }
    }
    
    private static BufferedImage createImage(
        JComponent component, double scaling)
    {
        int w = component.getWidth();
        int h = component.getHeight();
        int sw = (int)Math.ceil(w * scaling);
        int sh = (int)Math.ceil(h * scaling);
        
        BufferedImage image = 
            new BufferedImage(sw, sh, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g = image.createGraphics();
        g.scale(scaling, scaling);
        component.printAll(g);
        g.dispose();
        return image;
    }
}

All work and no play…


#8

Hallo Marco,

es ist genau wie du es schreibst, es soll der Inhalt der JTextArea in den Brief übernommen werden.
Ich habe in der GUI verschiedene Textfelder und zwei TextAreas. Die werden teilweise beim Aufrufen aus einer Datenbank befüllt.
Wenn ich das Ausdrucke habe ich mir eine Seite zusammengebaut. Als Briefkopf und Brieffuss wird eine eine Grafik eingefügt. Bei den Textfeldern wird mit .getText() ein String ausgelesen und dieser mit drawString() an die entsprechende Position im Brief eingefügt. Die Qualität des Ausdrucks und der Bildschirmansicht ist dann auch absolut OK
Bei der JTextArea war meine Idee, diese quasi als WYSIWYG in den Brief einzufügen. Daher wurde der Inhalt als BufferedImage “ausgelesen” und mit drawImage() eingefügt.
Durch die automatischen Zeilenumbrüche in der TextArea funktioniert das zeilenweise auslesen nicht.
Ich überlege im Moment ob ich die beiden Methoden (Haupttext.setLineWrap(true); Haupttext.setWrapStyleWord(true):wink: herausnehme und den Text bis zum nächsten “\n” auslese und die automatischen Zeilenumbrüche vor dem letzten Leerzeichen einer bestimmten Textlänge durch eine “\n” ersetze. Nach diesen kann ich den String dann mit .split aufteilen und die einzelnen Zeilen mit drawString() einfügen.

Jetzt verständlich?

LG Frank


#9

So grob. Du hattest ganz oben “JasperReports” erwähnt. Das ist zwar sehr bekannt (mir zumindest vom Namen her, und das will schon was heißen :wink: ), aber gemacht habe ich damit noch nichts. Wird das denn intern schon verwendet? Eine Naive Websuche liefert das erste Beispiel unter http://jasperreports.sourceforge.net/sample.reference/printservice/index.html , wo ja auch ein Text ausgegeben zu werden scheint, das so lang ist, dass er wohl Zeilenumbrüche enthalten muss. Mir ist jetzt noch nicht klar, warum da was über eine TextArea und ein BufferedImage läuft, wenn diese Funktionalität ja eigentlich schon angeboten wird…


#10

Hallo,

das mit dem Jasper Report wird in verschiedenen Foren immer mal wieder ins Spiel gebracht, wenn es um Drucken aus Java geht.
Ich habe mir mal das Eclipse - Plugin heruntergeladen und mir angeschaut. Du baust damit im Prinzip deine eigene (auszudruckende Seite) einmal zusammen und die wird dann jedes mal neu generiert.
Ich finde das halt sehr umfangreich und das kann viel mehr als ich brauche. Vor allem muss ich mich erst in die Sprache einarbeiten.
Wie es das bis jetzt verstanden habe, muss ich jeden String in eine HashMap “umwandeln” und dann wie auch immer an Jasper Report übergeben. Um diese Variablen dann da (ähnlich XML) in die zuvor angelegten Textfelder einzufügen.
An irgend einem Punkt kann ich dann entscheiden ob ich die Seite als Ausdruck, .html, .pdf oder was auch immer haben möchte.
Einfacher wäre es halt die TextArea vernünftig einzulesen.

LG Frank


#11

OK. Und … inwieweit funktioniert das mit dem “skalierten BufferedImage” nicht?


#12

Hallo,

die Qualität des BufferedImage ist zu schlecht. Ich habe mal ein .jpg angehangen. Dann ist das relativ leicht ersichtlich.
Die Textbausteine und Grafiken oben und unten (waren bevor sie in ein .jpg umgewandelt wurden) klar strukturiert und deutlich. Der Text des Briefes nicht.


#13

Sieht ja echt Katastrophal aus.

Bis jetzt habe ich, wenn ich Dokumente generiert habe immer PDF als Ausgabemedium genutzt und dann das PDF gedruckt.

Entweder direktes PDF generieren mit entweder
iText - gut, aber problematisch mit den Lizenzen, besser alte Version nutzen (unterstützt auch automatische Zeilenumbrüche)
Apache - PDFBox, einfachere Lizenzen, Zeilenumbrüche müssen selbst geregelt werden. Finden sich aber Beispiele auf Stackoverflow.

Reports via BIRT (Eclipse Version von Jasper Reports), gut wenn man eben Reports braucht oder auch Excel und sowas abdecken möchte. Das praktische daran ist, dass man da seine Datenquelle, wie oben genannt die HashMap, die befüllt wird vom Rest getrennt hat. Da kann man dann auch zum Beispiel Datenbank-Querrys als Datenquelle nutzen. Das Layout, kann man dann auch in einem Designer zusammenklicken und mit ein bisschen Gluecode laufen lassen, wobei dann direkt die Daten aus der Datenbank geholt werden.

Oder eben OpenOffice, das auch eine Vernünftige Java Anbindung hat und dort sein Dokument zusammenstellen.

Und Grafiken, wenn in Java selbst gezeichnet zum Beispiel ein Chart, eben das Image zeichnen lassen, als JPG exportieren und dann dieses im PDF einfügen.

Aber die Druckfunktion aus Java direkt war mir immer irgendwie suspekt.

Vielleicht ist ja doch was passenderes dabei.


#14

die Ausgabe deiner JTextArea ist (schrecklich) skaliert in deinem Brief. DPI JtextArea != DPI Brief. Du musst das Image der JTextArea schon in der passenden DPI haben.


#15

Hallo, ich denke dass es Birt herauslaufen wird (wusste gar nicht dass es so heißt). Habe dazu aber auch jetzt deutsche Anleitungen gefunden. Bei den langes gibt es kein Problem, da die lokal gespeichert sind und nur der absolute Pfad übergeben wird. Dann muss ich halt in den sauren Apfel beißen und mich da reinarbeiten.
LG Frank


#16

Es ist immer noch nicht klar, was passiert, wenn du (wie oben im compilierbaren Beispiel) das Bild einfach 5x so groß machst, wie die TextArea, und die TextArea dann mit einem skalierten Graphics2D dort reinzeichnest. Das sollte gut aussehen.


#17

Ich habe in der Regel LaTeX Code erzeugt und mit dem Programm einen schönen Output erzeugt.


#18

Hallo Marko,
ich habe nicht genau verstanden wie du das meinst. mit dem Code kann ich das schlechte Bild vergrößern. Ich müsste ja im Prinzip die JTextArea vorher im GUI 5 -fach vergrößern (2600 * 1000 px), dann passt es aber nicht mehr auf den Bildschirm. oder stehe ich jetzt auf dem Schlauch.
Was mit fehlt ist die Möglichkeit, die JTextArea mit 5-facher Auflösung auszulesen und und dann wieder (verkleinert) in den Brief einzufügen.

LG Frank


#19

Hallo Crian,

hast du irgendwelche Links zu dem Thema?


#20

Kannst du mal den Code posten, wo das BufferedImage in “das eingefügt wird, was du ausdruckst”?