Прежде всего, я надеюсь, что это не проблема, я начал новую тему. Tbh Я понятия не имею, как задать вопрос, основанный на уже отвеченном, поэтому я сделал это.
Я новичок в Java, и моя проблема заключается в следующем. Я пишу небольшую программу для чата и использую JEditorPane
с HTMLEditorKit
для отображения текста разными цветами, для отображения смайлов и отображения гиперссылок.
Моя проблема в том, что после некоторых исследований я обнаружил, что проблема может быть связана с Java7, я не могу заставить перенос строк работать должным образом. Я хочу, чтобы текст переносился по словам и переносился в середине строк, превышающих ширину компонента. Перенос слов работает нормально, но если кто-то вводит довольно длинную строку, JEditorPane
расширяется, и вам нужно изменить размер фрейма, чтобы все отображалось на экране, чего я не хочу.
Я пробовал несколько исправлений для этой проблемы, но они позволяют только перенос букв, так что перенос слов больше не работает. Кроме того, я хочу, чтобы пользователь мог переносить свой текст, нажимая Enter. Для этого я добавляю \n к тексту, и с исправлениями это больше не повлияет на результат, и все будет отображаться в одной строке.
У меня такое ощущение, что я провел годы в Интернете, чтобы найти решение, но пока ничего не помогло в моем случае, тем более, что это все время было одно и то же исправление. Я надеюсь, что вы, ребята, можете мне помочь.
Вкратце это означает:
Что у меня есть:
- Строка переносит слова в случае длинных строк, разделенных пробелами
- если вы используете Windows, и ваш ввод содержит переносы строк, созданные нажатием Enter, они также будут переноситься
- Если вы введете очень длинную строку без пробелов, панель будет расширена, и вам придется изменить размер рамки.
- Форматирование HTML позволяет отображать различные цвета, а также гиперссылки и смайлики.
Что мне нужно:
- Поведение переноса слов, как на данный момент, в случае, если это возможно, но перенос букв ТОЛЬКО в случае длинных строк, не разделенных пробелами, чтобы предотвратить расширение панели.
- Добавленные вручную переносы строк, сделанные нажатием ENTER в области ввода или копированием предварительно отформатированного текста на панель ввода
- Форматирование 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;
}
};
}
}