我有点新手。为了学习正确使用API,我正在设计以下项目: 该项目是一个解决块拼图解算器滑块拼图,类似于玩具店常见的高峰时段拼图 - https://en.wikipedia.org/wiki/Rush_Hour_(board_game)除了没有特殊车的逃生。
通过将块从板外区域拖到板上,用户指定拼图的起始配置。用户以相同的方式指定一个结束目标配置,该配置指示用户最初指定的一些(或所有)块必须位于拼图结尾的位置 - 结束配置可以仅使用一些块来指定,制作多种合法的结局配置。
解决难题的算法已经完成 - 我只需要设计界面,我就会陷入困境。为了设计托盘,我使用了网格布局。由于需要在某些位置输入块,我需要能够将块放在网格中的特定单元格中并移动它们。
'block'对象有四个属性 - 它的高度,宽度,顶行和最左边的列(即 - 每个块的左上角都有一个地址)。
我在这里使用了建议(https://stackoverflow.com/questions/2510159/can-i-add-a-component-to-a-specific-grid-cell-when-a-gridlayout-is-used)作为网格布局。
现在我只编程到java从.txt文件中读取拼图的位置,并且应该在屏幕上显示它(我还没有设计任何用户交互性)。
首先,这是我到目前为止编写的代码。
public class SolverPuzzleGUI extends JFrame {
//Specs from the puzzle.
Board initBoard;
ArrayList<Block> goalBlocks;
LinkedList<Move> moveList;
JLayeredPane layeredpane;
JPanel Board;
Dimension boardsize = new Dimension(400, 500);
JPanel[][] panelHolder = new JPanel[5][4];
public SolverPuzzleGUI(Board startBoard, ArrayList<Block> startGoalBlocks,
LinkedList<Move> startMoveList) {
this.initBoard = startBoard;
this.goalBlocks = startGoalBlocks;
this.moveList = startMoveList;
} // end constructor.
//gives the actual simulation
public void runSimulation() {
// Initalizing the main window.
setSize(500, 600);
setName("Solution");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setMinimumSize(getMinimumSize());
//Using layered pane
layeredpane = new JLayeredPane();
add(layeredpane);
layeredpane.setPreferredSize(boardsize);
layeredpane.setBackground(Color.YELLOW);
layeredpane.setVisible(true);
// adding the game tray
Board = new JPanel();
layeredpane.add(Board, JLayeredPane.DEFAULT_LAYER);
Board.setLayout(new GridLayout(5, 4));
// centering the game tray.
Board.setPreferredSize(boardsize);
Board.setMinimumSize(boardsize);
Board.setMaximumSize(boardsize);
Box box = new Box(BoxLayout.Y_AXIS);
box.add(Box.createVerticalGlue());
box.add(Board);
box.add(Box.createVerticalGlue());
add(box);
//Adding placeholders to the board for creating blocks
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 4; j++) {
panelHolder[i][j] = new JPanel();
panelHolder[i][j].setBackground(Color.DARK_GRAY);
Board.add(panelHolder[i][j]);
layeredpane.setLayer(panelHolder[i][j], JLayeredPane.DEFAULT_LAYER);
panelHolder[i][j].setVisible(false);
} // end 'j' for
} // end 'i' for
ArrayList<Block> initBlocks = initBoard.getBlocks();
//int count = 0; //DEBUG
for (Block block : initBlocks) {
this.drawBlock(block);
//count++;
//if(count > 4) { break; }
} // end 'for'
Board.setBackground(Color.DARK_GRAY);
Board.setVisible(true);
setVisible(true);
} // end 'run'
private void drawBlock(Block block) {
Dimension blockSize = new Dimension(block.getWidth()*100, block.getHeight()*100);
System.out.println(blockSize.width);
System.out.println(blockSize.height);
JPanel screenBlock = new JPanel();
screenBlock.setPreferredSize(blockSize);
screenBlock.setMinimumSize(blockSize);
screenBlock.setMaximumSize(blockSize);
screenBlock.setSize(blockSize);
screenBlock.setBackground(Color.BLUE);
screenBlock.setBorder(BorderFactory.createLineBorder(Color.BLACK));
layeredpane.setLayer(screenBlock, JLayeredPane.MODAL_LAYER);
int leftRow = block.getRow();
int leftCol = block.getColumn();
panelHolder[leftRow][leftCol].setSize(blockSize);
panelHolder[leftRow][leftCol].setVisible(true);
panelHolder[leftRow][leftCol].add(screenBlock);
layeredpane.setLayer(panelHolder[leftRow][leftCol], JLayeredPane.MODAL_LAYER);
screenBlock.setVisible(true);
}// end 'drawBlock'
public static void main(String[] args) {
String file = "C:\\Users\\Tim\\Desktop\\init.from.handout.txt";
String goal = "C:\\Users\\Tim\\Desktop\\goal.2.from.handout.txt";
/*
A SolverPuzzle object is the object which actually solves the algorithm -
when the class is constructed, it takes the file path of the inital
configuration as an input, as well as the file path of the goal
configuration. It has the following fields:
A 'board' object which specifies the inital configuration of the board.
It contains an ArrayList of Block objects(Remember block objects store
the height and width of the block, as well as the address of the
top left corner of block) which specify the starting
blocks, an ArrayList of EmptySpace objects which specify the empty
spaces on the board, an ArrayList of Move objects, which contain
the legal moves of the configuration, and the height and width of
the tray (in this application, the tray will always be 5 x 4).
An ArrayList of Block objects which specify the ending configuration.
A LinkedList of Move objects which specify the shortest possible
list of Moves which brings the configuration to a position which
satisfies the goal position. A Move object has three fields -
The block object being moved, and the row and column of the
top left corner of the block in the new position.
*/
SolverPuzzle test;
try { test = new SolverPuzzle(file, goal); }
catch (IOException ex) {
System.out.println("IOException");
return;
}
Board testBoard = test.getStartBoard();
ArrayList<Block> testGoalBlocks = test.getGoalBlocks();
LinkedList<Move> testMoveSolution = test.getMoveList();
// testing the gui
SolverPuzzleGUI testGUI = new SolverPuzzleGUI(testBoard, testGoalBlocks,
testMoveSolution);
testGUI.runSimulation();
}
} // end class 'SolverPuzzleGUI'
这是当前输出与所需输出的对比。
具体来说,我有两个问题:
1 - 为什么图像只显示块的左上角而不是整个块?
2 - 继续使用GridLayout或切换到GridBagLayout更好吗?
由于
答案 0 :(得分:1)
GridBagLayout
肯定适合你想做的事。例如,您可以扩展组件以包含多个列或行 - 就像您想要做的那样。查看java tutorials了解如何使用它们。
使用GridBagLayout
时要记住的一个要点是,您需要在每个组件后重置Constraints
,假设它们对于该特定组件是唯一的。
另外 - 我只能通过显示左上角来辨别你的意思 - 它看起来像它向我展示整个事物......