2012-05-03 27 views
3

我想設置JPopupMenu的位置,具體取決於打開菜單的按鈕的y位置。我的代碼在我的第一臺顯示器上工作正常,但在第二臺顯示器上失敗,這個顯示器的高度不同。 問題是getLocationOnScreen()傳遞相對於主屏幕的位置,而不是顯示組件的實際屏幕。在當前顯示器上獲取組件位置

我的代碼:

// screenSize represents the size of the screen where the button is 
// currently showing 
final Rectangle screenSize = dateButton.getGraphicsConfiguration().getBounds(); 

final int yScreen = screenSize.height; 
int preferredY; 

// getLocationOnScreen does always give the relative position to the main screen 
if (getLocationOnScreen().y + dateButton.getHeight() + datePopup.getPreferredSize().height > yScreen) { 
    preferredY = -datePopup.getPreferredSize().height; 
} else { 
    preferredY = getPreferredSize().height; 
} 

datePopup.show(DateSpinner.this, 0, preferredY); 

我怎樣才能實際顯示器上得到一個組件的位置?

回答

5

我使用第二屏幕的界限了一個解決方案,這是相當簡單:

public static Point getLocationOnCurrentScreen(final Component c) { 
    final Point relativeLocation = c.getLocationOnScreen(); 

    final Rectangle currentScreenBounds = c.getGraphicsConfiguration().getBounds(); 

    relativeLocation.x -= currentScreenBounds.x; 
    relativeLocation.y -= currentScreenBounds.y; 

    return relativeLocation; 
} 

謝謝您的回答!

+1

如果輔助監視器是相反的站點,該怎麼辦?如果主顯示器和輔助顯示器發生變化怎麼辦? – Stefan

+0

不應該是「+ =」? –

1

通常,當你調用「getLocationOnScreen()」時,它會得到組件「this」的位置(來自代碼我不太明白「this」是誰)。

也許你可以嘗試通過使用「button.getLocationOnScreen()」獲取按鈕的位置。

+0

這被稱爲包含按鈕的面板的內部。 – Stephan

1

這是一個小片段,展示瞭如何將元素相對於另一個元素進行定位。它在按鈕下方顯示一個彈出式菜單,在其左側顯示一個JDialog。我在多屏幕環境中進行了測試,其中次屏幕位於主屏幕的右側。

此外,使用getSize(),getWidth()和getHeight()而不是getPreferredSize()。 getSize(),getWidth和getHeight返回組件的實際尺寸,而getPreferredSize()僅僅是LayoutManager指示組件希望具有的指標。

如果使用方法JPopupMenu.show(),請確保使用相對於調用者組件的座標和大小。

import java.awt.Dimension; 
import java.awt.Point; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.ComponentEvent; 
import java.awt.event.ComponentListener; 

import javax.swing.JButton; 
import javax.swing.JDialog; 
import javax.swing.JFrame; 
import javax.swing.JMenuItem; 
import javax.swing.JPopupMenu; 

public class Test2 { 

    public static void main(String[] args) { 

     final JFrame frame = new JFrame(); 
     final JButton button = new JButton("Hello"); 
     button.addActionListener(new ActionListener() { 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       JPopupMenu popupMenu = new JPopupMenu(); 
       popupMenu.add(new JMenuItem("Some test")); 
       System.err.println(button.getLocationOnScreen()); 
       popupMenu.show(button, 0, button.getHeight()); 
       JDialog dialog = new JDialog(frame); 
       dialog.setSize(100, 30); 
       Point locationOnScreen = button.getLocationOnScreen(); 
       locationOnScreen.x += button.getWidth(); 
       dialog.setLocation(locationOnScreen); 
       dialog.setVisible(true); 
      } 
     }); 
     frame.addComponentListener(new ComponentListener() { 

      @Override 
      public void componentShown(ComponentEvent e) { 

      } 

      @Override 
      public void componentResized(ComponentEvent e) { 
       info(button); 
      } 

      private void info(final JButton button) { 
       if (button.isShowing()) { 
        System.err.println(button.getLocationOnScreen()); 
        System.err.println(button.getGraphicsConfiguration().getBounds()); 
       } 
      } 

      @Override 
      public void componentMoved(ComponentEvent e) { 
       info(button); 
      } 

      @Override 
      public void componentHidden(ComponentEvent e) { 

      } 
     }); 
     button.setPreferredSize(new Dimension(200, 60)); 
     frame.add(button); 
     frame.pack(); 
     frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 
     frame.setVisible(true); 
    } 
}