2014-07-14 26 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的子项。