模态JDialog的最佳位置以避免卡死 [英] Optimal location for a modal JDialog to avoid stuck

查看:55
本文介绍了模态JDialog的最佳位置以避免卡死的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的Swing应用程序必须向用户显示一个模式对话框.抱歉,您未发布SSCCE.

My Swing application has to show a modal dialog to the user. Sorry for not posting SSCCE.

topContainer可能是JFrameJApplet.

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);
     }
}

我在网络事件中像这样启动对话框

I start the dialog like this on network event

SwingUtilities.invokeLater(new Runnable() {
     @Override
     public void run() {
         NewGameDialog dialog = new NewGameDialog();
         dialog.setVisible(true);
     }
});

问题是为对话框设置最佳位置.

The problem is to set optimal location for my dialog.

1)如果将其设置为绝对值,并且我将应用程序框架移至第二个屏幕,则在第一个屏幕上显示对话框,这很奇怪.

1) If it is set as absolute value, and I move the app frame to the second screen, then dialog is shown on the first screen which is weird.

2)如果为JFrame设置了相对值,则可能是用户将应用程序框架移到了屏幕外部,并且相对位置的对话框对用户不可见.而且由于它是模态的,所以游戏会停滞不前.

2) If it is set a relative value to JFrame, it might appear that user moved the app frame outside of the screen and the dialog being relatively located would not be visible to the user. And because it is modal, the game would be stuck.

考虑到上述两个问题的最佳解决方案是什么?

推荐答案

这使我想起了我最喜欢的帖子,使用

This reminded me of a very favourite post of mine, using Window.setLocationByPlatform(true), on StackOverflow.

如何最佳定位Swing GUI

您可以在JDialog中添加FocusListener,并在focusGained(...)方法上,对于JFrameJDialog都可以使用setLocationRelativeTo(null),这样它们都可以到达JDialog的中心.屏幕,无论他们身在何处.

You can add a FocusListener to your JDialog and on focusGained(...) method, you can use setLocationRelativeTo(null) for both the JFrame and the JDialog, so that they both come to the center of the screen no matter where they are before.

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
                 */
            }
        });
    }
}

我到处搜索了一下,结果我认为,应用程序初次出现在哪个Monitor Screen上,将确定它是

I searched a bit here and there, and it turns out, in my opinion, that actually on which Monitor Screen your application comes at the first instance, will determine it's GraphicsConfiguration. Though as I roamed through the API, there is only a getter method for the said GraphicsConfiguration thingy and no setter methods for the same (Still You can specify one through the constructor of any top level Window i.e. JFrame(...)/JDialog(...)).

现在,您可以使用此代码来忙个不停,该代码可用于确定要设置的适当位置,再次,我认为您可能必须使用focusGain()方法来满足您的条件2问题.看看附带的代码,尽管无需创建new JFrame/JDialog,只需观察如何获取屏幕的坐标即可(可以在focusGain()方法中添加以确定整个应用程序的位置.)

Now you can occupy your head with this code, which can be used to determine the appropriate location, that you want to set, again, you might have to use focusGain() method in my opinion, to satisfy condition 2 of your question. Have a look at the code attached, though no need to create a new JFrame/JDialog, just watch how to get coordinates for the screen (that you can add in the focusGain() method to determine the location of the whole Application.)

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++) {
        JFrame f = new
        JFrame(gs[j].getDefaultConfiguration());
        Canvas c = new Canvas(gc[i]);
        Rectangle gcBounds = gc[i].getBounds();
        int xoffs = gcBounds.x;
        int yoffs = gcBounds.y;
        f.getContentPane().add(c);
        f.setLocation((i*50)+xoffs, (i*60)+yoffs);
        f.show();
    }
}

尝试更改此内容:

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

至:

setLocationRelativeTo(mainWindow);

为了测试以上内容,我按原样使用了FrameFocus类,尽管我已将您的更改添加到了CustomDialog方法中,如修改后的CustomDialog类所示.

To test the above thingy, I used my FrameFocus Class as is, though I had added your changes to my CustomDialog method, as shown in this modified CustomDialog Class.

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
                 */
            }
        });
    }
}

这篇关于模态JDialog的最佳位置以避免卡死的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