JEditorPane Zeilenumbruch in Java7

Zunächst hoffe ich, dass es kein Problem ist, ein neues Thema zu beginnen. Tbh Ich habe keine Ahnung, wie ich eine Frage stellen soll, die auf einer bereits beantworteten basiert, also habe ich das gemacht.

Ich bin mit Java ziemlich neu und mein Problem ist das folgende. Ich schreibe ein kleines Chatprogramm und benutze einJEditorPane mit einemHTMLEditorKit Anzeigen von Text in verschiedenen Farben, Anzeigen von Smileys und Anzeigen von Hyperlinks.

Mein Problem ist, und nachdem ich nachgeforscht habe, dass das Problem möglicherweise auf Java7 zurückzuführen ist, kann ich den Zeilenumbruch nicht richtig zum Laufen bringen. Ich möchte, dass der Text in einem Zeilenumbruch und in der Mitte von Strings umbrochen wird, die die Breite der Komponente überschreiten. Der Zeilenumbruch funktioniert einwandfrei, aber wenn jemand eine ziemlich lange Zeichenfolge eingibt, wird dieJEditorPane wird erweitert und Sie müssen die Größe des Rahmens ändern, um alles auf dem Bildschirm anzuzeigen, was ich nicht tun möchte.

Ich habe ein paar Korrekturen für dieses Problem versucht, aber sie erlauben nur den Zeilenumbruch, sodass der Zeilenumbruch nicht mehr funktioniert. Außerdem möchte ich, dass der Benutzer seinen Text durch Drücken der Eingabetaste umbrechen kann. Dafür füge ich dem Text \ n hinzu und mit den Korrekturen wird das Ergebnis nicht mehr beeinflusst und alles wird in einer Zeile angezeigt.

Ich habe das Gefühl, ich habe Jahre im Internet verbracht, um eine Lösung zu finden, aber jetzt hat nichts für meinen Fall funktioniert, zumal es die ganze Zeit die gleiche Lösung zu sein schien. Ich hoffe ihr könnt mir helfen.

Zusammenfassend bedeutet dies:

Was ich habe:

Zeilenumbruch bei langen, durch Leerzeichen getrennten ZeichenfolgenWenn Sie Windows verwenden und Ihre Eingabe Zeilenumbrüche enthält, die durch Drücken der Eingabetaste erstellt wurden, werden diese ebenfalls umgebrochenWenn Sie eine sehr lange Zeichenfolge ohne Leerzeichen eingeben, wird das Bedienfeld erweitert und Sie müssen die Größe des Rahmens ändernDurch HTML-Formatierung kann ich verschiedene Farben sowie Hyperlinks und Emoticons anzeigen

Was ich brauche:

Zeilenumbruchverhalten wie im Moment, wenn es möglich ist, aber nur bei langen Zeichenfolgen, die nicht durch Leerzeichen voneinander getrennt sind, um zu verhindern, dass das Bedienfeld erweitert wird.Manuell hinzugefügte Zeilenumbrüche durch Drücken der EINGABETASTE im Eingabebereich oder durch Kopieren eines vorformatierten Texts in den EingabebereichHTML-Formatierung wie ich sie schon habe

Was ich ausprobiert habe und was nicht geholfen hat:

jtextpane bricht keinen Text um undJTextPane bricht keinen Text um

Hier ist ein Code, um es selbst zu versuchen. Unten links befindet sich ein Eingabebereich, in den Sie Text eingeben können. Sie können auch Zeilenumbrüche hinzufügen, indem Sie die Eingabetaste drücken. Nach Anklicken des Buttons sehen Sie den Text im oberen Bereich.

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.IOException;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.border.TitledBorder;
import javax.swing.text.BadLocationException;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.StyleSheet;

