问题描述
我正在用一块板制作战舰游戏。下图显示了电路板 GUI 的外观。我当前的代码设置了一个没有“菜单层”的板。 (见图) 我尝试使用 Intellij 中的 Swing GUI 设计器执行此操作并获得以下表单(参见图片),但找不到将这些按钮插入面板内的方法。目前,我有以下代码。
package BattleshipGUI;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class BoardFrame extends JFrame {
//variables
Ships ship = new Ships();
static final Color colorHit = Color.red;
static final Color colornormal = Color.gray;
static final Color colorWater = Color.blue;
static final Color colorCarrier = Color.yellow;
static final Color colorBattleship = Color.BLACK;
static final Color colorSubmarine = Color.magenta;
static final Color colorDestroyer = Color.white;
int[][] map;
private Container contents;
int cols;
int rows;
boolean equalPoints;
Player p1 = new Player();
Player p2 = new Player();
private JPanel mainPanel; // I tried using the GUI swing designer,but I cant manage to create
//a menu-layer on top of the buttons
private JButton buttonHighscores;
private JButton quitGame;
private JLabel player1Points;
private JLabel player2Points;
private JLabel playerTurn;
JButton[][] tiles = new JButton[100][100]; // I create 100*100 buttons,but only assign the right
// number to them
public void setMap(int[][] map) {
this.map = map;
}
public void SetFrame(int r,int c) {
this.rows = r;
this.cols = c;
}
public BoardFrame(int r,int c) {
super("Battleship");
setSize(400,450); // I create a frame
this.setLayout(new GridLayout(r,c)); // I set the layout depending on the number of rows and
//columns
AttackHandler attackHandler = new AttackHandler(); // action event class
p1.turn = true; // player 1's turn is true,he commences
p2.turn= false; //player 2's turn is false
for (int i =0; i<r; i++) {
for (int j =0; j <c; j++) {
tiles[i][j] = new JButton(); // this is where all the buttons are declared
tiles[i][j].setBackground(colornormal);
add(tiles[i][j]);
tiles[i][j].addActionListener(attackHandler);
}
}
setResizable(true);
setLocationRelativeto(null);
setVisible(true);
setDefaultCloSEOperation(this.disPOSE_ON_CLOSE);
setSize(400,450); //the size of my frame
}
public class AttackHandler implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
Object source = e.getSource();
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (source == tiles[i][j]) {
isHit(i,j);
return;
}
}
}
}
}
public void isHit(int row,int col) {
// the map consists of an 2D array
//where 0's represent the water,1's represent the tiles that are
//already hit,and the other represent the ships
if (AllHit()) {
JOptionPane.showMessageDialog(null,"All Ships Destructed!");
setWinner();
String winner =DecideWinner();
JOptionPane.showMessageDialog(null,winner+" has won!","Winner",JOptionPane.PLAIN_MESSAGE);
int again = JOptionPane.showConfirmDialog(null,"Play Again","Play
Again",JOptionPane.YES_NO_OPTION);
if (again==0){
Main.main(null);
}
dispose();
}
else if (map[row][col] == 5) {
AddPoint(p1.turn,5); // this should add points to the player that
//has the turn
tiles[row][col].setBackground(colorCarrier);
map[row][col] = 1;
} else if (map[row][col] == 4) {
AddPoint(p1.turn,4);
tiles[row][col].setBackground(colorBattleship);
map[row][col] = 1;
} else if (map[row][col] == 3) {
AddPoint(p1.turn,3);
tiles[row][col].setBackground(colorSubmarine);
map[row][col] = 1;
} else if (map[row][col] == 2) {
AddPoint(p1.turn,2);
tiles[row][col].setBackground(colorDestroyer);
map[row][col] = 1;
} else if (map[row][col] == 1) {
System.out.println("Already Hit!");
} else if (map[row][col] == 0 || map[row][col] == 9) {
tiles[row][col].setBackground(colorWater);
map[row][col] = 1;
}
p1.changeTurn(p1.turn); // every click,the turn of each player should
//switch from true to false,p1 starts with value
//true,and p2 with false
p2.changeTurn(p2.turn);
System.out.println("Points Player 1: "+p1.points);
System.out.println("Points Player 2: "+p2.points);
}
public boolean AllHit() { // if all ships are hit,a message pops up
boolean allHit = true;
for (int i = 0; i<rows;i++) {
for (int j = 0; j < cols; j++) {
if (map[i][j] != 1 && map[i][j] != 0) {
allHit = false;
break;
}
}
}
return allHit;
}
public void AddRandomShips(int rows,int cols) {
int[][] map = ship.setRandomShips(rows,cols);
setMap(map);
}
public void AddShipsNotRandom(int size,int[][] coordinates){
int[][] map = ship.PlaceShips(size,coordinates);
setMap(map);
}
public void scoreMethod(boolean scoreMethod){
if(scoreMethod){
equalPoints = true;
}
else if(!scoreMethod){ // the second method adjusts the score
//for the second player because the first player
//is more likely to hit a ship
equalPoints = false;
}
}
public void AddPoint(boolean turn,int amount){
if (turn){
p1.points = p1.points+ amount;
}
else p2.points = p2.points+amount;
}
public void setWinner(){
if(p1.points>p2.points){
p1.setWon();
}
else p2.setWon();
}
public String DecideWinner(){
if (p1.won == true){
return "Player 1";
}
else return "Player 2";
}
}
GUI 应该是这样的:
这是我使用 Intellij 的 Swing Designer 设计的(带有“按钮”的面板应该填充我在代码中创建的 JButton
):
更新:
感谢先生。 Kroukamp,我能够添加菜单覆盖。代码如下所示:
package BattleshipGUI;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.LineBorder;
import java.awt.Dimension;
public class BoardFrame extends JFrame {
//variables
Ships ship = new Ships();
static final Color colornormal = Color.gray;
static final Color colorWater = Color.blue;
static final Color colorCarrier = Color.yellow;
static final Color colorBattleship = Color.BLACK;
static final Color colorSubmarine = Color.magenta;
static final Color colorDestroyer = Color.white;
int[][] map;
int cols;
int rows;
boolean equalPoints;
Player p1 = new Player();
Player p2 = new Player();
JButton[][] tiles = new JButton[100][100];
public void setMap(int[][] map) {
this.map = map;
}
public void SetFrame(int r,int c) {
this.rows = r;
this.cols = c;
}
JButton highscoresButton = new JButton("High scores");
JLabel player1scoreTitleLabel = new JLabel(String.valueOf(p1.points));
JLabel turnTitleLabel = new JLabel(Turn());
JLabel player2scoreTitleLabel = new JLabel(String.valueOf(p1.points));
JButton quitGameButton = new JButton("Quite Game");
JFrame frame = new JFrame("Battleship");
public BoardFrame(int r,int c) {
super("Battleship");
AttackHandler attackHandler = new AttackHandler(); // action event class
p1.turn = true; // player 1's turn is true,he commences
p2.turn= false; //player 2's turn is false
JFrame frame = new JFrame("Battleship");
frame.setDefaultCloSEOperation(JFrame.EXIT_ON_CLOSE);
// panel 1 (yellow border)
JPanel panel1 = new JPanel(new GridBagLayout());
JButton highscoresButton = new JButton("High scores");
JLabel player1scoreTitleLabel = new JLabel(String.valueOf(p1.points));
JLabel turnTitleLabel = new JLabel(Turn());
JLabel player2scoreTitleLabel = new JLabel(String.valueOf(p1.points));
JButton quitGameButton = new JButton("Quite Game");
GridBagConstraints s = new GridBagConstraints();
s.weightx = 1;
s.gridx = 0;
s.gridy = 0;
panel1.add(highscoresButton,s);
s.weightx = 1;
s.gridx = 1;
s.gridy = 0;
panel1.add(player1scoreTitleLabel,s);
s.weightx = 1;
s.gridx = 2;
s.gridy = 0;
panel1.add(turnTitleLabel);
s.weightx = 1;
s.gridx = 3;
s.gridy = 0;
panel1.add(player2scoreTitleLabel,s);
s.weightx = 1;
s.gridx = 4;
s.gridy = 0;
panel1.add(quitGameButton,s);
// panel 2 (red border)
JPanel panel2 = new JPanel();
GridLayout layout = new GridLayout(r,c);
layout.setHgap(0);
layout.setVgap(0);
panel2.setLayout(layout);
panel2.setBorder(new LineBorder(Color.blue,4));
for (int i =0; i<r; i++) {
for (int j =0; j < c; j++) {
tiles[i][j] = new JButton(){
@Override
public Dimension getPreferredSize() {
return new Dimension(100,100);
}
};
tiles[i][j].setBackground(colornormal);
panel2.add(tiles[i][j]);
tiles[i][j].addActionListener(attackHandler);
}
}
frame.add(panel1,BorderLayout.norTH);
frame.add(panel2,BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
public class AttackHandler implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
Object source = e.getSource();
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (source == tiles[i][j]) {
isHit(i,j);
return;
}
}
}
}
}
public void isHit(int row,int col) {
if (AllHit()) {
JOptionPane.showMessageDialog(null,"All Ships Destructed!");
setWinner();
String winner =DecideWinner();
if(p1.won){
p1.checkHighscore();
}
else if (p2.won){
p2.checkHighscore();
}
JOptionPane.showMessageDialog(null,winner,"Play
Again",JOptionPane.YES_NO_OPTION);
if (again==0){
Main.main(null);
}
frame.dispose();
}
else if (map[row][col] == 5) {
AddPoint(p1.turn,5);
tiles[row][col].setBackground(colorCarrier);
map[row][col] = 1;
} else if (map[row][col] == 4) {
AddPoint(p1.turn,2);
tiles[row][col].setBackground(colorDestroyer);
map[row][col] = 1;
} else if (map[row][col] == 1) {
System.out.println("Already Hit!");
} else if (map[row][col] == 0 || map[row][col] == 9) {
tiles[row][col].setBackground(colorWater);
map[row][col] = 1;
}
p1.changeTurn(p1.turn);
p2.changeTurn(p2.turn);
// I cannot find a way to change the labels....
player1scoreTitleLabel.setText(String.valueOf(p1.points));
player2scoreTitleLabel.setText(String.valueOf(p2.points));
turnTitleLabel.setText(Turn());
System.out.println("Points Player 1: "+p1.points);
System.out.println("Points Player 2: "+p2.points);
}
public boolean AllHit() {
boolean allHit = true;
for (int i = 0; i<rows;i++) {
for (int j = 0; j < cols; j++) {
if (map[i][j] != 1 && map[i][j] != 0) {
allHit = false;
break;
}
}
}
return allHit;
}
public void AddRandomShips(int rows,int cols) {
int[][] map = ship.setRandomShips(rows,coordinates);
setMap(map);
}
public void scoreMethod(boolean scoreMethod){
if(scoreMethod){
equalPoints = true;
}
else {
equalPoints = false;
}
}
public void AddPoint(boolean turn,int amount){
if (turn){
p1.points = p1.points+ amount;
}
else p2.points = p2.points+amount;
}
public void setWinner(){
if(p1.points>p2.points){
p1.setWon();
}
else if (p2.points>p1.points){
p2.setWon();
}
}
public String DecideWinner(){
if (p1.won){
return "Player 1 won the game!";
}
else if (p2.won){
return "Player 2 won the game!";
}
else return "It's a tie!";
}
public String Turn(){
if (p1.turn){
return "Player 1";
}else return "Player 2";
}
这会生成以下 GUI:
但是,我仍在努力寻找一种方法来更改分数 JLabels 的文本值,以下代码对我不起作用:
player1scoreTitleLabel.setText(String.valueOf(p1.points));
player2scoreTitleLabel.setText(String.valueOf(p2.points));
turnTitleLabel.setText(Turn())
解决方法
在此处添加我的评论是一个小示例,可帮助您入门,而无需 IDE 的负担来构建包含尽可能多的 Swing 最佳实践的 UI:
- 我选择使用
JLabel
,因为它更有意义 -
黄色 边框代表
panel1
,它使用了 GridBagLayout。 -
红色面板代表使用 GridLayout 的
panel2
。 - 最后,将 2 个
JPanel
添加到默认使用 BorderLayout 的JFrame
。
TestApp.java:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.border.LineBorder;
public class TestApp {
public TestApp() {
createAndShowGui();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(TestApp::new);
}
private void createAndShowGui() {
JFrame frame = new JFrame("TestApp");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// panel 1 (yellow border)
JPanel panel1 = new JPanel(new GridBagLayout());
JButton highScoresButton = new JButton("High Scores");
JLabel player1ScoreLabel = new JLabel("<html>Player 1 Score:<br><h2>950</h2>");
JLabel turnLabel = new JLabel("<html>Turn:<br><h1>Player 1</h1>");
JLabel player2ScoreLabel = new JLabel("<html>Player 2 Score:<br><h2>925</h2>");
JButton quitGameButton = new JButton("Quit Game");
GridBagConstraints c = new GridBagConstraints();
c.weightx = 1;
c.gridx = 0;
c.gridy = 0;
panel1.add(highScoresButton,c);
c.weightx = 1;
c.gridx = 1;
c.gridy = 0;
panel1.add(player1ScoreLabel,c);
c.weightx = 1;
c.gridx = 2;
c.gridy = 0;
panel1.add(turnLabel);
c.weightx = 1;
c.gridx = 3;
c.gridy = 0;
panel1.add(player2ScoreLabel,c);
c.weightx = 1;
c.gridx = 4;
c.gridy = 0;
panel1.add(quitGameButton,c);
panel1.setBorder(new LineBorder(Color.YELLOW,4)); // just for visual purposes of the answer
// panel 2 (red border)
JPanel panel2 = new JPanel();
GridLayout layout = new GridLayout(8,8);
layout.setHgap(5);
layout.setVgap(5);
panel2.setLayout(layout);
panel2.setBorder(new LineBorder(Color.RED,4)); // just for visual purposes of the answer
for (int i = 0; i < 64; i++) {
JLabel label = new JLabel() {
@Override
public Dimension getPreferredSize() {
return new Dimension(100,100);
}
};
label.setOpaque(true);
label.setBackground(Color.DARK_GRAY);
panel2.add(label);
}
frame.add(panel1,BorderLayout.NORTH);
frame.add(panel2,BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
}