我在 JFrame 中使用 JTextArea。我希望制表鍵插入四個空格而不是制表符。
該方法setTabSize不起作用,因為它在文本區域的內容中放置了一個制表符 ('\t')。
每當我按下制表鍵時,如何讓 JTextArea 插入四個空格而不是制表符?這樣,getText() 方法將為每個制表符回傳四個空格的縮進。
uj5u.com熱心網友回復:
我會避免使用 KeyListeners(作為 JTextComponents 的一般規則)甚至鍵系結,因為雖然鍵系結適用于鍵盤輸入,但它不適用于復制和粘貼。
在我看來,最好的方法是使用在 JTextArea 的 Document 上設定的 DocumentFilter(順便說一下,這是一個 PlainDocument)。這樣,即使您將文本復制并粘貼到帶有制表符的 JTextAreas 中,所有制表符也會在插入時自動轉換為 4 個空格。
例如:
import javax.swing.*;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DocumentFilter;
import javax.swing.text.PlainDocument;
public class TestTextArea {
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JTextArea textArea = new JTextArea(20, 50);
JScrollPane scrollPane = new JScrollPane(textArea);
int spaceCount = 4;
((PlainDocument) textArea.getDocument()).setDocumentFilter(new ChangeTabToSpacesFilter(spaceCount));
JFrame frame = new JFrame("GUI");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(scrollPane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
private static class ChangeTabToSpacesFilter extends DocumentFilter {
private int spaceCount;
private String spaces = "";
public ChangeTabToSpacesFilter(int spaceCount) {
this.spaceCount = spaceCount;
for (int i = 0; i < spaceCount; i ) {
spaces = " ";
}
}
@Override
public void insertString(FilterBypass fb, int offset, String string, AttributeSet attr)
throws BadLocationException {
string = string.replace("\t", spaces);
super.insertString(fb, offset, string, attr);
}
@Override
public void remove(FilterBypass fb, int offset, int length) throws BadLocationException {
super.remove(fb, offset, length);
}
@Override
public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs)
throws BadLocationException {
text = text.replace("\t", spaces);
super.replace(fb, offset, length, text, attrs);
}
}
}
所以現在,即使我將帶有標簽的檔案復制并粘貼到 JTextArea 中,所有標簽都會自動替換為spaceCount空格。
uj5u.com熱心網友回復:
這是那些“我想知道是否……”的時刻之一。
就個人而言,我會嘗試從源頭上更直接地解決問題。這意味著以某種方式“捕獲”Tab事件并“替換”它的功能。
因此,我首先修改




我顯然錯過了一些東西......
制表符是四個空格。在這個 "111\t" 字串中,制表符擴展為 1 個空格;"22\t" — 到 2 個空格;"3\t" — 到 3 個空格;最后,“\t”擴展為四個空格。
是的,這不是預期的行為嗎?!
JTextArea, tabSizeof 4, 等距字體

Sublime 文本編輯器,tabSize等距4字體

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Font;
import java.util.StringJoiner;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
StringJoiner textJoiner = new StringJoiner("\n");
for (int row = 0; row < 10; row ) {
StringJoiner rowJoiner = new StringJoiner("\t");
for (int col = 0; col < 10; col ) {
rowJoiner.add(Integer.toString(col).repeat(row));
}
textJoiner.add(rowJoiner.toString());
}
setLayout(new BorderLayout());
JTextArea ta = new JTextArea(10, 40);
ta.setFont(new Font("Monospaced", Font.PLAIN, 13));
ta.setText(textJoiner.toString());
add(new JScrollPane(ta));
}
protected String replicate(char value, int times) {
return new String(new char[times]).replace('\0', value);
}
}
}
我認為您正在考慮“制表位”,而不是“制表符大小”,例如,在這種情況下,即使是DocumentFilter也不會達到您的預期。
我認為問題中暗示了使用等寬字體
不要“假設”我們什么都知道。在我的實驗中,字體不是等寬的。這是提供“預期”和“實際”結果以及最小可重復示例的地方,因為它消除了歧義并且不會浪費每個人的時間(尤其是您的時間)??
這是它在任何文本編輯器中的作業方式。
我顯然在使用不同的文本編輯器??
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/429880.html
