Java Swing Threading问题

Java Swing Threading问题

问题描述:

我有一个在swing中使用线程的问题。 我会先解释问题,然后我会发布我的代码。Java Swing Threading问题

问题是以下几点。我有两个类,一个包含业务逻辑,另一个包含用户界面。基于接口中的用户操作,我调用包含业务逻辑的类中的方法。 但是,我的下一个任务是让用户点击一个UI元素,并且基于该点击,我将一个新的鼠标监听器附加到其他UI元素,然后等待用户单击该其他UI元素,之后,我想要更改初始点击的UI元素。 但是,我的应用程序在单击其他UI元素后会阻止。 在示例代码中,初始UI元素和其他UI元素都是相同的,但通常它们不会。

示例类:

======================================= =============================

package threadtests; 

import java.awt.Color; 

public class LogicClass extends Thread { 

    FrameClass fc; 
    SelectSynchronizerObject mysso; 

    public void run() { 
     while(true); 
    } 

    public void startThisFromFrame() { 
     MyMouseListener2 m2 = new MyMouseListener2(); 
     m2.initialize(fc.jp, mysso); 
     fc.jp.addMouseListener(m2); 
     mysso.getSelected(); 
     fc.jp.setBackground(new Color(100,100,100)); 
     fc.jp.removeMouseListener(m2); 
    } 

    public static void main(String args[]) { 
     SelectSynchronizerObject sso = new SelectSynchronizerObject(); 
     LogicClass lc = new LogicClass(); 
     lc.mysso = sso; 
     lc.start(); 
     FrameClass fc = new FrameClass(); 
     fc.lc = lc; 
     lc.fc = fc; 
     fc.mysso = sso; 
     fc.initialize(lc); 
    } 

} 

============== ================================================== ====

package threadtests; 

import java.awt.Color; 

import javax.swing.JFrame; 
import javax.swing.JPanel; 

public class FrameClass extends JFrame { 

    LogicClass lc; 
    SelectSynchronizerObject mysso; 
    JPanel jp = new JPanel(); 

    public void initialize(LogicClass arg) { 
     lc = arg; 
     setSize(100,100); 
     MyMouseListener m = new MyMouseListener(); 
     jp.addMouseListener(m); 
     m.initialize(jp, lc); 
     jp.setBackground(new Color(255,200,200)); 
     add(jp); 

     setVisible(true); 
    } 

} 

======================================= =============================

package threadtests; 

public class SelectSynchronizerObject { 

    public int selectednumer = 0; 
    public boolean numberset = false; 

    public synchronized void panelSelected(int a) { 
     selectednumer = a; 
     notify(); 
    } 

    public synchronized int getSelected() { 
     try { 
      wait(); 
     } catch (InterruptedException e) { 
      System.out.println(e); 
     } 
     return selectednumer; 
    } 

} 

============================================== ======================

package threadtests; 
import java.awt.Color; 
import java.awt.event.MouseEvent; 
import java.awt.event.MouseListener; 
import javax.swing.JPanel; 

public class MyMouseListener implements MouseListener { 

    JPanel mypanel; 
    LogicClass lc; 
    public void initialize(JPanel arg, LogicClass arg2) { 
     mypanel = arg; 
     lc = arg2; 
    } 
    public void mouseClicked(MouseEvent e) { 
     lc.startThisFromFrame(); 
    } 
    public void mousePressed(MouseEvent e) { 

    } 
    public void mouseReleased(MouseEvent e) { 
    } 
    public void mouseEntered(MouseEvent e) { 
     mypanel.setBackground(new Color(200,255,200)); 
    } 
    public void mouseExited(MouseEvent e) { 
     mypanel.setBackground(new Color(255,200,200)); 
    } 

} 

===================== ===============================================

package threadtests; 
import java.awt.event.MouseEvent; 
import java.awt.event.MouseListener; 
import javax.swing.JPanel; 

public class MyMouseListener2 implements MouseListener { 

    JPanel mypanel; 
    SelectSynchronizerObject sso; 
    public void initialize(JPanel arg, SelectSynchronizerObject arg1) { 
     mypanel = arg; 
     sso = arg1; 
    } 
    public void mouseClicked(MouseEvent e) { 
     sso.panelSelected(1); 
    } 
    public void mousePressed(MouseEvent e) { 
    } 
    public void mouseReleased(MouseEvent e) { 
    } 
    public void mouseEntered(MouseEvent e) { 
    } 
    public void mouseExited(MouseEvent e) { 
    } 

} 

==========================

感谢您的帮助。

+1

看看SwingUtilities.invokeLater – MeBigFatGuy 2011-04-28 19:47:28

+0

其实,我相信OP需要[SwingWorker](http://download.oracle.com/javase/6/docs/api/javax/swing/SwingWorker.html),这是为了在后台执行昂贵的任务。'invokeLater'意味着排队由其他线程完成的任务,这些线程需要更新UI(只能通过EDT进行) – 2011-04-28 19:54:40

+0

Nevermind,我重新阅读了这个问题,它看起来像OP想要创建新的UI无论如何最好通过EDT完成的元素 - 'invokeLater'看起来就像在这种情况下要走的路。 – 2011-04-28 19:56:48

第一:

public void run() { 
    while(true); 
} 

只是需要CPU从做其他的东西白白。

然后:

wait(); 

被称为在主线程,从而阻断。

其实你不需要invokelater,swingworker或任何东西,你只是一个小小的GUI事件编程。将事件监听器连接在一起,然后在没有任何线程的情况下获得所选面板。

通常,虽然线程对于很多程序都是必需的,但不需要强制它们在没有必要的地方,因为它们增加了编程的复杂性。

+0

实际上,LogicClass已经被设置为一个线程,并不是因为它需要是一个线程本身,而是因为我试图解决阻塞问题---使LogicClass成为一个线程,使其不会阻塞EDT。然而,它没有帮助,程序仍然被阻止。我实际上知道如何用更多的编程来解决问题,但我拥有的其他解决方案并不足以满足我的需求。我知道线程的理论,但我没有完全意识到它是如何在Java中实现的,因此我可能会仔细研究这一点。 – 2011-04-30 20:03:16

+0

一般来说,你不需要线程来使GUI工作 - 这是我试图解释。您需要线程来执行需要更长时间的操作,并且您想阻止它们阻止GUI。但是,由于线程增加了很多复杂性(你刚刚得到了一些等待问题),应该尽可能没有线程。在你的情况下,你永远不会(并且我的意思是从来没有)应该在主事件线程上调用wait,因为那样你肯定会阻止你的GUI。 – 2011-04-30 20:08:56

+0

你可以开始一个新的线程,并在那里等待,然后通知它,当它醒来时,它可以使用Swings invokeLater(必要的,因为Swing大多不是线程安全的)更改GUI。 – 2011-04-30 20:09:29