2010-08-09 27 views
1

我正在研究一個應用程序,該應用程序涉及用戶需要將鼠標懸停在屏幕上的多個移動點上以啓動特定的彈出窗口。目前,我正在偵聽JPanel上的mouseMoved事件,其中渲染了點,然後在光標位於點的特定距離內時啓動所需的彈出窗口。Java - 自定義形狀面板?

當我有數百個點 - 這可能會變得相當昂貴。

難道理想的解決方案是將我的「小點」表示爲小組件,並在每個點上註冊鼠標監聽器?

有誰知道我可能代表一個小的橢圓與JComponent

非常感謝

回答

1

以下是一些顯示如何創建「圓形」JButton的舊代碼。我將擴展JComponent的替代和重要的方法覆蓋是的paintComponent()和包含():

import java.awt.*; 
import java.awt.event.*; 
import java.awt.geom.*; 
import javax.swing.*; 

public class RoundButton extends JButton { 
    public RoundButton(String label) { 
     super(label); 

     // These statements enlarge the button so that it 
     // becomes a circle rather than an oval. 
     Dimension size = getPreferredSize(); 
     size.width = size.height = Math.max(size.width, size.height); 
     setPreferredSize(size); 

     // This call causes the JButton not to paint the background. 
     // This allows us to paint a round background. 
     setContentAreaFilled(false); 
    } 

    // Paint the round background and label. 
    protected void paintComponent(Graphics g) { 
    if (getModel().isArmed()) { 
      // You might want to make the highlight color 
      // a property of the RoundButton class. 
      g.setColor(Color.lightGray); 
     } else { 
      g.setColor(getBackground()); 
     } 
    g.fillOval(0, 0, getSize().width-1, getSize().height-1); 

     // This call will paint the label and the focus rectangle. 
    super.paintComponent(g); 
    } 

    // Paint the border of the button using a simple stroke. 
    protected void paintBorder(Graphics g) { 
     g.setColor(getForeground()); 
     g.drawOval(0, 0, getSize().width-1, getSize().height-1); 
    } 

    // Hit detection. 
    Shape shape; 
    public boolean contains(int x, int y) { 
     // If the button has changed size, make a new shape object. 
     if (shape == null || !shape.getBounds().equals(getBounds())) { 
      shape = new Ellipse2D.Float(0, 0, getWidth(), getHeight()); 
     } 
     return shape.contains(x, y); 
    } 

    // Test routine. 
    public static void main(String[] args) { 
     // Create a button with the label "Jackpot". 
     JButton button = new RoundButton("Jackpot"); 
     button.setBackground(Color.green); 
     button.setBounds(0, 0, 100, 100); 

     JButton button2 = new RoundButton("Jackpot2"); 
     button2.setBackground(Color.red); 
     button2.setBounds(50, 50, 100, 100); 

     // Create a frame in which to show the button. 
     JFrame frame = new JFrame(); 
     frame.getContentPane().setBackground(Color.yellow); 
     frame.getContentPane().setLayout(null); 
     frame.getContentPane().add(button); 
     frame.getContentPane().add(button2); 
//  frame.getContentPane().setLayout(new FlowLayout()); 
     frame.setSize(200, 200); 
     frame.setVisible(true); 

     MouseListener mouseListener = new MouseAdapter() { 
      public void mouseEntered(MouseEvent e) 
      {} 

      public void mouseExited(MouseEvent e) 
      {} 

      public void mouseClicked(MouseEvent e) 
      { 
       System.out.println("clicked "); 
      } 

      public void mousePressed(MouseEvent e) 
      { 
       System.out.println("pressed "); 
      } 

      public void mouseReleased(MouseEvent e) 
      { 
       System.out.println("released "); 
      } 
     }; 
     button.addMouseListener(mouseListener); 

    } 
} 

這很容易簡化了碰撞檢測,因爲沒有自定義代碼。由於您可以控制每個組件的Z順序,因此它還允許您輕鬆控制compnents的重疊。

+0

謝謝這是非常有用的! – TotalCruise 2010-08-11 08:16:55

1

您寫「此可能變得相當昂貴,」不管你自己編寫的「isMouseCloseToDot」方法

,或者你是否使用內置到搖擺的東西,在這兩種情況下的工作仍在需要由計算機執行以確定點是否已激活。

我建議堅持你目前的做法,除非你確定這種方法確實太昂貴了。用幾百個點做一個小測試。響應時間是否可以接受?

+0

這是可以接受的。我有很多很多的監聽事件來執行面板上的各種對象。所以,雖然我認爲swing例程會更有效率,但我還面臨着一個監聽器類,其中有許多搜索循環,並引用了面板上呈現的對象列表。爲了簡化代碼的觀點 - 這種方法也可以帶來好處。 – TotalCruise 2010-08-09 11:08:55

0

不確定哪種方法更昂貴,但基於組件的方法肯定更容易實現。

您只需要創建自己的組件,即可覆蓋paintcontains方法。將其添加到容器中的特定位置(使用絕對佈局或任何其他取決於您的需要)。您的聽衆將成爲提供組件行爲的新組件的一部分。

從設計和程序組織的角度來看,這是更優越的方法。