Java 模态JDialog的最佳位置以避免卡住

Java 模态JDialog的最佳位置以避免卡住,java,swing,jframe,jdialog,Java,Swing,Jframe,Jdialog,我的Swing应用程序必须向用户显示一个模式对话框。很抱歉没有发布SSCCE topContainer可能是JFrame或JApplet private class NewGameDialog extends JDialog { public NewGameDialog () { super(SwingUtilities.windowForComponent(topContainer), "NEW GAME", ModalityType.APPLICATION_MOD

我的Swing应用程序必须向用户显示一个模式对话框。很抱歉没有发布SSCCE

topContainer
可能是
JFrame
JApplet

private class NewGameDialog extends JDialog {
     public NewGameDialog () {
         super(SwingUtilities.windowForComponent(topContainer), "NEW GAME", ModalityType.APPLICATION_MODAL);

         //add components here

         getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));

         //TODO:
         setSize(new Dimension(250, 200));
         setLocation(650, 300);
     }
}
我在网络事件中像这样启动对话框

SwingUtilities.invokeLater(new Runnable() {
     @Override
     public void run() {
         NewGameDialog dialog = new NewGameDialog();
         dialog.setVisible(true);
     }
});
问题是为我的对话框设置最佳位置

1) 如果它被设置为绝对值,我将应用程序框架移动到第二个屏幕,那么第一个屏幕上会显示一个奇怪的对话框

2) 如果将相对值设置为JFrame,则用户可能会将应用程序框架移到屏幕之外,并且相对定位的对话框对用户不可见。因为它是模态的,所以游戏会被卡住


<>强>什么是考虑上述两个问题的最佳解决方案?>/P>> P> >我认为,最好是把对话中心放在当前屏幕的中间。
这总是有效的,如果它正好在屏幕中央,用户怎么会看不见它呢?和
setLocationRelativeTo
也可以使用,但您需要使用。

这让我想起了我最喜欢的一篇文章,using on StackOverflow

编辑1:

您可以将
FocusListener
添加到
JDialog
中,在
focusgound(…)
方法中,您可以对
JFrame
JDialog
使用
setLocationRelativeTo(null)
,这样它们都会出现在屏幕中央,无论它们之前在哪里

import java.awt.*;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;

/**
 * Created with IntelliJ IDEA.
 * User: Gagandeep Bali
 * Date: 1/14/13
 * Time: 7:34 PM
 * To change this template use File | Settings | File Templates.
 */
public class FrameFocus
{
    private JFrame mainwindow;
    private CustomDialog customDialog;

    private void displayGUI()
    {
        mainwindow = new JFrame("Frame Focus Window Example");
        customDialog = new CustomDialog(mainwindow, "Modal Dialog", true);
        mainwindow.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        JPanel contentPane = new JPanel();
        JButton mainButton = new JButton(
                "Click me to open a MODAL Dialog");
        mainButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (!customDialog.isShowing())
                    customDialog.setVisible(true);
            }
        });
        contentPane.add(mainButton);
        mainwindow.setContentPane(contentPane);
        mainwindow.pack();
        mainwindow.setLocationByPlatform(true);
        mainwindow.setVisible(true);
    }

    public static void main(String... args)
    {
        EventQueue.invokeLater(new Runnable()
        {
            @Override
            public void run()
            {
                new FrameFocus().displayGUI();
            }
        });
    }
}


class CustomDialog extends JDialog
{
    private JFrame mainWindow;
    public CustomDialog(JFrame owner, String title, boolean modal)
    {
        super(owner, title, modal);
        mainWindow = owner;
        JPanel contentPane = new JPanel();
        JLabel dialogLabel = new JLabel(
                "I am a Label on JDialog.", JLabel.CENTER);
        contentPane.add(dialogLabel);
        setContentPane(contentPane);
        pack();

        addFocusListener(new FocusListener() {
            @Override
            public void focusGained(FocusEvent e) {
                mainWindow.setLocationRelativeTo(null);
                setLocationRelativeTo(null);
            }

            @Override
            public void focusLost(FocusEvent e) {
                /*
                 * Nothing written for this part yet
                 */
            }
        });
    }
}
编辑2:

我到处搜索了一下,结果发现,在我看来,您的应用程序首先出现在哪个
监视器屏幕上,这将决定它的可用性。尽管我在API中漫游时,对于所述的
图形配置
thingy只有一个getter方法,而没有setter方法(仍然可以通过任何顶级窗口的构造函数指定一个,即/)

现在你可以用这个代码来占据你的头脑,它可以用来确定你想要设置的适当位置,同样,我认为你可能需要使用
focusGain()
方法来满足你问题的条件2。查看附带的代码,尽管不需要创建新的JFrame/JDialog,但只需查看如何获取屏幕坐标(您可以在
focusGain()
方法中添加坐标以确定整个应用程序的位置)

