2010-01-21 43 views
29

當用戶單擊JFrame的角落以調整大小並拖動鼠標時,JFrame將根據用戶拖動的鼠標的當前位置重新繪製。你怎麼能聽這些事件?在用戶拖動鼠標時收聽JFrame調整大小事件?

下面是我所目前正在嘗試:

public final class TestFrame extends JFrame { 
    public TestFrame() { 
     this.addComponentListener(new ComponentAdapter() { 
      public void componentResized(ComponentEvent e) { 
       // This is only called when the user releases the mouse button. 
       System.out.println("componentResized"); 
      } 
     }); 
    } 

    // These methods do not appear to be called at all when a JFrame 
    // is being resized. 
    @Override 
    public void setSize(int width, int height) { 
     System.out.println("setSize"); 
    } 

    @Override 
    public void setBounds(Rectangle r) { 
     System.out.println("setBounds A"); 
    } 

    @Override 
    public void setBounds(int x, int y, int width, int height) { 
     System.out.println("setBounds B"); 
    } 
} 

如何確定並限制用戶如何調整其大小的窗口(基於窗口的當前長寬比),因爲他們周圍拖動鼠標周圍?

+0

@finnw請你澄清你的賞金理由,因爲我看到'Java_1.4'和'Java_1.5'之間的區別,但是我找不到'Java_6','note'的區別,但是沒有最深的檢查到嵌套和繼承方法 – mKorbel 2011-10-06 08:53:39

+0

@mKorbel,我嘗試了兩種方法(JPanel上的ComponentListener;覆蓋驗證)。代碼編譯並在兩個版本的Java下運行,但在Java 1.6中,佈局不斷被重新計算,但是在Java 1.5只有當我釋放鼠標。 – finnw 2011-10-06 12:17:35

+0

@finnw你調整JComponent或JFrame – mKorbel 2011-10-06 12:23:40

回答

7

你可能需要重寫像validate(不要忘記調用超級)。當然,如果您使用窗口系統配置爲拖動輪廓線,這仍然可能不起作用。

+0

我怎麼會叫我認爲你只能在構造函數中調用超級域名? – 2011-06-09 16:55:37

+3

哎呀,找到它了。super.validate(),當然。 – 2011-06-09 17:00:12

37

您可以添加組件偵聽器,並實現這樣的功能的componentResized:

JFrame component = new JFrame("My Frame"); 

component.addComponentListener(new ComponentAdapter() 
{ 
     public void componentResized(ComponentEvent evt) { 
      Component c = (Component)evt.getSource(); 
      //........ 
     } 
}); 

編輯:顯然,對於JFrame的,上的componentResized事件被掛在事件的mouseReleased。這就是爲什麼當釋放鼠標按鈕時調用該方法的原因。

實現所需目標的一種方法是添加一個覆蓋整個JFrame區域的JPanel。然後將componentListener添加到JPanel(即使鼠標仍在拖動時,也會調用componentResized for JPanel)。當您的框架調整大小時,您的面板也將調整大小。

我知道,這不是最優雅的解決方案,但它的工作原理!

+0

感謝您的及時響應。但是,componentResized僅在用戶釋放鼠標按鈕時纔會調用。是否有可能聽到調整事件大小*爲用戶拖動鼠標? – Clinton 2010-01-21 01:50:44

+0

@Clinton真的!對不起,我沒有仔細閱讀你的問題! – Alex 2010-01-21 01:56:02

+0

@Clinton我很好奇這是如何完成的,我發現的唯一方法是在JFrame中添加一個JPanel。我不知道這是否有助於你。我已經更新了我的答案。 – Alex 2010-01-21 03:03:08

-2
public class MouseDrag extends Component implements MouseListener, 
    MouseMotionListener { 
    /** The Image we are to paint */ 
    Image curImage; 

    /** Kludge for showStatus */ 
    static Label status; 

    /** true if we are in drag */ 
    boolean inDrag = false; 

    /** starting location of a drag */ 
    int startX = -1, startY = -1; 

    /** current location of a drag */ 
    int curX = -1, curY = -1; 

    // "main" method 
    public static void main(String[] av) { 
    JFrame f = new JFrame("Mouse Dragger"); 
    Container cp = f.getContentPane(); 

    if (av.length < 1) { 
     System.err.println("Usage: MouseDrag imagefile"); 
     System.exit(1); 
    } 
    Image im = Toolkit.getDefaultToolkit().getImage(av[0]); 

    // create a MouseDrag object 
    MouseDrag j = new MouseDrag(im); 

    cp.setLayout(new BorderLayout()); 
    cp.add(BorderLayout.NORTH, new Label(
     "Hello, and welcome to the world of Java")); 
    cp.add(BorderLayout.CENTER, j); 
    cp.add(BorderLayout.SOUTH, status = new Label()); 
    status.setSize(f.getSize().width, status.getSize().height); 
    f.pack(); 
    f.setVisible(true); 
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    } 

    // "Constructor" - creates the object 
    public MouseDrag(Image i) { 
    super(); 
    curImage = i; 
    setSize(300, 200); 
    addMouseListener(this); 
    addMouseMotionListener(this); 
    } 

    public void showStatus(String s) { 
    status.setText(s); 
    } 

    // Five methods from MouseListener: 
    /** Called when the mouse has been clicked on a component. */ 
    public void mouseClicked(MouseEvent e) { 
    } 

    /** Called when the mouse enters a component. */ 
    public void mouseEntered(MouseEvent e) { 
    } 

    /** Called when the mouse exits a component. */ 
    public void mouseExited(MouseEvent e) { 
    } 


    // And two methods from MouseMotionListener: 
    public void mouseDragged(MouseEvent e) { 
    Point p = e.getPoint(); 
    // System.err.println("mouse drag to " + p); 
    showStatus("mouse Dragged to " + p); 
    curX = p.x; 
    curY = p.y; 
    if (inDrag) { 
     repaint(); 
    } 
    } 

    public void paint(Graphics g) { 
    int w = curX - startX, h = curY - startY; 
    Dimension d = getSize(); 
    g.drawImage(curImage, 0, 0, d.width, d.height, this); 
    if (startX < 0 || startY < 0) 
     return; 
    System.err.println("paint:drawRect @[" + startX + "," + startY 
     + "] size " + w + "x" + h); 
    g.setColor(Color.red); 
    g.fillRect(startX, startY, w, h); 
    } 

} 
+2

-1。這基本上是問題中的代碼的副本(我們已經知道並不能解決問題。) – finnw 2011-10-12 11:07:50

6

另一個解決方法(這是非常相似,Alex的,但有點更簡單)是從JFrame的根窗格,而不是聽事件:

public final class TestFrame extends JFrame { 
    public TestFrame() { 
     this.getRootPane().addComponentListener(new ComponentAdapter() { 
      public void componentResized(ComponentEvent e) { 
       // This is only called when the user releases the mouse button. 
       System.out.println("componentResized"); 
      } 
     }); 
    } 
} 

根據其他實施細節,可能會改變根窗格。如果這是可能性,那麼你可以覆蓋setRootPane()並處理。由於setRootPane()受保護,只能從構造函數調用,所以不太可能需要這樣做。

+0

不應該是'public void TestFrame(){'...? – 2014-01-05 02:53:43

+2

@AnnonomusPenguin,不,這是一個構造函數聲明,而構造函數不指定返回類型,如'void'。 – 2014-08-10 01:50:43