在Spring支持的java独立应用程序中放置SwingUtilities.invokeLater的位置?

时间:2014-03-17 10:51:58

标签: java multithreading spring swing

我在我的java Swing应用程序中使用Spring框架。我以这种方式在我的application-context.xml中初始化我的MVC对象作为spring bean,使用@Autowired for DI。

<bean id="model" class="com.Model"/>

<bean id="view" class="com.View"/>

<bean id="controller" class="com.Controller"/>

它运行成功没有任何问题。但是,通过阅读this question,我认为我应该将每个Swing组件放在SwingUtilities.invokerLater()中。

  

一些Swing组件方法在API规范中标记为“线程安全”;这些可以从任何线程安全地调用。必须从事件派发线程调用所有其他Swing组件方法。忽略此规则的程序可能在大多数情况下正常运行,但会遇到难以重现的不可预测的错误。

所以我的问题是,在哪里/如何将我的东西放到这个事件调度线程中?目前我的主要方法只是一个班轮......

ApplicationContext context =
    new ClassPathXmlApplicationContext("application-context.xml");

更新: 我想知道这是不是我应该做的事情?

SwingUtilities.invokeLater(new Runnable() {
  public void run() {
     ApplicationContext context =
        new ClassPathXmlApplicationContext("application-context.xml");
  }
  context.xxxx
  blahblahblah...
});

2 个答案:

答案 0 :(得分:0)

要在事件派发线程上运行代码,您可以执行以下操作:

EventQueue.invokeLater(new Runnable() {
    public void run() {
       //your code here
    }
 });

......或等效地:

SwingUtilities.invokeLater(new Runnable() {
    public void run() {
       //your code here
    }
 });

您可以在任何需要在事件派发线程上运行的代码的位置使用这两种方法。只需将代码包装在匿名Runnable中,您就可以了。

请注意,如果您要在匿名Runnable实施中定义要在其中访问的变量,则需要将它们声明为final。有关更多信息,请尝试以下操作:

答案 1 :(得分:0)

我昨晚有同样的问题,到处搜索,但找不到合适的答案。我绞尽脑汁待了几个小时,这就是我提出来的,看起来非常稳固。

这个解决方案使用Spring的查找方法注入来在EDT上懒洋洋地加载摆动Gui。

<强> IOnDemandBeanGetter.java
这是Spring将用于方法注入的接口

public interface IOnDemandBeanGetter {
    public IOnDemandBean getBean();
}

<强> IOnDemandBean.java
由IOnDemandBeanGetter返回的标记接口

public interface IOnDemandBean {}

<强> GuiOnEdtUtility.java
该实用程序使用注入的IOnDemandBeanGetter来获取bean并将其加载到EDT上。

public class GuiOnEdtUtility {
    private final IOnDemandBeanGetter beanGetter;

    public GuiOnEdtUtility(IOnDemandBeanGetter beanGetter) {
        this.beanGetter = beanGetter;
    }

    public void createGuiOnEdt(){
        SwingUtilities.invokeLater(()->beanGetter.getBean());
    }
}

<强> MainGui.java
它包含swing组件,将由IOnDemandBeanGetter返回,并由GuiOnEdtUtility加载到EDT上。你可以注入任何组件,我不是为了简单而做,但它们都必须有lazy-init =“true”

public class MainGui implements IOnDemandBean {
    private final JFrame frame = new JFrame();

    public MainGui() {
        System.out.println(SwingUtilities.isEventDispatchThread() 
                           ? "Created On EDT"
                           : "Not created On EDT");
    }

    public void init() {
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(200, 200);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}

<强>的beans.xml

<bean name="onDemandBeanGetter" class="IOnDemandBeanGetter">
    <lookup-method name="getBean" bean="mainGui"/>
</bean>

<bean name="guiOnEdtUtility" class="GuiOnEdtUtility" init-method="createGuiOnEdt">
    <constructor-arg ref="onDemandBeanGetter"></constructor-arg>
</bean>

<bean name="mainGui" class="MainGui" init-method="init" lazy-init="true"/>

<强>更新...
这就是MainGui.java从JFrame继承后的样子,它的工作方式相同

public class MainGui extends JFrame implements IOnDemandBean {

    public MainGui() {
        System.out.println(SwingUtilities.isEventDispatchThread() 
                           ? "Created On EDT"
                           : "Not created On EDT");
    }

    public void init() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(200, 200);
        setLocationRelativeTo(null);
        setVisible(true);
    }
}