Swing 为什么会有一个;IllegalStateException:试图在通知中变异;与转换器使用相互绑定时出现异常?

Swing 为什么会有一个;IllegalStateException:试图在通知中变异;与转换器使用相互绑定时出现异常?,swing,groovy,griffon,Swing,Groovy,Griffon,也许我在理解Griffon的converter&reverseConverter时遗漏了一些东西。出了什么问题,我应该如何解决 感谢@tim_yates的编辑,但我发现我不仅在Griffon中,而且在plain Groovy中也遇到了相同的错误,如下所示: import groovy.beans.Bindable import groovy.swing.SwingBuilder class Model { @Bindable String name @Bindable Inte

也许我在理解Griffon的converter&reverseConverter时遗漏了一些东西。出了什么问题,我应该如何解决

感谢@tim_yates的编辑,但我发现我不仅在Griffon中,而且在plain Groovy中也遇到了相同的错误,如下所示:

import groovy.beans.Bindable
import groovy.swing.SwingBuilder

class Model {
    @Bindable String name
    @Bindable Integer score
}

Model m = new Model()

new SwingBuilder().edt {
    frame(title: 'Untitled', pack: true, show: true) {
        flowLayout()
        label("Name: ")
        textField(columns: 10, text: bind("name", source: m, mutual: true))
        label("Score: ")
        textField(columns: 3, text: bind("score", source: m, 
            reverseConverter: { it.isEmpty()? 0: Integer.parseInt(it) },
            converter: { String.valueOf(it) },
            mutual: true))
        button("Save", actionPerformed: { 
            println "You're saving ${m.name} with score ${m.score}"
        })
        button("Reset Input To Default", actionPerformed: {
            edt {
              m.name = "defaultName"
              m.score = 50
            }
        })
    }
}
stacktrace更详细:

Result: groovy.swing.SwingBuilder@ae20b6Exception in thread "AWT-EventQueue-0" 
java.lang.IllegalStateException: Attempt to mutate in notification
    at javax.swing.text.AbstractDocument.writeLock(AbstractDocument.java:1338)
    at javax.swing.text.AbstractDocument.replace(AbstractDocument.java:659)
    at javax.swing.text.JTextComponent.setText(JTextComponent.java:1718)
    at sun.reflect.GeneratedMethodAccessor276.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
    at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
    at groovy.lang.MetaClassImpl.setProperty(MetaClassImpl.java:2404)
    at groovy.lang.MetaClassImpl.setProperty(MetaClassImpl.java:3341)
    at org.codehaus.groovy.runtime.InvokerHelper.setProperty(InvokerHelper.java:196)
    at groovy.beans.DefaultPropertyWriter.write(DefaultPropertyWriter.java:28)
    at groovy.beans.DefaultPropertyAccessor.write(DefaultPropertyAccessor.java:30)
    at org.codehaus.groovy.binding.PropertyBinding.setBeanProperty(PropertyBinding.java:236)
    at org.codehaus.groovy.binding.PropertyBinding.access$000(PropertyBinding.java:51)
    at org.codehaus.groovy.binding.PropertyBinding$2.run(PropertyBinding.java:189)
    at org.codehaus.groovy.binding.PropertyBinding.updateTargetValue(PropertyBinding.java:196)
    at org.codehaus.groovy.binding.AbstractFullBinding.fireBinding(AbstractFullBinding.java:51)
    at org.codehaus.groovy.binding.AbstractFullBinding.update(AbstractFullBinding.java:55)
    at org.codehaus.groovy.binding.PropertyBinding$PropertyFullBinding.propertyChange(PropertyBinding.java:279)
    at java.beans.PropertyChangeSupport.fire(PropertyChangeSupport.java:335)
    at java.beans.PropertyChangeSupport.firePropertyChange(PropertyChangeSupport.java:328)
    at java.beans.PropertyChangeSupport.firePropertyChange(PropertyChangeSupport.java:263)
    at java.beans.PropertyChangeSupport.firePropertyChange(PropertyChangeSupport.java:283)
    at java_beans_PropertyChangeSupport$firePropertyChange$0.call(Unknown Source)
    at Model.firePropertyChange(test.groovy)
    at Model$firePropertyChange.callCurrent(Unknown Source)
    at Model.setScore(test.groovy)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
    at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
    at groovy.lang.MetaClassImpl.setProperty(MetaClassImpl.java:2404)
    at groovy.lang.MetaClassImpl.setProperty(MetaClassImpl.java:3341)
    at Model.setProperty(test.groovy)
    at org.codehaus.groovy.runtime.InvokerHelper.setProperty(InvokerHelper.java:192)
    at groovy.beans.DefaultPropertyWriter.write(DefaultPropertyWriter.java:28)
    at groovy.beans.DefaultPropertyAccessor.write(DefaultPropertyAccessor.java:30)
    at org.codehaus.groovy.binding.PropertyBinding.setBeanProperty(PropertyBinding.java:236)
    at org.codehaus.groovy.binding.PropertyBinding.access$000(PropertyBinding.java:51)
    at org.codehaus.groovy.binding.PropertyBinding$2.run(PropertyBinding.java:189)
    at org.codehaus.groovy.binding.PropertyBinding.updateTargetValue(PropertyBinding.java:220)
    at org.codehaus.groovy.binding.AbstractFullBinding.fireBinding(AbstractFullBinding.java:51)
    at org.codehaus.groovy.binding.AbstractFullBinding.update(AbstractFullBinding.java:55)
    at groovy.swing.binding.JTextComponentTextBinding.removeUpdate(JTextComponentProperties.java:85)
    at javax.swing.text.AbstractDocument.fireRemoveUpdate(AbstractDocument.java:260)
    at javax.swing.text.AbstractDocument.handleRemove(AbstractDocument.java:623)
    at javax.swing.text.AbstractDocument.remove(AbstractDocument.java:591)
    at javax.swing.text.AbstractDocument.replace(AbstractDocument.java:667)
    at javax.swing.text.JTextComponent.setText(JTextComponent.java:1718)
    at sun.reflect.GeneratedMethodAccessor276.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
    at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
    at groovy.lang.MetaClassImpl.setProperty(MetaClassImpl.java:2404)
    at groovy.lang.MetaClassImpl.setProperty(MetaClassImpl.java:3341)
    at org.codehaus.groovy.runtime.InvokerHelper.setProperty(InvokerHelper.java:196)
    at groovy.beans.DefaultPropertyWriter.write(DefaultPropertyWriter.java:28)
    at groovy.beans.DefaultPropertyAccessor.write(DefaultPropertyAccessor.java:30)
    at org.codehaus.groovy.binding.PropertyBinding.setBeanProperty(PropertyBinding.java:236)
    at org.codehaus.groovy.binding.PropertyBinding.access$000(PropertyBinding.java:51)
    at org.codehaus.groovy.binding.PropertyBinding$2.run(PropertyBinding.java:189)
    at org.codehaus.groovy.binding.PropertyBinding.updateTargetValue(PropertyBinding.java:196)
    at org.codehaus.groovy.binding.AbstractFullBinding.fireBinding(AbstractFullBinding.java:51)
    at org.codehaus.groovy.binding.AbstractFullBinding.update(AbstractFullBinding.java:55)
    at org.codehaus.groovy.binding.PropertyBinding$PropertyFullBinding.propertyChange(PropertyBinding.java:279)
    at java.beans.PropertyChangeSupport.fire(PropertyChangeSupport.java:335)
    at java.beans.PropertyChangeSupport.firePropertyChange(PropertyChangeSupport.java:328)
    at java.beans.PropertyChangeSupport.firePropertyChange(PropertyChangeSupport.java:263)
    at java.beans.PropertyChangeSupport.firePropertyChange(PropertyChangeSupport.java:283)
    at java_beans_PropertyChangeSupport$firePropertyChange$0.call(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
    at java_beans_PropertyChangeSupport$firePropertyChange.call(Unknown Source)
    at Model.firePropertyChange(test.groovy)
    at Model$firePropertyChange.callCurrent(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:49)
    at Model$firePropertyChange.callCurrent(Unknown Source)
    at Model.setScore(test.groovy)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
    at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
    at groovy.lang.MetaClassImpl.setProperty(MetaClassImpl.java:2404)
    at groovy.lang.MetaClassImpl.setProperty(MetaClassImpl.java:3341)
    at Model.setProperty(test.groovy)
    at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.setGroovyObjectProperty(ScriptBytecodeAdapter.java:528)
    at test$_run_closure1_closure2_closure6_closure7.doCall(test.groovy:27)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
    at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
    at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:272)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:906)
    at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:39)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116)
    at groovy.swing.SwingBuilder.edt(SwingBuilder.groovy:330)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
    at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
    at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:361)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:906)
    at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.callCurrent(PogoMetaClassSite.java:66)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:49)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:133)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:141)
    at test$_run_closure1_closure2_closure6.doCall(test.groovy:25)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
    at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
    at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:272)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:906)
    at groovy.lang.Closure.call(Closure.java:412)
    at org.codehaus.groovy.runtime.ConvertedClosure.invokeCustom(ConvertedClosure.java:51)
    at org.codehaus.groovy.runtime.ConversionHandler.invoke(ConversionHandler.java:82)
    at $Proxy11.actionPerformed(Unknown Source)
    at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2018)
    at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2341)
    at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
    at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
    at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252)
    at java.awt.Component.processMouseEvent(Component.java:6505)
    at javax.swing.JComponent.processMouseEvent(JComponent.java:3321)
    at java.awt.Component.processEvent(Component.java:6270)
    at java.awt.Container.processEvent(Container.java:2229)
    at java.awt.Component.dispatchEventImpl(Component.java:4861)
    at java.awt.Container.dispatchEventImpl(Container.java:2287)
    at java.awt.Component.dispatchEvent(Component.java:4687)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4832)
    at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4492)
    at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4422)
    at java.awt.Container.dispatchEventImpl(Container.java:2273)
    at java.awt.Window.dispatchEventImpl(Window.java:2719)
    at java.awt.Component.dispatchEvent(Component.java:4687)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:703)
    at java.awt.EventQueue.access$000(EventQueue.java:102)
    at java.awt.EventQueue$3.run(EventQueue.java:662)
    at java.awt.EventQueue$3.run(EventQueue.java:660)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
    at java.awt.EventQueue$4.run(EventQueue.java:676)
    at java.awt.EventQueue$4.run(EventQueue.java:674)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:673)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:244)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:163)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:151)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:147)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:139)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:97)

