JTextArea DocumentListener 问题

Posted

技术标签:

【中文标题】JTextArea DocumentListener 问题【英文标题】:JTextArea DocumentListener Issue 【发布时间】:2018-11-11 18:18:28 【问题描述】:

Validation of jTextAreaName

以下代码使用 GridBagconstraints 创建一些 jTextAreaName。我的问题是我尝试使用 DocumentListener 验证 jTextAreaName 中的文本。但是它只验证最后一个 jTextAreaName。不是全部(见上图)。我认为这取决于 GridBagConstraints。但我不知道如何解决这个问题。

你有什么提示我应该改变什么吗?

提前致谢。

public class GridPanel extends JPanel 

private String[] COLUMNS = "Name", "Frame 1", "Frame 2", "Frame 3", "Frame 4", "Frame 5",
        "Frame 6", "Frame 7", "Frame 8", "Frame 9", "Frame 10", "Total Sum";

private JTextArea jTextAreaName;
public JTextArea jTextAreaTotalSum;
private JLabel labelName;
private JLabel labelFrame;
private JLabel labelSum;
private static String pattern = "[A-Za-z]*";
public static List<JTextArea> jTextAreas = new ArrayList<>();

public GridPanel(int numPlayers) 
    setLayout(new BorderLayout());
    createGrid(numPlayers);



public void createGrid(int numPlayers) 

    setLayout(new GridBagLayout());

    for (int y = 1; y <= numPlayers; y++) 

        createHeader();

        jTextAreaName = new JTextArea(2, 8);
        jTextAreaName.setEditable(true);
        addDocumentListener(jTextAreaName);

        add(jTextAreaName, GridBag.constraints(0, y, 1, 1));

        for (int i = 1; i <= 9; i++) 
            add(new BowlingFramePanel(2), GridBag.constraints(i, y, 1, 1));
        
        add(new BowlingFramePanel(3), GridBag.constraints(10, y, 1, 1));

        jTextAreaTotalSum = new JTextArea(2, 8);
        jTextAreaTotalSum.setEditable(false);

        add(jTextAreaTotalSum, GridBag.constraints(11, y, 1, 1));
    



private void addDocumentListener(JTextArea jTextArea) 
    jTextArea.getDocument().addDocumentListener(new DocumentListener() 
        @Override
        public void insertUpdate(DocumentEvent e) 
            validateInputName();
        

        @Override
        public void removeUpdate(DocumentEvent e) 
            validateInputName();
        

        @Override
        public void changedUpdate(DocumentEvent e) 
            validateInputName();
        
    );


private void validateInputName() 

    jTextAreas.add(jTextAreaName);

    for (JTextArea jTextArea : jTextAreas) 

        String text = jTextArea.getText();
        Pattern r = Pattern.compile(pattern);
        Matcher m = r.matcher(text);

        if (m.matches()) 
            jTextArea.setBackground(Color.GREEN);
            ifTextAreaIsEmptySetBackgroundColorWhite(jTextArea, text);
         else 
            jTextArea.setBackground(Color.RED);
            ifTextAreaIsEmptySetBackgroundColorWhite(jTextArea, text);
        
    


private void ifTextAreaIsEmptySetBackgroundColorWhite(JTextArea jTextArea, String text) 
    if (text.isEmpty()) 
        jTextArea.setBackground(Color.WHITE);
    


private void createHeader() 
    labelName = new JLabel(COLUMNS[0]);
    labelName.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));

    add(labelName, GridBag.constraints(0, 0, 1, 1));

    for (int x = 1; x <= 10; x++) 

        labelFrame = new JLabel(" " + "Frame " + Integer.toString(x));
        labelFrame.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));

        add(labelFrame, GridBag.constraints(x, 0, 1, 1));
    

    labelSum = new JLabel(" " + COLUMNS[11]);
    labelSum.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
    add(labelSum, GridBag.constraints(11, 0, 1, 1));



【问题讨论】:

1) 为了尽快获得更好的帮助,请发帖 minimal reproducible example 或 Short, Self Contained, Correct Example。 2) 请参阅Detection/fix for the hanging close bracket of a code block 了解我无法再费心修复的问题。 3) “我认为这取决于 GridBagConstraints。” 我认为你错了,但证明在 MCVE / SSCCE 中,所以发布一个我们可以使用的! 【参考方案1】:

我认为您应该在创建 JTexteAreas 后直接将它们添加到列表中。不在 DocumentListener 中:

public class GridPanel extends JPanel 

private String[] COLUMNS = "Name", "Frame 1", "Frame 2", "Frame 3", "Frame 4", "Frame 5",
        "Frame 6", "Frame 7", "Frame 8", "Frame 9", "Frame 10", "Total Sum";

