2013-09-24 42 views
1

我學習的Java Swing和適配器來處理事件,但我不得不涉及到以下工作比如有些懷疑,我學習:有關的Java Swing使用適配器和聽衆的一些疑問

import java.awt.*; 
import java.awt.event.*; 

import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.border.TitledBorder; 

public class ListenerDemo extends JPanel implements MouseMotionListener{ 

    // Label che visualizzano la posizione X ed Y del cursore: 
    JLabel labelX; 
    JLabel labelY; 

    public ListenerDemo() { 

     /* Add a MouseMotionListener to this object to catch when the user uses the mouse: */ 
     addMouseMotionListener(this); 

     Font f = new Font(Font.SANS_SERIF, Font.PLAIN, 50); 

     TitledBorder borderX = new TitledBorder("Mouse X"); 
     TitledBorder borderY = new TitledBorder("Mouse Y"); 

     borderX.setTitleJustification(TitledBorder.CENTER); 
     borderY.setTitleJustification(TitledBorder.CENTER); 

     labelX = new JLabel("0"); 
     labelX.setBorder(borderX); 
     labelY = new JLabel("0"); 
     labelY.setBorder(borderY); 

     labelX.setFont(f); 
     labelY.setFont(f); 
     super.add(labelX); 
     super.add(labelY); 

    } 

    // NOT IMPLEMENTED: 
    public void mouseDragged(MouseEvent e) {} 

    // IMPLEMENTED: 
    public void mouseMoved(MouseEvent e) { 
     labelX.setText("X : "+e.getX()); 
     labelY.setText("Y : "+e.getY()); 
    } 


    public static void main(String [] argv) { 

     // WindowsAdapter che implementa solo il metodo WindowClosing() 
     WindowAdapter adpt = new WindowAdapter() { 
      /* 
      * Alla chiusura della finestra ripassa il focus al frame principale. 
      * @param A low-level event that indicates that a window has changed its status 
      */ 
      public void windowClosing(WindowEvent e) { 
       System.exit(0); 
      } 
     }; 

     JFrame frame = new JFrame("ListenerDemo"); // Frame esterno 

     // Add at the frame ONLY the anonymous adapter WindowAdapter class: 
     frame.addWindowListener(adpt); 

     // Add to the ContentPane inside the frame the ListenerDemo listener: 
     frame.getContentPane().add(new ListenerDemo(), null); 

     // Display the window: 
     frame.pack(); 
     frame.setVisible(true); 
     frame.setExtendedState(JFrame.MAXIMIZED_BOTH); 
    } 
} 

我有一些困難,理解這個程序的邏輯:

第一個疑問是爲什麼** ListenerDemo類extendes JPanel並實現的MouseMotionListener

我認爲,該方案的邏輯是以下之一:

裏面的的main()方法創建一個新的WindowAdapter的對象,它是WindowAdapter的的實例,讓我只實施一些處理與我的事件相關的事件的方法。所以,使用這個適配器,我可以避免實現一些不感興趣的偵聽器方法。在這種情況下,WindowAdapter只實現與窗口閉合有關的方法,而不實現其他窗口事件。

是這個推理是否正確?

以下示例顯示了與使用經典偵聽器的概念的不同之處,在這個經典偵聽器中我必須實現處理所有與特定偵聽器相關的事件的所有方法。

在這個例子中,在我的main(),我添加自定義ListenerDemo到該幀的內容,我認爲此偵聽由該行添加一個addMouseMotionListener到當前對象:

addMouseMotionListener(this); 

因此,我有一個偵聽器,可以捕獲與我的框架內容中使用鼠標有關的所有事件。

在這種情況下,因爲我使用的傾聽者,我必須實現的MouseMotionListener聽衆的兩種方法:addMouseMotionListenerremoveMouseMotionListener

它是正確的嗎?

我還有一個疑問:在我看來,這種編碼風格是pretti可怕的(但也許這只是我的印象,因爲我不知道它),因爲它在一個類中都可以完成,我可以將它分離更好的方法?

TNX

安德烈

+0

在這個例子中,'WindowAdapter'沒有用,因爲可以通過使用'frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)'來完成這件事,儘管更喜歡'frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE)'。而且,'MouseMotionListener'只是在'JPanel'即''ListenerDemo'類上移動鼠標時更新'JLabel','mouseMoved(...)'方法用於更新'JLabel'上的文本。有關問題的分離,請參閱[MVC-Pattern](http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller),Swing也在內部使用它 –

回答

3

ListenerDemo是一個圖形用戶界面,所以這就是爲什麼它擴展JPanel:這樣,它繼承了默認面板的所有圖形屬性。

在我看來,ListenerDemo也實施MouseMotionListener是不好的做法。這是適配器模式的濫用。那麼這種模式是什麼?

總之:在ListenerDemo你有一些代碼:

labelX.setText("X : "+e.getX()); 
labelY.setText("Y : "+e.getY()); 

要線到面板的事件:當鼠標移動。

典型的適配器模式使用匿名內部類這樣的:

public ListenerDemo() { 

    addMouseMotionListener(new MouseMotionListener() { 
     // NOT IMPLEMENTED: 
     public void mouseDragged(MouseEvent e) {} 

     // IMPLEMENTED: 
     public void mouseMoved(MouseEvent e) { 
      labelX.setText("X : "+e.getX()); 
      labelY.setText("Y : "+e.getY()); 
     } 
    }); 

    // remaining code 
} 

的效果是非常相同的,但在我看來,這是尷尬,使ListenerDemo實施MouseMotionListener。沒有其他外部類需要知道您的演示可以捕獲鼠標事件,所以它應該隱藏在其實現中。

3

*Adapter類只是有用的存根,爲實現接口的每個方法提供空實現。如果你不想實現所有的方法,你可以使用它們 - 就像你只關心窗口關閉事件的例子。

實現您的UI的類也實現了事件處理程序接口是非常普遍的做法。這主要是因爲它很方便,但實際上它是不好的風格!你的ListenerDemo只需要內部監聽器,所以將它添加到類的公共API並不是一個好主意。 (你不希望你的類的用戶在某個地方使用它作爲一個MouseMotionListener,你呢?)

所以更好的做法是有一個匿名內部類,要麼實現MouseMotionListenerMouseAdapter派生:

private final MouseMotionListener mouseListener = new MouseAdapter() { 
    public void mouseMoved(MouseEvent e) { 
     labelX.setText("X : "+e.getX()); 
     labelY.setText("Y : "+e.getY()); 
    } 
} 

現在,在構造函數中,您可以註冊mouseListener而不是this

關於你關於分離的問題:你應該/可以將主要方法移到一個單獨的'Main'類中。