本文介绍了如何有效,快速地使用JButton完全填充JFrame?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以,我正在努力用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?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-28 17:24