我的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,则可能看起来用户将应用程序框架移动到屏幕之外,并且相对定位的对话框对用户不可见。因为它是模态的,所以游戏会被卡住。
考虑到上述两个问题,最佳解决方案是什么?
答案 0 :(得分:4)
我认为,最好将对话框置于当前屏幕中间,如here所述。
Toolkit toolkit = Toolkit.getDefaultToolkit();
Dimension screenSize = toolkit.getScreenSize();
int x = (screenSize.width - d.getWidth()) / 2;
int y = (screenSize.height - d.getHeight()) / 2;
d.setLocation(x, y);
如果它位于屏幕中央,它始终有效以及如何对用户不可见?也可以使用setLocationRelativeTo
,但您需要invoke it at the right time。
答案 1 :(得分:4)
这让我想起了我在StackOverflow上使用Window.setLocationByPlatform(true)的一个非常喜欢的帖子。
How to best position Swing GUIs
编辑1:
您可以在FocusListener
和JDialog
方法中添加focusGained(...)
,setLocationRelativeTo(null)
和{{1}可以使用JFrame
无论他们以前在哪里,他们都会到达屏幕的中心。
JDialog
编辑2:
我在这里和那里搜索了一下,在我看来,实际上你的应用程序在第一个实例上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
*/
}
});
}
}
实际上将确定它是GraphicsConfiguration。虽然当我漫游API时,只有一个getter方法用于上述Monitor Screen
东西,并且没有相同的setter方法(仍然可以通过任何顶级窗口的构造函数指定一个,即JFrame(...) / JDialog(...))。
现在,您可以使用此代码来占据您的头部,该代码可用于确定您想要设置的适当位置,在我看来,您可能必须使用GraphicsConfiguration
方法来满足条件2你的问题看一下附加的代码,虽然不需要创建focusGain()
,只是看看如何获取屏幕的坐标(可以在new JFrame/JDialog
方法中添加以确定整个应用程序的位置。)
focusGain()
编辑3:
尝试改变这一点:
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
答案 2 :(得分:4)
使用JDialog.setLocation()在期望的Point on the screen
上移动JDialog
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();
}
});
}
}
答案 3 :(得分:2)
在所有3位回答者的帮助下,我提出的代码似乎正是我所需要的。首先,JFrame
被放置在当前屏幕的中间,然后相应地JDialog
。
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;
}
}
}