@SuppressWarnings("serial")
public class LineWrapTest extends JFrame implements ActionListener, KeyListener {

private JButton btnSend;
private JTextArea textAreaIn;
private JEditorPane textAreaOut;
private HTMLEditorKit kit;
private HTMLDocument doc;

public LineWrapTest() {

    this.setSize(600, 500);
    this.setDefaultCloseOperation(EXIT_ON_CLOSE);
    this.setLocationRelativeTo(null);
    this.setTitle("Linewrap Test");
}

/**
 * Not important for problem
 */
public void paintScreen() {

    this.setLayout(new BorderLayout());

    this.add(this.getPanelOut(), BorderLayout.CENTER);
    this.add(this.getPanelIn(), BorderLayout.SOUTH);

    this.textAreaIn.requestFocusInWindow();
    this.setVisible(true);
}

/**
 * Not important for problem
 * 
 * @return panelOut
 */
private JPanel getPanelOut() {

    JPanel panelOut = new JPanel();
    panelOut.setLayout(new BorderLayout());

    this.textAreaOut = new JEditorPane();
    this.textAreaOut.setEditable(false);
    this.textAreaOut.setContentType("text/html");

    this.kit = new HTMLEditorKit();
    this.doc = new HTMLDocument();

    StyleSheet styleSheet = this.kit.getStyleSheet();
    this.kit.setStyleSheet(styleSheet);

    this.textAreaOut.setEditorKit(this.kit);
    this.textAreaOut.setDocument(this.doc);

    TitledBorder border = BorderFactory.createTitledBorder("Output");
    border.setTitleJustification(TitledBorder.CENTER);

    panelOut.setBorder(border);
    panelOut.add(this.textAreaOut);

    return panelOut;
}

/**
 * Not important for problem
 * 
 * @return panelIn
 */
private JPanel getPanelIn() {

    JPanel panelIn = new JPanel();
    panelIn.setLayout(new BorderLayout());

    this.textAreaIn = new JTextArea();
    this.textAreaIn.setLineWrap(true);
    this.textAreaIn.setWrapStyleWord(true);

    TitledBorder border = BorderFactory.createTitledBorder("Input");
    border.setTitleJustification(TitledBorder.CENTER);

    panelIn.setBorder(border);
    panelIn.add(this.getBtnSend(), BorderLayout.EAST);
    panelIn.add(this.textAreaIn, BorderLayout.CENTER);

    return panelIn;
}

/**
 * Not important for problem
 * 
 * @return btnSend
 */
private JButton getBtnSend() {

    this.btnSend = new JButton("Send");
    this.btnSend.addActionListener(this);

    return this.btnSend;
}

private void append(String text) {

    try {
        this.kit.insertHTML(this.doc, this.doc.getLength(), text, 0, 0, null);
    } catch (BadLocationException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

private String getHTMLText() {

    String txtIn = this.textAreaIn.getText().trim().replaceAll(SEPARATOR, "<br/>");

    StringBuffer htmlBuilder = new StringBuffer();

    htmlBuilder.append("<HTML>");
    htmlBuilder.append(txtIn);
    htmlBuilder.append("</HTML>");

    return htmlBuilder.toString();
}

@Override
public void actionPerformed(ActionEvent e) {

    if (e.getSource() == this.btnSend) {
        this.append(this.getHTMLText());
        this.textAreaIn.setText("");
        this.textAreaIn.requestFocusInWindow();
    }
}

public static void main(String[] args) {

    LineWrapTest test = new LineWrapTest();
    test.paintScreen();
}

@Override
public void keyPressed(KeyEvent e) {

    if (e.getKeyCode() == KeyEvent.VK_ENTER)
        if (!this.textAreaIn.getText().trim().isEmpty())
            this.textAreaIn.setText(this.textAreaIn.getText() + SEPARATOR);
}

@Override
public void keyReleased(KeyEvent e) {
}

@Override
public void keyTyped(KeyEvent e) {
}
}

AKTUALISIEREN: stützen sich auf einige Teile vonhttp://java-sl.com/tip_java7_text_wrapping_bug_fix.html

Irgendwie habe ich es herausgefunden, um meinem Ziel ein Stück näher zu kommen. Ich habe versucht, den Fix für ein HTMLEditorKit mit einem StlyedEditorKit-Fix zu kombinieren. Aber ich muss ehrlich sein, ich habe keine Ahnung, was ich dort tatsächlich getan habe :( Das Traurige ist, dass der manuelle Zeilenumbruch damit nicht mehr als Ersatz für das HTMLEditorKit funktioniert. Vielleicht können Sie dies als Basis für eine bessere Umsetzung.

Um es in meinem Beispiel zu verwenden, erstellen Sie einfach eine neue Klasse im Projekt mit dem CustomEditorKit und ersetzen Sie das HTMLEditorKit im Beispiel durch dieses CustomEditorKit. Sie werden feststellen, dass der Zeilenumbruch jetzt funktioniert. Wenn Sie jedoch die EINGABETASTE drücken, um einen eigenen Zeilenumbruch zu erhalten, wird diese Änderung nicht mehr im Ausgabebereich angezeigt und alles wird in einer Zeile angezeigt. Ein weiteres seltsames Problem ist, dass die Linien manchmal aufeinander liegen, wenn Sie die Größe des Rahmens ändern.

import javax.swing.SizeRequirements;
import javax.swing.text.Element;
import javax.swing.text.View;
import javax.swing.text.ViewFactory;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.InlineView;
import javax.swing.text.html.ParagraphView;

@SuppressWarnings("serial")
public class CustomEditorKit extends HTMLEditorKit {

@Override
public ViewFactory getViewFactory() {

    return new HTMLFactory() {
        @Override
        public View create(Element e) {
            View v = super.create(e);
            if (v instanceof InlineView) {
                return new InlineView(e) {
                    @Override
                    public int getBreakWeight(int axis, float pos, float len) {
                        return GoodBreakWeight;
                    }

                    @Override
                    public View breakView(int axis, int p0, float pos, float len) {
                        if (axis == View.X_AXIS) {
                            this.checkPainter();
                            this.removeUpdate(null, null, null);
                        }
                        return super.breakView(axis, p0, pos, len);
                    }
                };
            }
            else if (v instanceof ParagraphView) {
                return new ParagraphView(e) {
                    @Override
                    protected SizeRequirements calculateMinorAxisRequirements(int axis, SizeRequirements r) {
                        if (r == null) {
                            r = new SizeRequirements();
                        }
                        float pref = this.layoutPool.getPreferredSpan(axis);
                        float min = this.layoutPool.getMinimumSpan(axis);
                        // Don't include insets, Box.getXXXSpan will include them. 
                        r.minimum = (int) min;
                        r.preferred = Math.max(r.minimum, (int) pref);
                        r.maximum = Integer.MAX_VALUE;
                        r.alignment = 0.5f;
                        return r;
                    }

                };
            }
            return v;
        }
    };
    }
}

Antworten auf die Frage(2)

Ihre Antwort auf die Frage