Линейная оболочка JEditorPane в Java7
Прежде всего, я надеюсь, что это не проблема, я начал новую тему. Я понятия не имею, как задать вопрос, основанный на уже отвеченном вопросе, поэтому я сделал это.
Я довольно новичок в Java, и моя проблема заключается в следующем. Я пишу небольшую программу чата и используюJEditorPane
сHTMLEditorKit
отображать текст разными цветами, отображать смайлики и гиперссылки.
Моя проблема в том, что после некоторых исследований я обнаружил, что проблема может быть связана с Java7, я не могу заставить работать linewrap должным образом. Я хочу, чтобы текст переносился по словам и переносился по середине строк, превышающих ширину компонента. Обтекание словом работает хорошо, но если кто-то набирает довольно длинную строку,JEditorPane
расширяется, и вам нужно изменить размер кадра, чтобы вывести все на экран, чего я не хочу, чтобы происходило.
Я пробовал несколько исправлений для этой проблемы, но они разрешают перенос букв только так, чтобы перенос слов больше не работал. Кроме того, я хочу, чтобы пользователь мог обернуть свой текст, нажав Enter. Для этого я добавляю \ n к тексту, и с исправлениями это больше не повлияет на результат, и все будет отображаться в одной строке.
У меня такое чувство, что я потратил годы в Интернете, чтобы найти решение, но сейчас у меня ничего не получалось, особенно если учесть, что это все время было одно и то же. Я надеюсь, что вы, ребята, можете мне помочь.
В итоге это означает:
Что у меня есть:
Строка переносит слово в случае длинных строк, разделенных пробеламиЕсли вы используете Windows, и ваш ввод содержит переносы строк, созданные нажатием Enter, они также переносятсяЕсли вы введете очень длинную строку без пробелов, панель раскроется, и вам нужно изменить размер фреймаФорматирование HTML позволяет отображать различные цвета, а также гиперссылки и смайлики.Что мне нужно:
Поведение переноса слов, как сейчас, в случае, если это возможно, перенос букв только в случае длинных строк, не разделенных пробелами, чтобы предотвратить расширение панели.Вручную добавили переносы строк, нажав клавишу ВВОД в области ввода или если я скопировал предварительно отформатированный текст на панель вводаФорматирование HTML как у меня ужеЧто я пробовал и что не помогло:
jtextpane не переносит текст а такжеJTextPane не является переносом текста
Вот некоторый код, чтобы попробовать это самостоятельно. В левом нижнем углу находится область ввода для ввода текста. Вы также можете добавить переносы строк, нажав Enter. После нажатия на кнопку вы увидите текст в области выше.
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) {
}
}
ОБНОВИТЬ: основываться на некоторых частяхhttp://java-sl.com/tip_java7_text_wrapping_bug_fix.html
Каким-то образом я решил сделать шаг ближе к своей цели. Я попытался объединить исправление для HTMLEditorKit с исправлением StlyedEditorKit. Но я должен быть честным, я не имею ни малейшего представления о том, что я на самом деле сделал там :( Печально то, что ручная перенос строки больше не работает с этим как замена HTMLEditorKit. Может быть, вы можете использовать это как основа для лучшей реализации.
Чтобы использовать его в моем примере, просто создайте новый класс в проекте с CustomEditorKit и замените HTMLEditorKit в примере этим CustomEditorKit. Вы заметите, что перенос слов и букв теперь работает, но если вы нажмете ENTER, чтобы получить собственную перенос строк, это изменение больше не будет отображаться на панели вывода, и все будет отображаться в одной строке. Еще одна странная проблема заключается в том, что если вы измените размер рамки, линии иногда будут лежать друг на друге.
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;
}
};
}
}