2014-07-14 48 views
2

我注意到功能Control#setLocation(int, int)的一個問題。我用它來同步兩個Shell之間的移動,即如果我移動第一個,第二個移動相同數量的像素。控制集偏移4px在Windows 7上

這一切都正常工作,除了一件小事:調用setLocation()Shell的實際位置偏移4像素(在Windows 7上,沒有得到改變,在另一個操作系統上測試它)。

下面是說明該問題的示例程序:

public class StackOverflow 
{ 
    public static void main(String[] args) 
    { 
     Display display = new Display(); 
     final Shell shell = new Shell(); 
     shell.setLayout(new GridLayout(5, true)); 

     for (int i = 0; i < 25; i++) 
      new Label(shell, SWT.NONE).setText("Label: " + i); 

     final Shell otherShell = new Shell(shell); 
     otherShell.setLayout(new FillLayout()); 
     new Button(otherShell, SWT.PUSH).setText("Button"); 

     Listener synchronizeMovement = new Listener() 
     { 
      @Override 
      public void handleEvent(Event event) 
      { 
       Rectangle parentBounds = shell.getBounds(); 
       Rectangle displayBounds = Display.getDefault().getBounds(); 
       Point size = otherShell.getSize(); 

       /* Check if there's sufficient space to the right of the parent */ 
       if ((displayBounds.width - (parentBounds.width + parentBounds.x)) >= size.x) 
       { 
        otherShell.setLocation(parentBounds.x + parentBounds.width, parentBounds.y); 
        System.out.println(parentBounds + " -> (" + (parentBounds.x + parentBounds.width) + ", " + parentBounds.y + ")"); 
       } 
      } 
     }; 

     shell.addListener(SWT.Move, synchronizeMovement); 
     otherShell.addListener(SWT.Show, synchronizeMovement); 

     shell.pack(); 
     shell.open(); 
     otherShell.pack(); 
     otherShell.open(); 

     while (!shell.isDisposed()) 
     { 
      if (!display.readAndDispatch()) 
      { 
       display.sleep(); 
      } 
     } 
     display.dispose(); 
    } 
} 

如果我以這樣的方式定位在主窗口,該輸出是

矩形{124,100,276, 143} - >(400,100)

我得到以下人工測量後的結果:

enter image description here

這使我得出的結論是有一個抵消/邊界/保證金/無論涉及,我不知道。

期望的結果是調用setLocation(400, 100)導致Shell位於「(400,100)」而不是「(396,96)」(這應該是一個合理的假設,對嗎?)。

有沒有人有詳細的見解,爲什麼這是這種情況,以及如何解決它?


更新

如果我使用SWT.NO_TRIMotherShell的風格它工作得很好。所以它必須與窗飾(框架)有關。

+2

這是值得這項工作在Mac OS X上正確工作 –

+0

謝謝@ greg-449,這是很好的知道。當我回家時,我會在Linux上嘗試它。 – Baz

+0

SWT是否有像AWT這樣的getInsets()函數? getInsets()返回AWT中Frame的邊框大小。也許SWT有類似的功能。 –

回答

1

好吧,我發現了這個問題。閱讀Shell的文檔,我發現這一點:

public Shell(Shell parent) 

構建只給出其父這個類的一個新實例。它創建於風格SWT.DIALOG_TRIM

SWT.DIALOG_TRIM(這是SWT.CLOSE | SWT.TITLE | SWT.BORDER)在Windows上,似乎加Shell解決這個微胖/保證金/邊界。

這個小例子說明了這個問題:

public static void main(String[] args) 
{ 
    Display display = new Display(); 
    Shell shell = new Shell(); 

    shell.pack(); 
    shell.open(); 
    shell.setBounds(0, 0, 100, 100); 

    Shell childOne = new Shell(shell); 
    childOne.pack(); 
    childOne.open(); 
    childOne.setBounds(0, 100, 100, 100); 

    Shell childTwo = new Shell(SWT.DIALOG_TRIM); 
    childTwo.pack(); 
    childTwo.open(); 
    childTwo.setBounds(0, 200, 100, 100); 

    while (!shell.isDisposed()) 
    { 
     if (!display.readAndDispatch()) 
     { 
      display.sleep(); 
     } 
    } 
    display.dispose(); 
} 

是這樣的:

enter image description here

這使得它很明顯,SWT.DIALOG_TRIM負責...

在我來說,我解決它通過明確指定的樣式:

new Shell(shell, SWT.SHELL_TRIM); 

TL;博士

如果你想定位您Shell像素完美,不要使用SWT.DIALOG_TRIM,而是SWT.SHELL_TRIM或者根本不創建Shell作爲另一個Shell的子項。