问题描述
所以,我正在努力用Java重新创建Minesweeper,现在我需要将JFrame上的所有按钮放在网格中。我的代码如下:
So, I am working on recreating Minesweeper in Java and right now I need to place all of the buttons on the JFrame in a grid. My code is below:
import javax.swing.*;
import java.util.ArrayList;
import java.awt.*;
import javax.imageio.*;
public class Graphics{
private JFrame frame;
private JPanel panel;
private JLabel label;
private int boardSizeY;
private int boardSizeX;
private ImageIcon ImgEmpty = new ImageIcon("/Images/Empty.png");
private ImageIcon ImgFull = new ImageIcon("/Images/UnSelected.png");
public Graphics(int sizeY, int sizeX){
boardSizeX = sizeX;
boardSizeY = sizeY;
gui();
drawButtons();
}
public void gui() {
frame = new JFrame("Minesweeper");
frame.setVisible(true);
frame.setSize(boardSizeX*20, boardSizeY*20 + 2);
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel = new JPanel();
panel.setLayout(null);
}
public void drawButtons(){
ArrayList<JButton> buttons = new ArrayList<>();
int x = 0;
int y = 0;
for(int t = 0; t < boardSizeX*boardSizeY; t++){
buttons.add(new JButton(ImgFull));
panel.add(buttons.get(t));
buttons.get(t).setBounds(x*20, y*20, 20, 20);
if(y == boardSizeY-1){
x++;
y = 0;
}
else y++;
}
frame.add(panel);
}
}
我编写的代码非常慢对于尺寸大于10x10的电路板。我可以对drawButtons()函数进行哪些更改以加快处理。
The code that I wrote works, however is extremely slow for board sizes greater than 10x10. What changes can I make to my drawButtons() function in order to quicken the process.
推荐答案
这30 x 30(900个按钮) )版本几乎立即出现在这台机器上。它使用 JButton
组件并使用 GridLayout
将它们排出。
This 30 x 30 (900 buttons) version appears almost instantly on this machine. It uses JButton
components and lays them out using a GridLayout
.
这是10 x 10大字体的样子。
This is what it looks like at 10 x 10 with a larger font.
import java.awt.*;
import java.util.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
public class MineSweeper {
public final static String BOMB = new String(Character.toChars(128163));
private JComponent ui = null;
private MineFieldModel mineFieldModel;
private final Color[] colors = {
Color.BLUE,
Color.CYAN.darker(),
Color.GREEN.darker(),
Color.YELLOW.darker(),
Color.ORANGE.darker(),
Color.PINK.darker(),
Color.MAGENTA,
Color.RED
};
private final int size = 30;
private final float fontSize = 10f;
private JButton[][] buttons;
private JLabel info = new JLabel("Enter the minefield!");
MineSweeper() {
initUI();
}
private JToolBar getToolBar() {
JToolBar tb = new JToolBar();
tb.setFloatable(false);
tb.setLayout(new FlowLayout(FlowLayout.LEADING, 4, 2));
tb.add(info);
return tb;
}
private final Point[] getExposableSquares(Point point) {
Point[] points = null;
int x = point.x;
int y = point.y;
if (mineFieldModel.isBomb(x, y)) {
}
return points;
}
public final void initUI() {
if (ui != null) {
return;
}
ui = new JPanel(new BorderLayout(4, 4));
ui.setBorder(new EmptyBorder(4, 4, 4, 4));
ui.add(getToolBar(), BorderLayout.PAGE_START);
mineFieldModel = new MineFieldModel(size, (int)(size*size*.4));
JPanel mineFieldContainer = new JPanel(new GridLayout(
size, size));
ui.add(mineFieldContainer, BorderLayout.CENTER);
int in = 5;
Insets insets = new Insets(in, in, in, in);
Font f = getCompatibleFonts().firstElement().deriveFont(fontSize);
buttons = new JButton[size][size];
for (int ii = 0; ii < size; ii++) {
for (int jj = 0; jj < size; jj++) {
JButton b = new SquareButton();
b.setMargin(insets);
b.setFont(f);
b.setText("?");
if (mineFieldModel.isExposed(ii, jj)) {
if (mineFieldModel.isBomb(ii, jj)) {
b.setForeground(Color.red);
b.setForeground(Color.BLACK);
b.setText(BOMB);
} else if (mineFieldModel.countSurroundingMines(ii, jj) > 0) {
int count = mineFieldModel.countSurroundingMines(ii, jj);
if (count > 0) {
b.setForeground(colors[count - 1]);
b.setText("" + count);
}
} else {
b.setText("");
}
}
buttons[ii][jj] = b;
mineFieldContainer.add(b);
}
}
}
private static Vector<Font> getCompatibleFonts() {
Font[] fonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts();
Vector<Font> fontVector = new Vector<>();
for (Font font : fonts) {
if (font.canDisplayUpTo("12345678?" + BOMB) < 0) {
fontVector.add(font);
}
}
return fontVector;
}
public JComponent getUI() {
return ui;
}
public static void main(String[] args) {
Runnable r = () -> {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception useDefault) {
}
MineSweeper o = new MineSweeper();
JFrame f = new JFrame(o.getClass().getSimpleName());
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setLocationByPlatform(true);
f.setContentPane(o.getUI());
f.pack();
f.setMinimumSize(f.getSize());
f.setVisible(true);
};
SwingUtilities.invokeLater(r);
}
}
class MineFieldModel {
public int size;
/**
* Records bomb locations.
*/
boolean[][] mineField;
/**
* Records whether this location has been exposed.
*/
boolean[][] fieldPlaceExposed;
int numberMines;
Random r = new Random();
MineFieldModel(int size, int numberMines) {
this.size = size;
this.numberMines = numberMines;
mineField = new boolean[size][size];
fieldPlaceExposed = new boolean[size][size];
ArrayList<Point> locations = new ArrayList<>();
for (int ii = 0; ii < this.size; ii++) {
for (int jj = 0; jj < size; jj++) {
mineField[ii][jj] = false;
// must change this to false for the actual game.
fieldPlaceExposed[ii][jj] = true;
Point p = new Point(ii, jj);
locations.add(p);
}
}
Collections.shuffle(locations, r);
for (int ii = 0; ii < numberMines; ii++) {
Point p = locations.get(ii);
mineField[p.x][p.y] = true;
}
}
public boolean isBomb(int x, int y) {
return mineField[x][y];
}
public boolean isExposed(int x, int y) {
return fieldPlaceExposed[x][y];
}
public int getSize() {
return size;
}
public int countSurroundingMines(int x, int y) {
int lowX = x - 1;
lowX = lowX < 0 ? 0 : lowX;
int highX = x + 2;
highX = highX > size ? size : highX;
int lowY = y - 1;
lowY = lowY < 0 ? 0 : lowY;
int highY = y + 2;
highY = highY > size ? size : highY;
int count = 0;
for (int ii = lowX; ii < highX; ii++) {
for (int jj = lowY; jj < highY; jj++) {
if (ii != x || jj != y) {
if (mineField[ii][jj]) {
count++;
}
}
}
}
return count;
}
}
class SquareButton extends JButton {
@Override
public Dimension getPreferredSize() {
Dimension d = super.getPreferredSize();
int w = d.width;
int h = d.height;
int s = w>h ? w : h;
return new Dimension(s, s);
}
}
这篇关于如何有效,快速地使用JButton完全填充JFrame?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!