Ich habe zwei konkurrierenden Anforderungen für einen Swing-basierten Textarea-Komponente gegeben worden:Wrapping JTextArea bei fester Zeichenbreite
- Muss eine variable Breite Schriftart verwenden (weil es hübsch aussieht).
- Muss Text an einer bestimmten Zeichenbreite wickelt
Ein einfacher zu erreichen Combo (einen Text UI entsprechen), nicht wahr? Hacken Sie eine Benutzeroberfläche, um meine eigene Version einer umhüllten Ansicht bereitzustellen, die von WrappedPlainView erbt, und überschreiben Sie calculateBreakPosition(), um das gewünschte Umbruchverhalten bereitzustellen.
Außer es sieht nicht so einfach aus. Ich ignoriere für den Moment Probleme, die von variablen Renderbreiten herrühren ... Ich finde, dass calculateBreakPosition() nicht für Bearbeitungen aufgerufen wird, von denen ich erwarte, dass sie aufgerufen werden (Hinzufügen von Zeichen zur Vorderseite von umgebrochenem Text), und es wird Pause berechnet Positioniert sich in einigen ziemlich häufigen Szenarios um 1 oder 2, ohne auf meine überschriebene Methode Bezug zu nehmen, was mich zu der Annahme verleitet, dass ich in Optimierungen oder Details der Textbereichsimplementierung laufe, von denen ich nicht genug erwarte. Das Überschreiben mehrerer Methoden zum Debuggen und Beheben dieser Probleme erweist sich als schwierig: Viele der Methoden in WrappedPlainView sind als final oder privat markiert, enthalten Verweise auf com.sun-Klassen und/oder verweisen auf private/final-Methoden oder Methoden mit com.sun-Klassen.
Irgendwelche Vorschläge, um das auf den Weg zu bringen?
Was ich zur Zeit:
package com.foo.inputs;
import java.util.Vector;
import javax.swing.text.BadLocationException;
import javax.swing.text.Element;
import javax.swing.text.WrappedPlainView;
public class CustomWrappedPlainView extends WrappedPlainView
{
private int charsWide;
public CustomWrappedPlainView(Element elem, int width)
{
super(elem, true);
this.charsWide = width;
}
@Override
protected int calculateBreakPosition(int p0, int p1)
{
int length = p1 - p0;
// Check for fit without wrapping.
if(length <= charsWide)
{
return p1;
}
// Given: Past this point, we have at least charsWide+1 characters.
String text;
try
{
// Get one extra character. If wrapping at 5 chars and the/
// first six chars are: '12345 ' then we don't need to split
// anything - that extra char matters.
text = getDocument().getText(p0, charsWide+1);
} catch(BadLocationException err)
{
// Should not happen
// Fall back to max width
return p0 + charsWide;
}
return p0 + getBreakPosition(text, charsWide);
}
/** Determine where to break a substring. */
static protected int getBreakPosition(String text, int charsWide)
{
// Paranoid check to avoid string bound errors
if(text.length() <= charsWide)
{
return text.length();
}
// keep this simple, until/unless we need something more complex.
for(int i = charsWide; i>= 0; i--)
{
char nyble = text.charAt(i);
if(Character.isAlphabetic(nyble))
{
continue;
}
if(Character.isDigit(nyble))
{
continue;
}
if(Character.isWhitespace(nyble))
{
// Wrap AFTER the space.
// Don't start new lines with a space.
return i+1;
}
}
// Fallback: wrap after our break point
return charsWide;
}
/**
* Utility method for CustomTextAreaEditor. Ultimately this must
* match the break logic from {@link #calculateBreakPosition(int, int)}
* exactly to allow for WYSIWYG.
*/
public static String[] breakOutLines(String text, int wrapWidth)
{
String[] paragraphs = text.split("\n");
Vector<String> lines = new Vector<>();
nextParagraph:
for(String paragraph : paragraphs)
{
int length = paragraph.length();
while(length > 0)
{
if(length <= wrapWidth)
{
lines.add(paragraph);
continue nextParagraph;
}
int breakPoint = getBreakPosition(paragraph, wrapWidth);
lines.add(paragraph.substring(0,breakPoint));
paragraph = paragraph.substring(breakPoint);
length = paragraph.length();
}
}
return lines.toArray(new String[0]);
}
}
Irgendeine Rückmeldung? Hat das geholfen? – camickr
Entschuldigung, um darauf zurück zu kommen. Ich vermute, dass es nicht funktioniert (mein Problem ist, dass calculateBreakPosition() nicht aufgerufen wird, damit die darauf basierenden Überschreibungen wahrscheinlich fehlschlagen), aber ich hatte keine Zeit, es richtig auszuprobieren. Angenommen, es funktioniert, dann bin ich damit konfrontiert, dass ich eine Komponente mit fester Breite in einem UI-Framework benötige, das dies nicht zulässt. Die anderen Ansätze, die ich habe, beinhalten ausreichende hyjinks, dass sie wahrscheinlich auf etwas in den Details von JTextArea fehlschlagen würden – epeters