当用户按 Enter 时禁用 JTextArea 调整大小
Disabling JTextArea resizing when user press Enter
我有一个 JTextArea
,我希望用户输入一个人的地址。我知道用户将输入的有效地址不会超过 5 rows
和 10 columns
。所以我将它设置为 JTextArea (5,10)
。这样就很好用了。
问题是,当用户持续按 enter
超过 5 次时,文本区域将开始调整大小。我不想将文本区域放在 JScrollPane
中,因为用户输入的文本不适合滚动。
问题:我们如何禁止 JTextArea
在用户按下 enter
时调整大小?
这是我的代码:
public class JTextAreaDemo {
private JFrame frame;
JTextAreaDemo(){
frame= new JFrame();
frame.setSize(300, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new net.miginfocom.swing.MigLayout());
frame.setVisible(true);
frame.setLocationRelativeTo(null);
JLabel label=new JLabel("Address :");
JTextArea address= new JTextArea(5,20);
frame.add(label,"cell 0 0");
frame.add(address, "cell 1 0");
}
public static void main(String [] args){
SwingUtilities.invokeLater(new Runnable(){
@Override
public void run() {
new JTextAreaDemo();
}});
}
}
使用 setPreferredSize(new Dimension(X,Y))
以便 JTextArea 将保持您设置的尺寸,并且根本不会移动!
您仍然需要将 JTextArea 放在 JScrollPane
思想中。
我建议您使用 InputVerifier
来跟踪您 JTextArea
中输入的输入次数,当它达到 4 时,它应该忽略输入。
正如您在评论中指出的那样,DocumentListener
会做同样的事情,KeyListener
也会做同样的事情。
您可以尝试使用DocumentFilter
,例如:
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.text.AbstractDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DocumentFilter;
public class TestFrame extends JFrame {
public static void main(String... s) {
new TestFrame();
}
private JTextArea area;
public TestFrame() {
init();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setLocationRelativeTo(null);
setVisible(true);
}
private void init() {
area = new JTextArea();
((AbstractDocument)area.getDocument()).setDocumentFilter(getFilter(5));
add(new JScrollPane(area));
}
private DocumentFilter getFilter(final int lineCount) {
return new DocumentFilter(){
@Override
public void replace(FilterBypass fb, int offset, int length,
String text, AttributeSet attrs)
throws BadLocationException {
if(area.getLineCount()<=lineCount && area.getLineOfOffset(area.getCaretPosition())<lineCount)
if(text.contains("\n") && area.getLineCount()<lineCount)
super.replace(fb, offset, length, text, attrs);
else if(!text.contains("\n"))
super.replace(fb, offset, length, text, attrs);
}
};
}
}
如前所述,可以使用DocumentFilter
。我 post 这个答案是因为它提供了优雅的解决方案。
public class JTextAreaDemo {
private JFrame frame = new JFrame();
JTextArea address = new JTextArea(5, 20);
JTextAreaDemo() {
JLabel label = new JLabel("Address :");
frame.getContentPane().add(label, BorderLayout.CENTER);
frame.getContentPane().add(address, BorderLayout.SOUTH);
((PlainDocument) address.getDocument()).setDocumentFilter(new LineFilter());
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
class LineFilter extends DocumentFilter {
@Override
public void insertString(FilterBypass fb, int offset, String string, AttributeSet attr) throws BadLocationException {
if (address.getLineCount() < 5 || !string.contains("\n"))
super.insertString(fb, offset, string, attr);
}
@Override
public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException {
if (address.getLineCount() < 5 || !text.contains("\n"))
super.replace(fb, offset, length, text, attrs);
}
}
public static void main(String[] args) {
new JTextAreaDemo();
}
}
虽然用户输入覆盖方法 insertString
不相关,但覆盖所有基础通常是个好主意。否则可以去掉。
请注意,不需要 JScrollBar
。
编辑:
为了让@MadProgrammer 在晚上安静地睡觉,行计数是直接从文档中完成的(以不太优雅的方式):
@Override
public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException {
String content = fb.getDocument().getText(0, fb.getDocument().getLength());
Matcher matcher = Pattern.compile("\n").matcher(content);
int lines = 0;
while (matcher.find()) {
lines++;
}
if (lines < 4 || !text.contains("\n"))
super.replace(fb, offset, length, text, attrs);
}
insertString
方法可以使用相同的代码。
我有一个 JTextArea
,我希望用户输入一个人的地址。我知道用户将输入的有效地址不会超过 5 rows
和 10 columns
。所以我将它设置为 JTextArea (5,10)
。这样就很好用了。
问题是,当用户持续按 enter
超过 5 次时,文本区域将开始调整大小。我不想将文本区域放在 JScrollPane
中,因为用户输入的文本不适合滚动。
问题:我们如何禁止 JTextArea
在用户按下 enter
时调整大小?
这是我的代码:
public class JTextAreaDemo {
private JFrame frame;
JTextAreaDemo(){
frame= new JFrame();
frame.setSize(300, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new net.miginfocom.swing.MigLayout());
frame.setVisible(true);
frame.setLocationRelativeTo(null);
JLabel label=new JLabel("Address :");
JTextArea address= new JTextArea(5,20);
frame.add(label,"cell 0 0");
frame.add(address, "cell 1 0");
}
public static void main(String [] args){
SwingUtilities.invokeLater(new Runnable(){
@Override
public void run() {
new JTextAreaDemo();
}});
}
}
使用 setPreferredSize(new Dimension(X,Y))
以便 JTextArea 将保持您设置的尺寸,并且根本不会移动!
您仍然需要将 JTextArea 放在 JScrollPane
思想中。
我建议您使用 InputVerifier
来跟踪您 JTextArea
中输入的输入次数,当它达到 4 时,它应该忽略输入。
正如您在评论中指出的那样,DocumentListener
会做同样的事情,KeyListener
也会做同样的事情。
您可以尝试使用DocumentFilter
,例如:
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.text.AbstractDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DocumentFilter;
public class TestFrame extends JFrame {
public static void main(String... s) {
new TestFrame();
}
private JTextArea area;
public TestFrame() {
init();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setLocationRelativeTo(null);
setVisible(true);
}
private void init() {
area = new JTextArea();
((AbstractDocument)area.getDocument()).setDocumentFilter(getFilter(5));
add(new JScrollPane(area));
}
private DocumentFilter getFilter(final int lineCount) {
return new DocumentFilter(){
@Override
public void replace(FilterBypass fb, int offset, int length,
String text, AttributeSet attrs)
throws BadLocationException {
if(area.getLineCount()<=lineCount && area.getLineOfOffset(area.getCaretPosition())<lineCount)
if(text.contains("\n") && area.getLineCount()<lineCount)
super.replace(fb, offset, length, text, attrs);
else if(!text.contains("\n"))
super.replace(fb, offset, length, text, attrs);
}
};
}
}
如前所述,可以使用DocumentFilter
。我 post 这个答案是因为它提供了优雅的解决方案。
public class JTextAreaDemo {
private JFrame frame = new JFrame();
JTextArea address = new JTextArea(5, 20);
JTextAreaDemo() {
JLabel label = new JLabel("Address :");
frame.getContentPane().add(label, BorderLayout.CENTER);
frame.getContentPane().add(address, BorderLayout.SOUTH);
((PlainDocument) address.getDocument()).setDocumentFilter(new LineFilter());
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
class LineFilter extends DocumentFilter {
@Override
public void insertString(FilterBypass fb, int offset, String string, AttributeSet attr) throws BadLocationException {
if (address.getLineCount() < 5 || !string.contains("\n"))
super.insertString(fb, offset, string, attr);
}
@Override
public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException {
if (address.getLineCount() < 5 || !text.contains("\n"))
super.replace(fb, offset, length, text, attrs);
}
}
public static void main(String[] args) {
new JTextAreaDemo();
}
}
虽然用户输入覆盖方法 insertString
不相关,但覆盖所有基础通常是个好主意。否则可以去掉。
请注意,不需要 JScrollBar
。
编辑:
为了让@MadProgrammer 在晚上安静地睡觉,行计数是直接从文档中完成的(以不太优雅的方式):
@Override
public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException {
String content = fb.getDocument().getText(0, fb.getDocument().getLength());
Matcher matcher = Pattern.compile("\n").matcher(content);
int lines = 0;
while (matcher.find()) {
lines++;
}
if (lines < 4 || !text.contains("\n"))
super.replace(fb, offset, length, text, attrs);
}
insertString
方法可以使用相同的代码。