2012-03-29 54 views
1

我的理解是,可以通過使用組件的addXXXListener方法添加監聽器(例如MouseListener)來處理Swing事件。Swing中的事件處理(通過JFrame重寫它)

假設我想,無論如何,攔截一個組件(在我的情況下,一個JFrame)收到的所有事件,並做一些通用的例如。無論出於何種原因編寫我的自定義事件調度程序。一個非常繁瑣和慢速的方法是創建一個Listener類,每個事件監聽並對它們做一些事情。

但是,我發現了一個更好的主意:我延長JFrame,然後推翻的processEvent(AWTEvent中的事件),如下所示:

public class GameFrame extends JFrame 
{ 
    public GameFrame(int width, int height) 
    { 
     super(); 
     //blah blah, stuff 
     setVisible(true); 
    } 

    //override processEvent which is called in Component class every time an event happens 
    @Override 
    public void processEvent(AWTEvent event) 
    { 
     System.out.println("override " + event); 
     //do whatever I want with my event here, then send it back up 
     doSomething(event); 
     super.processEvent(event); 
    } 
} 

的想法是,每當一個事件上的JFrame發生,processEvent方法會被調用,我可以從那裏直接得到活動。

不幸的是,processEvent方法只能用WindowEvents調用。 MouseEvents和KeyEvents似乎不起作用:當我運行代碼時,System.out.println只打印出WindowEvents。

我想我知道原因 - 因爲在我的代碼中沒有MouseListeners,Component不會打擾調用processEvent,因爲沒有MouseListeners。所以我可能得到這個代碼工作,如果我創建並添加到JFrame的MouseListener,KeyListener等,但這與我前面提到的繁瑣和慢速方法沒有什麼不同。

那麼我該怎麼辦? 是否還有其他一些組件方法,每當組件發生事件時都會調用,並且可以重寫它以便直接從馬的嘴中截取組件上的所有事件,而不必使用Listener?

回答

2

這是因爲JFrame只支持兩種類型的事件。在JFrame.java,有一行:

protected void frameInit() { 
    enableEvents(AWTEvent.KEY_EVENT_MASK | AWTEvent.WINDOW_EVENT_MASK); 
    //other code here. 
} 

解決的辦法是像下面,改變JFrame的行爲,迫使它向listene和的MouseEvent其它事件你名(〔實施例:AWTEvent.MOUSE_MOTION_EVENT_MASK或MOUSE_WHEEL_EVENT_MASK)。

enableEvents()在Component類中,它是受保護的方法,所以必須使用反射來四處走動。

public static void main(String[] args) 
    throws NoSuchMethodException, InvocationTargetException, IllegalAccessException 
{ 
    JFrame frame = new GameFrame(); 
    frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 
    frame.setLocationRelativeTo(null); 
    frame.setSize(800, 600); 

    frame.setVisible(true); 
} 

public static class GameFrame extends JFrame 
{ 
    public GameFrame() 
    { 
     super(); 
     enableEvent(AWTEvent.KEY_EVENT_MASK | AWTEvent.WINDOW_EVENT_MASK | AWTEvent.MOUSE_EVENT_MASK); 
    } 

    //override processEvent which is called in Component class every time an event happens 
    @Override 
    public void processEvent(AWTEvent event) 
    { 
     System.out.println("override " + event); 
     super.processEvent(event); 
    } 

} 
+0

+1但沒有詳細解答OP – mKorbel 2012-03-29 19:50:39

+0

感謝您的投票,但哪一部分您想了解更多細節?反射部分?我可以添加更多評論。 – chenyi1976 2012-03-29 22:38:22

+0

OP在這裏 - 謝謝你的答案!不過,我不確定你爲什麼使用反射;我簡單地從我的GameFrame的構造函數中調用了enableEvents(),並且它的工作非常完美......對於我用過的方法,我可能還有些警告我不知道? – user1299784 2012-03-31 02:49:38