2011-04-28 108 views
1

我有一個在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

回答

2

第一:

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