JTextField 和 JSlider 之间的交互 - DocumentListener 感到困惑
Posted
技术标签:
【中文标题】JTextField 和 JSlider 之间的交互 - DocumentListener 感到困惑【英文标题】:Interaction between JTextField and JSlider - DocumentListener gets confused 【发布时间】:2017-08-27 22:21:49 【问题描述】:我有一个包含文本字段(红色、绿色、蓝色)和滑块(红色、绿色、蓝色)的面板。用户应该能够使用他们喜欢的任何一个,并且相应的组件应该更新。 (例如,在红色文本字段中输入 100 应将红色滑块移动到 100)。
由于我希望滑块在插入或删除文本时更新,因此我创建了一个简单的 DocumentListener。但是,我收到错误消息“java.lang.IllegalStateException: Attempt to mutate in notification”。我的程序对是否应该首先更新滑块或文本字段感到困惑。有没有办法解决这个问题?我将在下面发布我的两个课程,并附上GUI的照片以供快速参考。
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】:这可能来得有点晚,但我这周在做一个 Java 项目,遇到了和你上面描述的一样的问题。
在寻找解决方案时,我偶然发现了您的问题。由于它还没有答案,我认为回到这里并描述我是如何解决问题的可能会有所帮助(也许它会对您或将来的其他人有所帮助)。
因此,Swing API 似乎通过提供一个名为getValueIsAdjusting 的非常好的方法来帮助我们。此方法是JSlider
类的一部分。
这如何解决问题?
我们从ChangeListener
实现修改stateChanged
方法:
@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
将触发滑块的stateChanged
方法,但它会不调用setText
,因为滑块值不是“调整” .
因此,您摆脱了异常。
【讨论】:
以上是关于JTextField 和 JSlider 之间的交互 - DocumentListener 感到困惑的主要内容,如果未能解决你的问题,请参考以下文章
JTextField 和 JTextPane 之间的根本区别是啥?