java fx如果Swt对话框改变了位置,则上下文菜单将显示错误的位置

时间:2017-03-12 11:48:08

标签: javafx swt

我有以下测试代码,在linux env(如ubuntu)中运行。上下文菜单将显示menubutton邻居的错误位置。 屏幕截图如enter image description here

import java.io.IOException;
import java.net.URL;
import java.util.function.Function;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Shell;

import application.SWTTestUtil;
import javafx.embed.swt.FXCanvas;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;

public class ContextMenuTestingComposite extends Composite {
  private FXCanvas fxCanvas;

  public ContextMenuTestingComposite(Composite parent, int style) {
    super(parent, SWT.NONE);
    setLayout(new FillLayout());
    fxCanvas = new FXCanvas(this, SWT.NONE);
    Parent root = getRoot();
    if (root == null) {
      return;
    }
    Scene scene = new Scene(root);
    fxCanvas.setScene(scene);
  }

  protected Parent getRoot() {
    FXMLLoader fxmlLoader = new FXMLLoader(getURL());
    fxmlLoader.setController(this);

    Parent root = null;
    try {
      root = fxmlLoader.load();
    } catch (IOException e) {
      e.printStackTrace();
    }
    return root;
  }

  protected URL getURL() {
    return getClass().getResource("contextmenuTestingComposite.fxml");
  }

  public static void main(String[] args) {
    Display display = new Display();
    Shell shell = new Shell(display);
    shell.setSize(800, 600);
    shell.setText("test the context menu");
    shell.setLayout(new GridLayout(1, false));
    centerShellToPrimaryWindow(shell.getDisplay(), shell);
    ContextMenuTestingComposite composite = new ContextMenuTestingComposite(shell, SWT.NONE);
    composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
    shell.open();
    while (!shell.isDisposed()) {
      if (!display.readAndDispatch()) {
        display.sleep();
      }
    }
    display.dispose();
  }

  public static void centerShellToPrimaryWindow(Display display, Shell shell) {
    Monitor primary = display.getPrimaryMonitor();
    Rectangle bounds = primary.getBounds();
    Rectangle rect = shell.getBounds();

    int x = bounds.x + (bounds.width - rect.width) / 2;
    int y = bounds.y + (bounds.height - rect.height) / 2;
    shell.setLocation(x, y);
  }

}

FXML

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.geometry.Insets?>
<?import javafx.scene.control.ComboBox?>
<?import javafx.scene.control.MenuButton?>
<?import javafx.scene.control.MenuItem?>
<?import javafx.scene.layout.VBox?>


<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="600.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1">
   <children>
      <ComboBox prefWidth="150.0" />
      <MenuButton mnemonicParsing="false" text="MenuButton">
        <items>
          <MenuItem mnemonicParsing="false" text="Action 1" />
          <MenuItem mnemonicParsing="false" text="Action 2" />
        </items>
         <VBox.margin>
            <Insets top="59.0" />
         </VBox.margin>
      </MenuButton>
   </children>
</VBox>

有谁知道这个问题?这个问题将通过稍微移动一下来解决。以前,如何通过程序来实现?

1 个答案:

答案 0 :(得分:2)

我在Linux中遇到了同样的问题,这是解决方法-激活SWT对话框(外壳)后,将其“摇动”一次。

shell.addShellListener(new ShellAdapter() {
   @Override
   public void shellActivated(ShellEvent e) {
       Point p = shell.getLocation();
       shell.setLocation(p.x, p.y - 1);
       shell.setLocation(p.x, p.y);

       shell.removeShellListener(this);
   }
});

希望对您有帮助。