模态JDialog的最佳位置以避免卡死 [英] Optimal location for a modal JDialog to avoid stuck
问题描述
我的Swing应用程序必须向用户显示一个模式对话框.抱歉,您未发布SSCCE.
My Swing application has to show a modal dialog to the user. Sorry for not posting 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);
}
}
我在网络事件中像这样启动对话框
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.
您可以在JDialog
中添加FocusListener
,并在focusGained(...)
方法上,对于JFrame
和JDialog
都可以使用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
上,将确定它是 JFrame( ...)/
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屋!