JTextField和JSlider之间的交互 ​​- DocumentListener混淆

时间:2017-04-03 06:43:16

标签: user-interface jtextfield illegalstateexception jslider documentlistener

我有一个包含文本字段(红色,绿色,蓝色)和滑块(红色,绿色,蓝色)的面板。用户应该能够利用他们喜欢的任何一个,相应的组件应该更新。 (例如,在红色文本字段中输入100应将红色滑块移动到100)。

由于我希望滑块在插入或删除文本时更新 ,因此我创建了一个简单的DocumentListener。但是,我收到错误消息" java.lang.IllegalStateException:尝试在通知中进行变异。"我的程序对是否应该首先更新滑块或文本字段感到困惑。有没有办法解决这个问题?我将在下面发布我的两个课程,并附上GUI的照片以供快速参考。enter image description here

public class ColorChooser extends javax.swing.JPanel implements ChangeListener {
    private Vector listeners;

    public ColorChooser() {
        initComponents();
        listeners = new Vector();
        sldRed.addChangeListener(this);
        sldGreen.addChangeListener(this);
        sldBlue.addChangeListener(this);
        txtRed.setText("0");
        txtGreen.setText("0");
        txtBlue.setText("0");
        Document docRed = txtRed.getDocument();
        docRed.addDocumentListener(new MyDocumentListener(txtRed, sldRed));
        Document docGreen = txtGreen.getDocument();
        docGreen.addDocumentListener(new MyDocumentListener(txtGreen, sldGreen));
        Document docBlue = txtBlue.getDocument();
        docBlue.addDocumentListener(new MyDocumentListener(txtBlue, sldBlue));
}

    // Variables declaration - do not modify                     
    private javax.swing.JLabel labelBlue;
    private javax.swing.JLabel labelGreen;
    private javax.swing.JLabel labelRed;
    private javax.swing.JSlider sldBlue;
    private javax.swing.JSlider sldGreen;
    private javax.swing.JSlider sldRed;
    private jcolorchooser.JColorIntegerField txtBlue;
    private jcolorchooser.JColorIntegerField txtGreen;
    private jcolorchooser.JColorIntegerField txtRed;
    // End of variables declaration                   

    @Override
    public void stateChanged(ChangeEvent ce) {
        if (ce.getSource() == sldRed) {
            txtRed.setText(Integer.toString(sldRed.getValue()));
        }
        if (ce.getSource() == sldGreen) {
            txtGreen.setText(Integer.toString(sldGreen.getValue()));
        }
        if (ce.getSource() == sldBlue) {
            txtBlue.setText(Integer.toString(sldBlue.getValue()));
        }
        int r = sldRed.getValue();
        int g = sldGreen.getValue();
        int b = sldBlue.getValue();
        Color color = new Color(r,g,b);
        fireColorEvent(new ColorEvent(this,color));
    }
    private void fireColorEvent(ColorEvent colorEvent){
        Vector v;
        synchronized(this){
            v = (Vector)listeners.clone();
        }
        int size = v.size();
        for(int i=0; i<size; i++){
            ColorListener colorListener = (ColorListener)v.elementAt(i);
            colorListener.changeColor(colorEvent);
        }
    }
    public void addColorListener(ColorListener colorListener){
        listeners.addElement(colorListener);
    }
    public void removeColorListener(ColorListener colorListener){
        listeners.removeElement(colorListener);
   }

}

//DocumentListener Class
public class MyDocumentListener implements DocumentListener {
    private JColorIntegerField jColorIntegerField;
    private JSlider jColorSlider;

    public MyDocumentListener(JColorIntegerField jColorIntegerField,
        JSlider jColorSlider) {
        this.jColorIntegerField = jColorIntegerField;
        this.jColorSlider = jColorSlider;
    }

    public void insertUpdate(DocumentEvent de) {
        if (jColorIntegerField.getText().equals("")) {
            jColorSlider.setValue(0);
        }
        else {
            jColorSlider.setValue(Integer.parseInt(
                jColorIntegerField.getText()));
        }
    }

    @Override
    public void removeUpdate(DocumentEvent de) {
        if (jColorIntegerField.getText().equals("")) {
            jColorSlider.setValue(0);
        }
        else {
            jColorSlider.setValue(Integer.parseInt(
                jColorIntegerField.getText()));
        }
    }

    @Override
    public void changedUpdate(DocumentEvent de) {

    }
}

1 个答案:

答案 0 :(得分:0)

这可能会有点晚,但本周我正在研究一个Java项目,我遇到的问题和你上面描述的一样。

在寻找解决方案时,我偶然发现了你的问题。由于它还没有答案,我认为回到这里描述我是如何解决问题可能会有所帮助(也许它将来会帮助你或其他人)。

因此,似乎Swing API通过提供一个名为getValueIsAdjusting的非常好的方法来帮助我们。此方法是for (int i=0; i < results.Count; i++) { if (results[i].StartsWith("\"")) results[i] = results[i].Remove(0, 1); if (results[i].EndsWith("\"")) results[i] = results[i].Remove(results[i].Length - 1, 1); } 类的一部分。

  

这是如何解决问题的?

我们修改了JSlider实施中的stateChanged方法:

ChangeListener

@Override public void stateChanged(ChangeEvent ce) { JSlider source = (JSlider)ce.getSource(); if (source.getValueIsAdjusting()) { if (source == sldRed) txtRed.setText(Integer.toString(sldRed.getValue())); else if (source == sldGreen) txtGreen.setText(Integer.toString(sldGreen.getValue())); else if (source == sldBlue) txtBlue.setText(Integer.toString(sldBlue.getValue())); } int r = sldRed.getValue(); int g = sldGreen.getValue(); int b = sldBlue.getValue(); Color color = new Color(r, g, b); fireColorEvent(new ColorEvent(this, color)); } 指令仅在您仍在“调整”滑块时才会发生if (source.getValueIsAdjusting())(这意味着您仍然使用鼠标拖动它)。

将值写入setText会触发滑块的JTextField方法,但 NOT 会调用stateChanged,因为滑块价值不是“调整”。

因此,你摆脱了异常。