Я работаю над созданием текстового редактора, написанного на Java, и я решил использовать JTextPane вместо JTextArea, потому что это позволит мне создавать расширенный текстовый редактор с использованием различных цветовых схем.Однако JTextPane не имеет функции setTabSize (int size), но я могу использовать TabStops и TabSet для достижения этой цели.
Моя первая попытка
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import javax.swing.*;
import javax.swing.text.AttributeSet;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;
import javax.swing.text.TabSet;
import javax.swing.text.TabStop;
public class Editor extends JFrame {
JTextPane txt;
public Editor() {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
RichTextEdit rte = new RichTextEdit();
txt = new JTextPane(rte);
txt.setPreferredSize(new Dimension(400,200));
add(new JScrollPane(txt));
Font f = new Font("Monospaced", Font.PLAIN, txt.getFont().getSize());
txt.setFont(f);
FontMetrics fm = txt.getFontMetrics(f);
int width = fm.stringWidth("w");
int tabSize = 4;
TabStop[] tabs = new TabStop[1];
tabs[0] = new TabStop(width*tabSize, TabStop.ALIGN_LEFT, TabStop.LEAD_NONE);
TabSet tabset = new TabSet(tabs);
StyleContext cont = StyleContext.getDefaultStyleContext();
AttributeSet a = cont.addAttribute(SimpleAttributeSet.EMPTY,
StyleConstants.TabSet, tabset);
txt.setParagraphAttributes(a, false);
this.pack();
this.setLocationRelativeTo(null);
this.setVisible(true);
}
}
Эта попытка работает толькокогда курсор находится в начале документа.Если я начинаю что-то печатать в JTextPane, то нажимаю tab, он перемещается только на 4-ю позицию.Таким образом, если я наберу две буквы, каретка перемещается только на две буквы при нажатии на вкладку.Затем после этого он перемещает только один символ на каждое нажатие.
Моя вторая попытка: все, что я сделал, это добавил еще одну вкладку, и это сработало, если я дважды нажимал на вкладку в строке, если на ней нет других символов.линия.По сути, так же, как и моя первая попытка, за исключением того, что она позволяла нажимать две вкладки (равные 8 символам в длину)
TabStop[] tabs = new TabStop[2];
tabs[0] = new TabStop(width * tabSize, TabStop.ALIGN_LEFT, TabStop.LEAD_NONE);
tabs[1] = new TabStop(width * tabSize * 2, TabStop.ALIGN_LEFT, TabStop.LEAD_NONE);
Мне пришлось умножить вторую вкладку на 2, чтобы заставить пространство вкладок перемещаться еще на 4длина символов.
Моя последняя попытка состояла в том, чтобы получить количество символов в данной строке.(Я выполнил) Затем добавить 4 символа в эту строку.Итак, если пользователь набрал: 123456 в JTextPane и нажал на вкладку, он просто добавит 4 пробела в конец, но я продолжаю получать сообщение об ошибке при попытке установить setParagraphAttributes после начальной установки.Поэтому я думаю, что у него уже есть AttributeSet, затем либо измените значение, либо удалите AttributeSet, а затем добавьте его с обновленным TabSize.Это то, что у меня есть до сих пор:
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.util.Enumeration;
import javax.swing.*;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.Element;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;
import javax.swing.text.TabSet;
import javax.swing.text.TabStop;
import javax.swing.text.Utilities;
public class Editor extends JFrame {
JTextPane txt;
public Editor() {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
RichTextEdit rte = new RichTextEdit();
txt = new JTextPane(rte);
txt.setPreferredSize(new Dimension(400,200));
add(new JScrollPane(txt));
txt.setFont(new Font("Monospaced", Font.PLAIN, 16));
txt.addCaretListener(new CaretListener() {
@Override
public void caretUpdate(CaretEvent arg0) {
// TODO Auto-generated method stub
Update();
}
});
Update();
this.pack();
this.setLocationRelativeTo(null);
this.setVisible(true);
}
public void Update() {
int caretPosition = txt.getCaretPosition();
Element root = txt.getDocument().getDefaultRootElement();
int n = root.getElementIndex(caretPosition) + 1;
Element child = root.getElement(n-1);
int start = child.getStartOffset();
int end = child.getEndOffset();
int length = end - start;
int j = (length >0) ? length - 1 : 0;
System.out.println(n);
System.out.println(caretPosition);
System.out.println(j);
System.out.println("----------");
Font f = new Font("Monospaced", Font.PLAIN, txt.getFont().getSize());
FontMetrics fm = txt.getFontMetrics(f);
int width = fm.stringWidth("w");
int tabSize = (j > 0) ? j + 4 : 4;
TabStop[] tabs = new TabStop[1];
tabs[0] = new TabStop(width * tabSize, TabStop.ALIGN_LEFT, TabStop.LEAD_NONE);
TabSet tabset = new TabSet(tabs);
StyleContext cont = StyleContext.getDefaultStyleContext();
AttributeSet a = cont.addAttribute(SimpleAttributeSet.EMPTY, StyleConstants.TabSet, tabset);
txt.setParagraphAttributes(a, true);
}
}
Я получаю IllegalStateException в этой строке txt.setParagraphAttributes(a,true);
, когда я вызываю функцию обновления из caretListener