我有一个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();
}});
}
}
答案 0 :(得分:2)
您可以尝试使用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);
}
};
}
}
答案 1 :(得分:2)
如前所述,可以使用DocumentFilter
。我发布这个答案是因为它提供了优雅的解决方案。
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
方法可以使用相同的代码。
答案 2 :(得分:1)
使用setPreferredSize(new Dimension(X,Y))
以便JTextArea保留您设置的尺寸,并且根本不会移动!
您仍然需要将JTextArea置于JScrollPane
之内。
答案 3 :(得分:0)
我建议您使用InputVerifier
来跟踪已在JTextArea
中输入的输入次数,当它达到4时,它应该忽略输入。
正如您在评论中指出的那样DocumentListener
会做同样的事情,KeyListener
也可以这样做。