我正在创建数独游戏,我想知道当我在用户请求新的数独板时创建 JDialog 对象时,是否有一种方法可以删除(或使不可见)父窗口。当我使用 JDialog 对象(通过我的内部类 Dialog1 和 Dialog2)创建新板时,所有 JDialog 对象都堆叠在一起。具体来说,在 Dialog2 类中,我希望包含上一个游戏的基础窗口在按下“设置给定”按钮时消失。
如果您想直观地观察我所描述的问题,我将发布单独的类,但实际上只有第一类应该与问题相关(SudokuMain)。
编辑
没关系,显然我可以在这里输入的字符是有限的。好吧,这里是 SudokuMain,删除了不相关的代码部分:
// Allow short name access to following classes
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
public class SudokuMain extends JComponent {
/**
* The application method.
*
* @param args The command-line arguments.
*/
public static void main(String[] args) {
new SudokuMain();
}
// this field refers to the SudokuBase class to access information
// of the board.
private SudokuBase board;
// this field refers to SudokuView object to access its information
// and provide output
private SudokuView view;
// the window all the components are contained in
private JFrame win;
// center JPanel object in window
private JPanel center;
// left JPanel object in window
private JPanel west;
// right JPanel object in window
private JPanel east;
// JPanel object to hold graphic "buttons"
private JPanel symbols;
// the first set-up window (cannot be changed once
// instantiated)
private final Dialog1 setWin1;
/**
* Constructs SudokuMain object.
*/
public SudokuMain() {
// start game
board = makeBoard();
view = new SudokuView(board);
win = new JFrame("Sudoku Game");
center = new JPanel();
west = new JPanel();
east = new JPanel();
// graphic "buttons" for current Sudoku board
symbols = new SetSymbols(view);
// the first set-up window
setWin1 = new Dialog1(this, "New Game", true);
// create menu bar
final MenuAtTop menuBar = new MenuAtTop(this);
win.setJMenuBar(menuBar);
// display game mode
JLabel mode = new JLabel("Normal Play Mode");
mode.setHorizontalAlignment(JLabel.CENTER);
Font modeFont = new Font("Arial", Font.BOLD, 14);
mode.setFont(modeFont);
// set selected cell at (0, 0)
view.setSelected(0, 0);
win.setLayout(new BorderLayout());
west.setLayout(new BorderLayout());
east.setLayout(new BorderLayout());
center.setLayout(new FlowLayout());
west.add(symbols);
east.add(view, BorderLayout.CENTER);
center.add(west);
center.add(east);
win.add(center, BorderLayout.CENTER);
win.add(mode, BorderLayout.SOUTH);
win.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
win.pack();
win.setVisible(true);
}
// this inner class constructs graphic "buttons" to set desired
// cells of board
class SudokuControlButton extends JPanel {
// row of selected cell
private int selRow;
// column of selected cell
private int selCol;
// the value that corresponds with the desired symbol
private int value;
/**
* Constructs SudokuControlButton object; the graphic "button"
* to control the board.
*
* @param view The SudokuView object to be controlled.
* @param v The value that corresponds to the desired symbol.
*/
public SudokuControlButton(final SudokuView view, int v) {
// set characteristics of graphic "button"
setPreferredSize(new Dimension(50, 50));
setBackground(Color.LIGHT_GRAY);
value = v;
addMouseListener(new MouseListener() {
/**
* This method selects a "button" and puts it in focus when the mouse
* is clicked on it.
*
* @param event Captures information on the mouse button being
* clicked (pressed and released) on a component.
*/
public void mouseClicked(MouseEvent e) {
selRow = view.getSelectedRow();
selCol = view.getSelectedColumn();
if(!board.isGiven(selRow, selCol)) {
board.setValue(selRow, selCol, value);
view.new SudokuCell(selRow, selCol, board);
// set to "highlighted" color
setBackground(Color.WHITE);
view.repaint();
}
else { // have system beep sound
getToolkit().beep();
}
repaint();
}
/**
* This method handles behavior when the mouse enters a graphic
* "button".
*
* @param event Captures information on the mouse button being
* entered over a component.
*/
public void mouseEntered(MouseEvent e){
// set to "highlighted" color
setBackground(Color.WHITE);
repaint();
}
/**
* This method handles behavior when the mouse exits a graphic
* "button".
*
* @param event Captures information on the mouse button being
* exited from a component.
*/
public void mouseExited(MouseEvent e){
// set to default color
SudokuControlButton button = (SudokuControlButton) e.getSource();
setBackground(Color.LIGHT_GRAY);
repaint();
}
/**
* This method handles behavior when the mouse is pressed on a
* graphic "button".
*
* @param event Captures information on the mouse button being
* pressed on a component.
*/
public void mousePressed(MouseEvent e){
// set to "active" color
setBackground(Color.YELLOW);
repaint();
}
/**
* This method handles behavior when the mouse is released on a
* graphic "button".
*
* @param e Captures information on the mouse button being
* released on a component.
*/
public void mouseReleased(MouseEvent e){
}
});
}
/**
* This method draws the graphic "button" associated with
* each numeric value, 0 to 12.
*
* @param g The drawing mechanism.
*/
public void paintComponent(Graphics g) {
super.paintComponent(g);
switch(value) {
case 0:
drawSymbol(g, 0);
break;
case 1:
drawSymbol(g, 1);
break;
case 2:
drawSymbol(g, 2);
break;
case 3:
drawSymbol(g, 3);
break;
case 4:
drawSymbol(g, 4);
break;
case 5:
drawSymbol(g, 5);
break;
case 6:
drawSymbol(g, 6);
break;
case 7:
drawSymbol(g, 7);
break;
case 8:
drawSymbol(g, 8);
break;
case 9:
drawSymbol(g, 9);
break;
case 10:
drawSymbol(g, 10);
break;
case 11:
drawSymbol(g, 11);
break;
case 12:
drawSymbol(g, 12);
break;
}
}
/**
* This method draws the symbol that corresponds with
* the specified value (0-12).
*
* @param g The drawing mechanism.
* @param value The specified value.
*/
public void drawSymbol(Graphics g, int value) {
if(value < 0 || value > 12) {
String msg = "Value cannot be less than 0 or greater than 12.";
throw new IllegalArgumentException(msg);
}
// enable drawing with "thick" lines
Graphics2D g2 = (Graphics2D) g;
g2.setStroke(new BasicStroke(3));
switch(value) {
case 0:
// draw borders
g.drawRect(0, 0, 50, 50);
break;
case 1:
// draw borders
g.drawRect(0, 0, 50, 50);
// draw symbol
g2.drawLine(5, 5, 5, 45);
break;
case 2:
// draw borders
g.drawRect(0, 0, 50, 50);
// draw symbol
g2.drawLine(5, 5, 5, 45);
g2.drawLine(10, 5, 10, 45);
break;
case 3:
// draw borders
g.drawRect(0, 0, 50, 50);
// draw symbol
g2.drawLine(5, 5, 5, 45);
g2.drawLine(10, 5, 10, 45);
g2.drawLine(15, 5, 15, 45);
break;
case 4:
// draw borders
g.drawRect(0, 0, 50, 50);
// draw symbol
g2.drawLine(5, 5, 5, 45);
g2.drawLine(10, 5, 10, 45);
g2.drawLine(15, 5, 15, 45);
g2.drawLine(20, 5, 20, 45);
break;
case 5:
// draw borders
g.drawRect(0, 0, 50, 50);
// draw symbol
g2.drawLine(5, 5, 5, 45);
g2.drawLine(10, 5, 10, 45);
g2.drawLine(15, 5, 15, 45);
g2.drawLine(20, 5, 20, 45);
g2.drawLine(25, 5, 25, 45);
break;
case 6:
// draw borders
g.drawRect(0, 0, 50, 50);
// draw symbol
g2.drawLine(5, 5, 5, 45);
g2.drawLine(10, 5, 10, 45);
g2.drawLine(15, 5, 15, 45);
g2.drawLine(20, 5, 20, 45);
g2.drawLine(25, 5, 25, 45);
g2.drawLine(30, 5, 30, 45);
break;
case 7:
// draw borders
g.drawRect(0, 0, 50, 50);
// draw symbol
g2.drawLine(5, 5, 5, 20);
g2.drawLine(10, 5, 10, 20);
g2.drawLine(15, 5, 15, 20);
g2.drawLine(20, 5, 20, 20);
g2.drawLine(25, 5, 25, 20);
g2.drawLine(30, 5, 30, 20);
g2.drawLine(5, 30, 5, 45);
break;
case 8:
// draw borders
g.drawRect(0, 0, 50, 50);
// draw symbol
g2.drawLine(5, 5, 5, 20);
g2.drawLine(10, 5, 10, 20);
g2.drawLine(15, 5, 15, 20);
g2.drawLine(20, 5, 20, 20);
g2.drawLine(25, 5, 25, 20);
g2.drawLine(30, 5, 30, 20);
g2.drawLine(5, 30, 5, 45);
g2.drawLine(10, 30, 10, 45);
break;
case 9:
// draw borders
g.drawRect(0, 0, 50, 50);
// draw symbol
g2.drawLine(5, 5, 5, 20);
g2.drawLine(10, 5, 10, 20);
g2.drawLine(15, 5, 15, 20);
g2.drawLine(20, 5, 20, 20);
g2.drawLine(25, 5, 25, 20);
g2.drawLine(30, 5, 30, 20);
g2.drawLine(5, 30, 5, 45);
g2.drawLine(10, 30, 10, 45);
g2.drawLine(15, 30, 15, 45);
break;
case 10:
// draw borders
g.drawRect(0, 0, 50, 50);
// draw symbol
g.drawLine(5, 5, 5, 20);
g.drawLine(10, 5, 10, 20);
g.drawLine(15, 5, 15, 20);
g.drawLine(20, 5, 20, 20);
g.drawLine(25, 5, 25, 20);
g.drawLine(30, 5, 30, 20);
g.drawLine(5, 30, 5, 45);
g.drawLine(10, 30, 10, 45);
g.drawLine(15, 30, 15, 45);
g.drawLine(20, 30, 20, 45);
break;
case 11:
// draw borders
g.drawRect(0, 0, 50, 50);
// draw symbol
g.drawLine(5, 5, 5, 20);
g.drawLine(10, 5, 10, 20);
g.drawLine(15, 5, 15, 20);
g.drawLine(20, 5, 20, 20);
g.drawLine(25, 5, 25, 20);
g.drawLine(30, 5, 30, 20);
g.drawLine(5, 30, 5, 45);
g.drawLine(10, 30, 10, 45);
g.drawLine(15, 30, 15, 45);
g.drawLine(20, 30, 20, 45);
g.drawLine(25, 30, 25, 45);
break;
case 12:
// draw borders
g.drawRect(0, 0, 50, 50);
// draw symbol
g.drawLine(5, 5, 5, 20);
g.drawLine(10, 5, 10, 20);
g.drawLine(15, 5, 15, 20);
g.drawLine(20, 5, 20, 20);
g.drawLine(25, 5, 25, 20);
g.drawLine(30, 5, 30, 20);
g.drawLine(5, 30, 5, 45);
g.drawLine(10, 30, 10, 45);
g.drawLine(15, 30, 15, 45);
g.drawLine(20, 30, 20, 45);
g.drawLine(25, 30, 25, 45);
g.drawLine(30, 30, 30, 45);
break;
}
}
}
// this inner class provides a JMenuBar object at the top of
// the board
class MenuAtTop extends JMenuBar implements ActionListener{
// SudokuMain object we are dealing with
private SudokuMain main;
// the "File" menu
private JMenu fileMenu;
// the "New Game" option in the "File" menu
private JMenuItem newGame;
// JDialog object to create a dialog box to prompt
// user for new game information
private JDialog createNewWin;
/**
* Constructs MenuAtTop object.
*
* @param m The SudokuMain object to be referred to.
*/
public MenuAtTop(final SudokuMain m) {
main = m;
// instantiate and bind to reference
fileMenu = new JMenu("File");
add(fileMenu);
// instantiate and bind to reference
newGame = new JMenuItem("New Game");
newGame.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N,
ActionEvent.CTRL_MASK));
fileMenu.add(newGame);
// add action listener to "newGame" option
newGame.addActionListener(this);
}
/**
* This method handles the action of activating the "New Game"
* option.
*
* @param e Captures information about the event that occurred.
*/
public void actionPerformed(ActionEvent e) {
setEnabled(false);
// create dialog box prompting for the new board information
createNewWin = new Dialog1(main, "Create New Board", true);
// make it visible
createNewWin.setVisible(true);
}
}
// this inner class provides a dialog box to prompt the user
// for new board information
class Dialog1 extends JDialog {
// rows for new game
private JTextField rows;
// cols for new game
private JTextField cols;
// button to create a new board
private JButton createBoard;
// button to cancel new board and return to
// previous game
private JButton cancel;
// labels for rows per region
private JLabel rowLabel;
// label for columns per region
private JLabel colLabel;
// label dislayed when error occurs
private JLabel errorMes;
// JPanel object to house error message
private JPanel center;
// JPanel object to house rows and columns prompt
private JPanel north;
// JPanel object to house create new board and cancel buttons
private JPanel south;
// JDialog object to create window for new game
private JDialog createWin2;
/**
* Constructs Dialog1 object.
*
* @param win The window containing the dialog box.
* @param header The title of the dialog box.
* @param modal Whether dialog box is modal or not.
*/
public Dialog1(final SudokuMain win, String header, boolean modal) {
// call superclass constructor
super();
// instantiate and bind to references
rows = new JTextField(2);
cols = new JTextField(2);
createBoard = new JButton("Create New Board");
cancel = new JButton("Cancel");
rowLabel = new JLabel("Rows per region: ");
colLabel = new JLabel("Columns per region: ");
errorMes = new JLabel();
north = new JPanel(new FlowLayout());
center = new JPanel(new FlowLayout());
south = new JPanel(new FlowLayout());
// set characteristics
setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
setTitle(header);
setModal(modal);
setLayout(new BorderLayout());
// set characteristics of error message
errorMes.setForeground(Color.RED);
errorMes.setFont(new Font("Arial", Font.ITALIC, 12));
errorMes.setVisible(false);
// keep track of "old" board
final SudokuBase oldBoard = board;
// add action listener for "Cancel" button
cancel.addActionListener(new ActionListener() {
/**
* This method handles the action of activating the
* "Cancel" button to make the dialog box "invisible".
*
* @param e Captures information about the event that occurred.
*/
public void actionPerformed(ActionEvent e) {
setVisible(false);
}
});
// add action listener for "Create Board" button
createBoard.addActionListener(new ActionListener() {
/**
* This method handles the action of activating the
* "Cancel" button to make the dialog box "invisible".
*
* @param e Captures information about the event that occurred.
*/
public void actionPerformed(ActionEvent e) {
int newRows;
int newCols;
int newSize;
// handles potential exception when converting String input
// to int
try{
newRows = Integer.parseInt(rows.getText());
newCols = Integer.parseInt(cols.getText());
} catch (NumberFormatException exc) {
newRows = 0;
newCols = 0;
}
newSize = newRows * newCols;
// input validation
if(newSize <= 0 || newSize > 12) {
errorMes.setText("Rows times columns cannot be less than one" +
" or greater than 12!");
errorMes.setVisible(true);
pack();
} else {
errorMes.setVisible(false);
setVisible(false);
// update board to new board
board = new SudokuBoard(newRows, newCols);
createWin2 = new Dialog2(win, oldBoard, view, symbols, newRows,
newCols, "New Sudoku Game", true);
}
}});
// place error message in the center
center.add(errorMes);
// place labels for rows and columns at the top
north.add(rowLabel);
north.add(rows);
north.add(colLabel);
north.add(cols);
// place both buttons at bottom
south.add(createBoard);
south.add(cancel);
add(center, BorderLayout.CENTER);
add(north, BorderLayout.NORTH);
add(south, BorderLayout.SOUTH);
pack();
if(!win.win.isVisible()) {
dispose();
}
}
}
// this inner class a dialog box to house a new game
class Dialog2 extends JDialog {
// view to be used
private SudokuView view;
// the panel to house the board (view) and both the
// "Set givens" and "Cancel" buttons
private JPanel panel;
// panel placed within "panel" that houses both the "Set givens"
// and "Cancel" buttons
private JPanel northPanel;
// panel to house the graphic "buttons"
private JPanel symbols;
// "Set givens" button
private JButton setGivenCells;
// "Cancel" button
private JButton cancel;
/**
* Constructs Dialog2 object.
*
* @param win The window containing the dialog box.
* @param oldBoard The "old" SudokuBoard to keep track of.
* @param oldView The "old" SudokuView to keep track of.
* @param oldSymbols The "old" graphic "buttons" to keep track of.
* @param rows The rows of the new Sudoku board to be created.
* @param cols The columns of the new Sudoku board to be created.
* @param header The title of the dialog box.
* @param modal Whether the dialog box is modal or not.
*/
public Dialog2(final SudokuMain mainWin, final SudokuBase oldBoard,
final SudokuView oldView, final JPanel oldSymbols,
int rows, int cols, String header, boolean modal) {
// call superclass constructor
super();
// instantiate and bind to references
view = new SudokuView(board);
panel = new JPanel();
northPanel = new JPanel();
setGivenCells = new JButton("Set givens");
cancel = new JButton("Cancel");
symbols = new SetSymbols(view);
// create menu bar
final MenuAtTop menuBar = new MenuAtTop(mainWin);
setJMenuBar(menuBar);
// display "Set-Up Mode"
final JLabel setupMode = new JLabel("Set-Up Mode");
setupMode.setHorizontalAlignment(JLabel.CENTER);
Font setupModeFont = new Font("Comic Sans MS", Font.BOLD, 18);
setupMode.setFont(setupModeFont);
setupMode.setForeground(Color.RED);
// display "Normal Play Mode"
final JLabel mode = new JLabel("Normal Play Mode");
mode.setHorizontalAlignment(JLabel.CENTER);
Font modeFont = new Font("Arial", Font.BOLD, 14);
mode.setFont(modeFont);
// set up characteristics
setTitle(header);
setModal(modal);
setLayout(new FlowLayout());
panel.setLayout(new BorderLayout());
northPanel.setLayout(new FlowLayout());
// add action listener to "Set givens" button
setGivenCells.addActionListener(new ActionListener() {
/**
* This method handles the action of activating the
* "Set givens" button.
*
* @param e Captures information about the event that occurred.
*/
public void actionPerformed(ActionEvent e) {
// set "given" cells
board.fixGivens();
// remove "Set-Up Mode" label and replace with
// "Normal Play Mode" label
panel.remove(setupMode);
panel.add(mode, BorderLayout.SOUTH);
// disable both buttons
setGivenCells.setEnabled(false);
cancel.setEnabled(false);
validate();
repaint();
}
});
// add action listener to "Cancel" button
cancel.addActionListener(new ActionListener() {
/**
* This method handles the action of activating the
* "Cancel" button.
*
* @param e Captures information about the event that occurred.
*/
public void actionPerformed(ActionEvent e) {
// have window refer to "old" board
board = oldBoard;
mainWin.west.remove(mainWin.symbols);
mainWin.east.remove(mainWin.view);
mainWin.view = oldView;
mainWin.symbols = oldSymbols;
mainWin.west.add(mainWin.symbols);
mainWin.east.add(mainWin.view);
// disable both buttons
setGivenCells.setEnabled(false);
cancel.setEnabled(false);
setVisible(false);
repaint();
}
});
// place buttons at the top
northPanel.add(setGivenCells);
northPanel.add(cancel);
// place board to fill remainder of space not
// occupied by buttons at the top
panel.add(view, BorderLayout.CENTER);
panel.add(northPanel, BorderLayout.NORTH);
panel.add(setupMode, BorderLayout.SOUTH);
// place graphic "buttons" to left of board
add(symbols);
add(panel);
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
pack();
setVisible(true);
}
}
// this inner class creates the graphic "buttons" to set the selected cell
// to the desired "button"
class SetSymbols extends JPanel {
// temporary board provides information to create graphic "buttons"
private SudokuBoard tempBd;
private int value;
/**
* Constructs SetSymbols object.
*
* @param view The SudokuView object for SetSymbols.
*/
public SetSymbols(final SudokuView view) {
// instantiate and bind to reference
tempBd = new SudokuBoard(1, board.getBoardSize() + 1);
setLayout(new GridLayout((tempBd.getBoardSize())/2 + 1, 2));
for(int colSymbol = 0; colSymbol < tempBd.getBoardSize(); colSymbol++) {
// keep track of value of graphic "button"
value = colSymbol;
final JPanel symPanel = new JPanel();
// set value for each graphic "button"
tempBd.setValue(0, colSymbol, colSymbol);
// add the appropriate symbol to each graphic "button"
symPanel.add(new SudokuControlButton(view, value));
// add graphic "button"
add(symPanel);
}
}
}
}