private JTextArea jTextAreaName;
public JTextArea jTextAreaTotalSum;
private JLabel labelName;
private JLabel labelFrame;
private JLabel labelSum;
private static String pattern = "[A-Za-z]*";
public static List<JTextArea> jTextAreas = new ArrayList<>();

public GridPanel(int numPlayers) 
    setLayout(new BorderLayout());
    createGrid(numPlayers);



public void createGrid(int numPlayers) 

    setLayout(new GridBagLayout());

    for (int y = 1; y <= numPlayers; y++) 

        createHeader();

        jTextAreaName = new JTextArea(2, 8);
        jTextAreaName.setEditable(true);
        addDocumentListener(jTextAreaName);

        add(jTextAreaName, GridBag.constraints(0, y, 1, 1));

        for (int i = 1; i <= 9; i++) 
            add(new BowlingFramePanel(2), GridBag.constraints(i, y, 1, 1));
        
        add(new BowlingFramePanel(3), GridBag.constraints(10, y, 1, 1));

        jTextAreaTotalSum = new JTextArea(2, 8);
        jTextAreaTotalSum.setEditable(false);

        add(jTextAreaTotalSum, GridBag.constraints(11, y, 1, 1));
        jTextAreas.add(jTextAreaName);
    



private void addDocumentListener(JTextArea jTextArea) 
    jTextArea.getDocument().addDocumentListener(new DocumentListener() 
        @Override
        public void insertUpdate(DocumentEvent e) 
            validateInputName();
        

        @Override
        public void removeUpdate(DocumentEvent e) 
            validateInputName();
        

        @Override
        public void changedUpdate(DocumentEvent e) 
            validateInputName();
        
    );


private void validateInputName() 
    for (JTextArea jTextArea : jTextAreas) 

        String text = jTextArea.getText();
        Pattern r = Pattern.compile(pattern);
        Matcher m = r.matcher(text);

        if (m.matches()) 
            jTextArea.setBackground(Color.GREEN);
            ifTextAreaIsEmptySetBackgroundColorWhite(jTextArea, text);
         else 
            jTextArea.setBackground(Color.RED);
            ifTextAreaIsEmptySetBackgroundColorWhite(jTextArea, text);
        
    


private void ifTextAreaIsEmptySetBackgroundColorWhite(JTextArea jTextArea, String text) 
    if (text.isEmpty()) 
        jTextArea.setBackground(Color.WHITE);
    


private void createHeader() 
    labelName = new JLabel(COLUMNS[0]);
    labelName.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));

    add(labelName, GridBag.constraints(0, 0, 1, 1));

    for (int x = 1; x <= 10; x++) 

        labelFrame = new JLabel(" " + "Frame " + Integer.toString(x));
        labelFrame.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));

        add(labelFrame, GridBag.constraints(x, 0, 1, 1));
    

    labelSum = new JLabel(" " + COLUMNS[11]);
    labelSum.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
    add(labelSum, GridBag.constraints(11, 0, 1, 1));



【讨论】:

【参考方案2】:

您在 for 循环中使用了相同的对象。

for (int y = 1; y <= numPlayers; y++) 
    ...
    jTextAreaName = new JTextArea(2, 8);

jTextAreaName 仍然是相同的引用,因此只创建了最后一个 jtextarea。

你需要有足够的 JTextArea 对象,然后是 numPlayers 变量。

您的 createGrid 方法的一个可能选项如下

public void createGrid(int numPlayers) 

    setLayout(new GridBagLayout());
    jTextAreaNames = new JTextArea[numPlayers+1];

    for (int y = 1; y <= numPlayers; y++) 

        createHeader();

        jTextAreaNames[y] = new JTextArea(2, 8);
        jTextAreaNames[y].setEditable(true);
        addDocumentListener(jTextAreaNames[y]);

        add(jTextAreaNames[y], GridBag.constraints(0, y, 1, 1));

        for (int i = 1; i <= 9; i++) 
            add(new BowlingFramePanel(2), GridBag.constraints(i, y, 1, 1));
        
        add(new BowlingFramePanel(3), GridBag.constraints(10, y, 1, 1));

        jTextAreaTotalSum = new JTextArea(2, 8);
        jTextAreaTotalSum.setEditable(false);

        add(jTextAreaTotalSum, GridBag.constraints(11, y, 1, 1));
    


然后把 validateInputName 方法稍微改动一下

private void validateInputName() 

    for (JTextArea jTextArea : jTextAreaNames) 

        if(jTextArea == null) continue;

        String text = jTextArea.getText();
        Pattern r = Pattern.compile(pattern);
        Matcher m = r.matcher(text);

        if (m.matches()) 
            jTextArea.setBackground(Color.GREEN);
            ifTextAreaIsEmptySetBackgroundColorWhite(jTextArea, text);
         else 
            jTextArea.setBackground(Color.RED);
            ifTextAreaIsEmptySetBackgroundColorWhite(jTextArea, text);
        
    