只是:

setLocationRelativeTo(mainWindow);
为了测试上述内容,我使用了我的
FrameFocus
类,尽管我已经将您的更改添加到了我的
CustomDialog
方法中,如此修改的
CustomDialog
类所示

class CustomDialog extends JDialog
{
    private JFrame mainWindow;
    public CustomDialog(JFrame owner, String title, boolean modal)
    {
        super(owner, title, modal);
        mainWindow = owner;
        JPanel contentPane = new JPanel();
        JLabel dialogLabel = new JLabel(
                "I am a Label on JDialog.", JLabel.CENTER);
        contentPane.add(dialogLabel);
        setContentPane(contentPane);
        pack();

        addFocusListener(new FocusListener() {
            @Override
            public void focusGained(FocusEvent e) {
                //mainWindow.setLocationRelativeTo(null);
                //setLocationRelativeTo(null);
                GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
                GraphicsDevice[] gs = ge.getScreenDevices();
                for (int j = 0; j < gs.length; j++) {
                    GraphicsDevice gd = gs[j];
                    GraphicsConfiguration[] gc = gd.getConfigurations();
                    for (int i=0; i < gc.length; i++) {
                        Rectangle gcBounds = gc[i].getBounds();

                        Point loc = mainWindow.getLocationOnScreen();
                        if (gcBounds.contains(loc)) {
                            System.out.println("at " + j + " screen");

                            int x = gcBounds.x + (gcBounds.width - mainWindow.getWidth()) / 2;
                            int y = gcBounds.y + (gcBounds.height - mainWindow.getHeight()) / 2;
                            mainWindow.setLocation(x, y);

                            //x = (int) (loc.getX() + (mainWindow.getWidth() - CustomDialog.this.getWidth()) / 2);
                            //y = (int) (loc.getY() + (mainWindow.getHeight() - CustomDialog.this.getHeight()) / 2);
                            //CustomDialog.this.setLocation(x, y);
                            CustomDialog.this.setLocationRelativeTo(mainWindow);

                            break;
                        }
                    }
                }
            }

            @Override
            public void focusLost(FocusEvent e) {
                /*
                 * Nothing written for this part yet
                 */
            }
        });
    }
}
class CustomDialog扩展JDialog
{
私有JFrame主窗口;
公共自定义对话框(JFrame所有者、字符串标题、布尔模式)
{
超级(所有者、所有权、模态);
主窗口=所有者;
JPanel contentPane=新的JPanel();
JLabel dialogLabel=新的JLabel(
“我是JDialog上的一个标签。”,JLabel.CENTER);
contentPane.add(dialogLabel);
setContentPane(contentPane);
包装();
addFocusListener(新FocusListener(){
@凌驾
获得公共无效焦点(焦点事件e){
//mainWindow.setLocationRelativeTo(空);
//setLocationRelativeTo(空);
GraphicsEnvironment ge=GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice[]gs=ge.getScreenDevices();
对于(int j=0;j
用于在所需屏幕上移动
JDialog

导入java.awt.GridLayout;
导入java.awt.Point;
导入java.awt.event.ActionEvent;
导入javax.swing.AbstractAction;
导入javax.swing.Action;
导入javax.swing.JButton;
导入javax.swing.JDialog;
导入javax.swing.JFrame;
导入javax.swing.JPanel;
导入javax.swing.SwingUtilities;
导入javax.swing.border.EmptyBorder;
公共类jdialogatepoint{
私有JFrame=新JFrame();
private JPanel panel=new JPanel();
专用JDialog对话框;
专用点位置;
公共jDialogaPoint(){
createGrid();
createDialog();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
框架。添加(面板);
帧设置位置(100100);
frame.pack();
frame.setVisible(true);
}
私有void createGrid(){
panel.setLayout(新的GridLayout(3,3,4,4));
int l=0;
int行=3;
int col=3;
JBu
int x = loc.getX() + (mainWindow.getWidth() - getWidth()) / 2;
int y = loc.getY() + (mainWindow.getHeight() - getHeight()) / 2;
setLocation(x, y);
setLocationRelativeTo(mainWindow);
class CustomDialog extends JDialog
{
    private JFrame mainWindow;
    public CustomDialog(JFrame owner, String title, boolean modal)
    {
        super(owner, title, modal);
        mainWindow = owner;
        JPanel contentPane = new JPanel();
        JLabel dialogLabel = new JLabel(
                "I am a Label on JDialog.", JLabel.CENTER);
        contentPane.add(dialogLabel);
        setContentPane(contentPane);
        pack();

        addFocusListener(new FocusListener() {
            @Override
            public void focusGained(FocusEvent e) {
                //mainWindow.setLocationRelativeTo(null);
                //setLocationRelativeTo(null);
                GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
                GraphicsDevice[] gs = ge.getScreenDevices();
                for (int j = 0; j < gs.length; j++) {
                    GraphicsDevice gd = gs[j];
                    GraphicsConfiguration[] gc = gd.getConfigurations();
                    for (int i=0; i < gc.length; i++) {
                        Rectangle gcBounds = gc[i].getBounds();

                        Point loc = mainWindow.getLocationOnScreen();
                        if (gcBounds.contains(loc)) {
                            System.out.println("at " + j + " screen");

                            int x = gcBounds.x + (gcBounds.width - mainWindow.getWidth()) / 2;
                            int y = gcBounds.y + (gcBounds.height - mainWindow.getHeight()) / 2;
                            mainWindow.setLocation(x, y);

                            //x = (int) (loc.getX() + (mainWindow.getWidth() - CustomDialog.this.getWidth()) / 2);
                            //y = (int) (loc.getY() + (mainWindow.getHeight() - CustomDialog.this.getHeight()) / 2);
                            //CustomDialog.this.setLocation(x, y);
                            CustomDialog.this.setLocationRelativeTo(mainWindow);

                            break;
                        }
                    }
                }
            }

            @Override
            public void focusLost(FocusEvent e) {
                /*
                 * Nothing written for this part yet
                 */
            }
        });
    }
}
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;

public class JDialogAtPoint {

    private JFrame frame = new JFrame();
    private JPanel panel = new JPanel();
    private JDialog dialog;
    private Point location;

    public JDialogAtPoint() {
        createGrid();
        createDialog();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(panel);
        frame.setLocation(100, 100);
        frame.pack();
        frame.setVisible(true);
    }

    private void createGrid() {
        panel.setLayout(new GridLayout(3, 3, 4, 4));
        int l = 0;
        int row = 3;
        int col = 3;
        JButton buttons[][] = new JButton[row][col];
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                buttons[i][j] = new JButton("");
                buttons[i][j].putClientProperty("column", i + 1);
                buttons[i][j].putClientProperty("row", j + 1);
                buttons[i][j].setAction(updateCol());
                panel.add(buttons[i][j]);
                l++;
            }
        }
    }

    private void createDialog() {
        dialog = new JDialog();
        dialog.setAlwaysOnTop(true);
        dialog.setModal(true);
        dialog.setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE);
        JPanel pane = (JPanel) dialog.getContentPane();
        pane.setBorder(new EmptyBorder(20, 20, 20, 20));
        dialog.pack();
    }

    public Action updateCol() {
        return new AbstractAction("Display JDialog at Point") {

            private static final long serialVersionUID = 1L;

            @Override
            public void actionPerformed(ActionEvent e) {
                JButton btn = (JButton) e.getSource();
                System.out.println("Locations coordinates" + btn.getLocation());
                System.out.println("clicked column "
                        + btn.getClientProperty("column")
                        + ", row " + btn.getClientProperty("row"));
                if (!dialog.isVisible()) {
                    showingDialog(btn.getLocationOnScreen());
                }
            }
        };
    }

    private void showingDialog(final Point loc) {
        dialog.setVisible(false);
        location = loc;
        int x = location.x;
        int y = location.y;
        dialog.setLocation(x, y);
        Runnable doRun = new Runnable() {

            @Override
            public void run() {//dialog.setLocationRelativeTo(frame);
                dialog.setVisible(true);
            }
        };
        SwingUtilities.invokeLater(doRun);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                JDialogAtPoint cf = new JDialogAtPoint();
            }
        });
    }
}
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice[] gs = ge.getScreenDevices();
for (int j = 0; j < gs.length; j++) {
    GraphicsDevice gd = gs[j];
    GraphicsConfiguration[] gc = gd.getConfigurations();
    for (int i=0; i < gc.length; i++) {
        Rectangle gcBounds = gc[i].getBounds();

        Point loc = mainWindow.getLocationOnScreen();
        if (gcBounds.contains(loc)) {
            System.out.println("at " + j + " screen");

            int x = gcBounds.x + (gcBounds.width - mainWindow.getWidth()) / 2;
            int y = gcBounds.y + (gcBounds.height - mainWindow.getHeight()) / 2;
            mainWindow.setLocation(x, y);

            int x = loc.getX() + (mainWindow.getWidth() - getWidth()) / 2;
            int y = loc.getY() + (mainWindow.getHeight() - getHeight()) / 2;
            setLocation(x, y);

            break;
        }
    }
}