我相信这是由转换器引起的绑定中的一个错误,因为它们以这样一种方式转换值,绑定认为它在触发时正在改变。如果没有注册转换器(因此在两端强制使用相同的类型),则不会发生错误;这让我觉得是转换器的故障


听我说,根据上面的回答,应该在

处提出问题,我也同意这可能是一个错误,应该报告

对于临时,我将使用此解决方法防止异常显示:

textField(columns: 3, text: bind("score", target: m, 
    converter: { it.isEmpty()? 50: Integer.parseInt(it) },
    reverseConverter: { String.valueOf(it) },
    mutual: true))
转换器需要将空字符串转换为模型中相同的默认值,在本例中为50。这将满足
org.codehaus.groovy.binding.PropertyBinding
中的以下保护:

public void updateTargetValue(final Object newValue) {

  Runnable runnable = new Runnable() {
     public void run() {
         ...
         if ((sourceValue==null && newValue==null) || 
              DefaultTypeTransformation.compareEqual(sourceValue, newValue)) {
            // not a change, don't fire it
            return;
         }
     }
  }

}

是的,也许是虫子。从Groovy的源代码调试:
Model.name-->JTextField
将调用
PropertyBinding.updateTargetValue
,这将触发另一个绑定,
JTextField-->Model.name
,它将再次调用
updateTargetValue
compareEqual
将停止执行。对于
Model.score-->JTextField
updateTargetValue()
将使用从reverseConverter返回的字符串
updateTargetValue()
将触发
JTextField-->模型。score
绑定,其中
JTextField。text
将是一个空字符串(应为“50”!),这将导致
compareEqual
无法停止后续绑定循环。知道为什么吗?谢谢你的帮助。是的,我同意这个问题似乎是在equals比较期间使用了转换值,而不是实际值。我在这里创建了一张罚单