我认为没有必要使用列表类对象。 不要忘记检查数组对象的 null 值,因为第一个 jtextfield 始终为 null。

if(jTextArea == null) continue;

这是我的完整代码,带有一些想象力。

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;

public class GridPanel extends JPanel 

    private String[] COLUMNS =  "Name", "Frame 1", "Frame 2", "Frame 3", "Frame 4", "Frame 5", "Frame 6", "Frame 7",
            "Frame 8", "Frame 9", "Frame 10", "Total Sum" ;

    private JTextArea[] jTextAreaNames;
    public JTextArea jTextAreaTotalSum;
    private JLabel labelName;
    private JLabel labelFrame;
    private JLabel labelSum;
    private static String pattern = "[A-Za-z]*";
    //public static List<JTextArea> jTextAreas = new ArrayList<>();


    public static void main(String[] args) 
        SwingUtilities.invokeLater(new Runnable() 

            public void run() 
                int numPlayers = 10;
                JFrame frame = new JFrame();
                frame.add(new GridPanel(numPlayers));
                frame.setPreferredSize(new Dimension(800,600));
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                //frame.getContentPane().add(mainPanel);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            

        );
    


    public GridPanel(int numPlayers) 
        setLayout(new BorderLayout());
        createGrid(numPlayers);
    

    static class GridBag
    
        static GridBagConstraints constraints(int gx, int gy, int gw, int gh)
        
            GridBagConstraints c = new GridBagConstraints();
            c.gridx = gx;
            c.gridy = gy;
            c.gridheight = gh;
            c.gridwidth = gw;

            return c;
        
    

    class BowlingFramePanel extends JPanel
    
        BowlingFramePanel(int a)
        

        
    

    public void createGrid(int numPlayers) 

        setLayout(new GridBagLayout());
        jTextAreaNames = new JTextArea[numPlayers+1];

        for (int y = 1; y <= numPlayers; y++) 

            createHeader();

            jTextAreaNames[y] = new JTextArea(2, 8);
            jTextAreaNames[y].setEditable(true);
            addDocumentListener(jTextAreaNames[y]);

            add(jTextAreaNames[y], GridBag.constraints(0, y, 1, 1));

            for (int i = 1; i <= 9; i++) 
                add(new BowlingFramePanel(2), GridBag.constraints(i, y, 1, 1));
            
            add(new BowlingFramePanel(3), GridBag.constraints(10, y, 1, 1));

            jTextAreaTotalSum = new JTextArea(2, 8);
            jTextAreaTotalSum.setEditable(false);

            add(jTextAreaTotalSum, GridBag.constraints(11, y, 1, 1));
        

    

    private void addDocumentListener(JTextArea jTextArea) 
        jTextArea.getDocument().addDocumentListener(new DocumentListener() 
            @Override
            public void insertUpdate(DocumentEvent e) 
                validateInputName();
            

            @Override
            public void removeUpdate(DocumentEvent e) 
                validateInputName();
            

            @Override
            public void changedUpdate(DocumentEvent e) 
                validateInputName();
            
        );
    

    private void validateInputName() 

        //jTextAreas.add(jTextAreaName);

        for (JTextArea jTextArea : jTextAreaNames) 

            if(jTextArea == null) continue;

            String text = jTextArea.getText();
            Pattern r = Pattern.compile(pattern);
            Matcher m = r.matcher(text);

            if (m.matches()) 
                jTextArea.setBackground(Color.GREEN);
                ifTextAreaIsEmptySetBackgroundColorWhite(jTextArea, text);
             else 
                jTextArea.setBackground(Color.RED);
                ifTextAreaIsEmptySetBackgroundColorWhite(jTextArea, text);
            
        
    

    private void ifTextAreaIsEmptySetBackgroundColorWhite(JTextArea jTextArea, String text) 
        if (text.isEmpty()) 
            jTextArea.setBackground(Color.WHITE);
        
    

    private void createHeader() 
        labelName = new JLabel(COLUMNS[0]);
        labelName.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));

        add(labelName, GridBag.constraints(0, 0, 1, 1));

        for (int x = 1; x <= 10; x++) 

            labelFrame = new JLabel(" " + "Frame " + Integer.toString(x));
            labelFrame.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));

            add(labelFrame, GridBag.constraints(x, 0, 1, 1));
        

        labelSum = new JLabel(" " + COLUMNS[11]);
        labelSum.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
        add(labelSum, GridBag.constraints(11, 0, 1, 1));

    

【讨论】:

以上是关于JTextArea DocumentListener 问题的主要内容,如果未能解决你的问题,请参考以下文章

Java:JTextArea类

jTextArea如何加滚动条

JTextArea 到 ArrayList<String> 的行

JTextArea:居中对齐

更改 JTextArea 中的文本选择类型

JTextArea 中的文本更改事件?如何?