Java:向ChangeEvent添加文本字段

时间:2014-11-24 05:35:42

标签: java swing actionlistener

我有一个家庭作业,我必须改变颜色选择器(它有3个滑块,RGB并显示颜色),以便有文本字段,当在字段中键入值时,它也会更改滑块。我得到了基本的想法但是我找不到正在改变的文本字段的解决方案,他们只能使用Action Event。这是我的代码

package colorchooser;
import java.util.Vector;
import java.awt.Color;
import javax.swing.event.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JOptionPane;

/**
 *
 * @author -
 */
public class ColorChooser extends javax.swing.JPanel implements ChangeListener, ActionListener{

    private Vector listeners;

    /**
     * Creates new form ColorChooser
     */
    public ColorChooser() {
        initComponents();
        listeners = new Vector();
        sldRed.addChangeListener(this);
        sldGreen.addChangeListener(this);
        sldBlue.addChangeListener(this);
        txtRed.addActionListener(this);

    // Variables declaration - do not modify                     
    private javax.swing.JButton btnSetColor;
    private javax.swing.JLabel lblBlue;
    private javax.swing.JLabel lblGreen;
    private javax.swing.JLabel lblRed;
    private javax.swing.JSlider sldBlue;
    private javax.swing.JSlider sldGreen;
    private javax.swing.JSlider sldRed;
    private javax.swing.JTextField txtBlue;
    private javax.swing.JTextField txtGreen;
    private javax.swing.JTextField txtRed;
    // End of variables declaration                   

    @Override
    public void stateChanged(ChangeEvent ce) {
         int r = sldRed.getValue();
         int g = sldGreen.getValue();
         int b = sldBlue.getValue();
         Color color = new Color(r,g,b);
         fireColorEvent(new ColorEvent(this,color));
         txtRed.setText(Integer.toString(r));
         txtGreen.setText(Integer.toString(g));
         txtBlue.setText(Integer.toString(b));
    }

    public void addColorListener(ColorListener colorListener){
        listeners.addElement(colorListener);
    }

    public void actionPerformed(ActionEvent ae) {

        if(ae.getSource()==btnSetColor){
            try
            {
                if(Integer.parseInt(txtRed.getText()) <= 255){
                sldRed.setValue(Integer.parseInt(txtRed.getText()));
                }
                else
                {
                    txtRed.setText("0");
                    JOptionPane.showMessageDialog(this,"Error: Please enter a value equal to or less than 255");
                }            


                if(Integer.parseInt(txtBlue.getText()) <= 255){
                sldBlue.setValue(Integer.parseInt(txtBlue.getText()));
                }
                else
                {
                    txtBlue.setText("0");
                    JOptionPane.showMessageDialog(this,"Error: Please enter a value equal to or less than 255");
                }                

                if(Integer.parseInt(txtGreen.getText()) <= 255){
                sldGreen.setValue(Integer.parseInt(txtGreen.getText()));
                }
                else
                {
                    txtGreen.setText("0");
                    JOptionPane.showMessageDialog(this,"Error: Please enter a value equal to or less than 255");
                }                
            }
            catch (Exception ex)
            {
                JOptionPane.showMessageDialog(this,"Error: Please Enter Numbers");
                txtRed.setText("0");
                txtGreen.setText("0");
                txtBlue.setText("0");
                sldRed.setValue(Integer.parseInt(txtRed.getText()));
                sldGreen.setValue(Integer.parseInt(txtGreen.getText()));
                sldBlue.setValue(Integer.parseInt(txtBlue.getText()));
            }
        }
    }

您可以看到我正在向滑块添加更改侦听器,但我必须向txtRed添加一个动作侦听器,因为它不接受addChangeListener。关于解决方案的任何想法?

谢谢!

1 个答案:

答案 0 :(得分:1)

创建一个可以处理已更改字段的方法......

protected void fieldWasChanged(JTextField field) {
    try {
        int value = Integer.parseInt(field.getText());
        JSlider slider = null;
        if (field == txtBlue) {
            slider = sldBlue;
        } else if (field == txtRed) {
            slider = sldRed;
        } else if (field == txtGreen) {
            slider = sldGreen;
        }
        if (slider != null) {
            slider.setValue(value);
        }
    } catch (NumberFormatException exp) {
        exp.printStackTrace(); 
        // Display error message
    }
}

接下来,创建一个实现DocumentListener接口...

的内部类
public class DocumentHandler implements DocumentListener {

    private JTextField field;

    public DocumentHandler(JTextField field) {
        this.field = field;
    }

    protected void documentUpdated() {
        fieldWasChanged(field);
    }

    @Override
    public void insertUpdate(DocumentEvent e) {
        documentUpdated();
    }

    @Override
    public void removeUpdate(DocumentEvent e) {
        documentUpdated();
    }

    @Override
    public void changedUpdate(DocumentEvent e) {
        documentUpdated();
    }

}

这将监控Document下方字段的更改并调用您的fieldWasChanged方法...

接下来,使用此处理程序注册每个字段...

protected void registerDocumentHandler(JTextField field) {
    DocumentHandler handler = new DocumentHandler(field);
    field.getDocument().addDocumentListener(handler);
}

//...

registerDocumentHandler(txtBlue);
registerDocumentHandler(txtRed);
registerDocumentHandler(txtGreen);

现在,如果你真的试过这个,你会发现你输入内容的那一刻,你的用户界面会变得没有响应,你的程序最终会因StackOverflowException而崩溃,这是因为DocumentHandler正在更新JSlider s,这是更新字段,通知DocumentHandler和......等等......

一个简单的解决方案是放入一个标记,而true阻止DocumentHandler通知fieldWasChanged方法......

public class DocumentHandler implements DocumentListener {

    private JTextField field;
    private boolean isUpdating;

    public DocumentHandler(JTextField field) {
        this.field = field;
    }

    protected void documentUpdated() {
        if (!isUpdating) {
            try {
                fieldWasChanged(field);
            } finally {
                isUpdating = false;
            }
        }
    }

    //...

现在您可以输入并获得实时反馈,您可以将文本粘贴到字段中,然后更新滑块...

现在,尽管如此,我建议您尝试使用JFormattedTextFieldJSlider代替JTextField,因为它们可以帮助验证数据本身。有关详细信息,请参阅How to Use Formatted Text FieldsHow to Use Spinners

如果您不想使用这些内容,但仍希望限制用户只能输入数字,请查看Implementing a Document FilterDocumentFilter Examples