📄 mazegui.java
字号:
package mazeAssignment;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JSlider;
import javax.swing.JTextField;
import javax.swing.JToggleButton;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
public class MazeGui implements ActionListener
{
//GUI constants.
public static final int MIN_Y_SIZE = 600;
public static final int MENU_PANEL_WIDTH = 260;
public static final int STATUS_PANEL_WIDTH = 70;
public static final int SLIDER_MIN = 0;
public static final int SLIDER_MAX = 100;
public static final int INSET_SIZE = 1;
private Manager manager;
private JFrame frame;
private MazeGraph mazePanel;
private Maze maze;
//General options panel
private JSlider delaySlider;
private JTextField txtMazeBreadth;
private JTextField txtMazeHeight;
private JButton btnUpdateSize;
private JToggleButton tbtnBuildColors;
//Build options panel
private ButtonGroup buildButtonGroup;
private JRadioButton[] rbtnBuildAlgorithms;
private JButton btnBuildAndPause;
private JButton btnResetAll;
//Post build options panel
private JTextField txtRemoveWalls;
private JCheckBox cboxRandomizeStartEnd;
private JButton btnPostBuild;
//Solve options panel
private ButtonGroup solveButtonGroup;
private JRadioButton[] rbtnSolveAlgorithms;
private JButton btnSolveAndPause;
private JButton btnResetSolve;
//Benchmark panel
private JLabel lblBuildTotalLabel;
private JLabel lblBuildTotal;
private JLabel lblBuildTickCountLabel;
private JLabel lblBuildTickCount;
private JLabel lblBuildTimePerTickLabel;
private JLabel lblBuildTimePerTick;
private JLabel lblSolveTotalLabel;
private JLabel lblSolveTotal;
private JLabel lblSolveTickCountLabel;
private JLabel lblSolveTickCount;
private JLabel lblSolveTimePerTickLabel;
private JLabel lblSolveTimePerTick;
//Current GUI state
private int currentGuiState;
/**
* Constructs the entire GUI.
* @param maze The maze used in the maze panel.
*/
public MazeGui(Manager manager, Maze maze)
{
//Should be run from the event thread.
if(! SwingUtilities.isEventDispatchThread())
throw new WrongThreadException("MazeGui() constructor");
this.manager = manager;
makeFrame();
insertMazePanel(maze);
currentGuiState = -1; //To force reflectStateChange() to update the gui.
reflectStateChange();
//frame.pack();
frame.setVisible(true);
}
/**
* Called from the manager to display the an error message.
*/
public void displayErrorMessage(String message, String title)
{
//Should be run from the event thread.
if(! SwingUtilities.isEventDispatchThread())
throw new WrongThreadException("MazeGui.displayErrorMessage()");
JOptionPane.showMessageDialog(frame, message, title, JOptionPane.ERROR_MESSAGE);
}
/**
* Handles the button presses.
* This function validates button presses and text field inputs.
* Other logic is in the separate functions.
*/
@Override
public void actionPerformed(ActionEvent event)
{
int state = manager.getState();
if(event.getSource() == btnUpdateSize)
{
//Should only be handled when the manager is not busy.
if(! manager.isBusy())
{
//Check if the user wants to loose any current maze data (if any)
if(state == Manager.STATE_BUILD_PAUSED || state == Manager.STATE_SOLVE_PAUSED)
{
boolean abortResize =
JOptionPane.showConfirmDialog(
frame,
"Resizing will cause the current maze to get removed, continue?",
"Erase current maze?",
JOptionPane.OK_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE) != JOptionPane.OK_OPTION;
//Abort if the user selected cancel
if(abortResize)
return;
}
try
{
int xSize = Integer.parseInt( txtMazeBreadth.getText() );
int ySize = Integer.parseInt( txtMazeHeight.getText() );
//Should 1 or larger at the very least.
if(xSize < 2 || ySize < 2)
throw new NumberFormatException();
handleResize(xSize, ySize);
}
catch(NumberFormatException e)
{
displayErrorMessage("Specify valid values in 'breadth' and 'height'.", "Invalid input");
return;
}
}
}
else if(event.getSource() == btnBuildAndPause)
{
int delay = delaySlider.getValue();
if(delay < SLIDER_MIN || SLIDER_MAX < delay)
{
displayErrorMessage("Slider value is outside of slider bounds, should not happend!!!", "Paranoia error");
return;
}
//This button has 3 functions, start, pause and unpause.
switch(state)
{
//Start
case Manager.STATE_CLEAR:
case Manager.STATE_BUILD_FINISHED:
case Manager.STATE_SOLVE_PAUSED:
case Manager.STATE_SOLVED:
{
startBuild(delay);
break;
}
//Pause
case Manager.STATE_BUILDING:
{
manager.pauseBuild();
break;
}
//Resume
case Manager.STATE_BUILD_PAUSED:
{
continueBuild(delay);
break;
}
case Manager.STATE_SOLVING:
default:
{
displayErrorMessage("Invalid state: "+state+" encountered in actionListener for btnBuildAndPause.", "Paranoia error");
return;
}
}
}
else if(event.getSource() == btnResetAll)
{
switch(state)
{
case Manager.STATE_BUILDING:
case Manager.STATE_SOLVING:
{
displayErrorMessage("An operation is in progress, cannot reset!", "Paranoia error");
return;
}
case Manager.STATE_BUILD_PAUSED:
case Manager.STATE_BUILD_FINISHED:
case Manager.STATE_SOLVE_PAUSED:
case Manager.STATE_SOLVED:
case Manager.STATE_CLEAR:
{
manager.clearAll();
return;
}
}
}
else if(event.getSource() == btnPostBuild)
{
//Validate the manager state.
if( manager.getState() != Manager.STATE_BUILD_FINISHED )
{
displayErrorMessage("This function is only available after the build stage.", "Paranoia error");
return;
}
int wallsToKnock;
boolean doRandomExit = cboxRandomizeStartEnd.isSelected();
//Validate the removewall text field.
try
{
wallsToKnock = Integer.parseInt(txtRemoveWalls.getText());
if(wallsToKnock < 0)
throw new NumberFormatException();
}
catch(NumberFormatException ne)
{
displayErrorMessage("Remove walls has to be a number of 0 or higher.", "Input error");
return;
}
//Call the function to process the request.
manager.intermediaryStep(doRandomExit, wallsToKnock);
//Update the mazePanel
mazePanel.repaint();
}
else if(event.getSource() == btnSolveAndPause)
{
int delay = delaySlider.getValue();
if(delay < SLIDER_MIN || SLIDER_MAX < delay)
{
displayErrorMessage("Slider value is outside of slider bounds, should not happend!!!", "Paranoia error");
return;
}
//This button has 3 functions, start, pause and unpause.
switch(state)
{
//Start
case Manager.STATE_BUILD_FINISHED:
case Manager.STATE_SOLVED:
{
startSolve(delay);
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -