JButton 隐藏直到悬停第一次启动

JButton Hidden Until Hovered First Startup

请注意,我发现了一个类似的 post ,但是这个问题似乎一直存在这个问题,并没有真正提供关于为什么会发生这种情况的解释,只是一个替代方案方法。

我正在创建一个 Stratego 游戏,现在我正在创建棋盘,游戏可以在其中交换他们的棋子,然后提交棋盘布局作为他们军队的起始位置。

我在每一帧上都有一个 JButton(每个玩家一个,第二个在第一个玩家提交并离开计算机后出现),并且第一帧上的 JButton 仅在您悬停之前隐藏它,但只是程序在打开 Eclipse 后第一次运行。

谁能解释一下为什么会这样?

主要运行class

LogicInterpreter logic = new LogicInterpreter();

    Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();

    InputFrame inputPlayer1 = new InputFrame(logic, 1, "red", 600, 600);
    inputPlayer1.setLocation(dim.width / 2 - inputPlayer1.getSize().width/2,
            dim.height / 2 - inputPlayer1.getSize().height / 2);

    while(!logic.isSetUp1()){
        //Just to make it work
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    //Now bring up board 2

    InputFrame inputPlayer2 = new InputFrame(logic, 2, "blue", 600, 600);
    inputPlayer2.setLocation(dim.width / 2 - inputPlayer2.getSize().width/2,
            dim.height / 2 - inputPlayer2.getSize().height / 2);

    while(!logic.isSetUp2()){
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    //Will eventually open the main board
    openBoards(logic);
}

这是输入帧的相关设置代码

public class InputFrame extends JFrame {

private static final long serialVersionUID = 1L;
private LogicInterpreter holder;
private Panel2 jp;
private int height, width;
private Map<Integer, ArrayList<Integer>> lakeCoords = new HashMap<>();
private List<Piece> pieces = new ArrayList<>();
private int playernumber;
private String playerColor;
Piece selectedPiece;
Piece secondSelectedPiece;
boolean hidePieces = false;

JButton submit = new JButton("SUBMIT");

public void addCoords() {
    lakeCoords.put(3, new ArrayList<Integer>(Arrays.asList(6, 5)));
    lakeCoords.put(4, new ArrayList<Integer>(Arrays.asList(6, 5)));
    lakeCoords.put(7, new ArrayList<Integer>(Arrays.asList(6, 5)));
    lakeCoords.put(8, new ArrayList<Integer>(Arrays.asList(6, 5)));
}

public void createPieces() {
    int y = 1;

    if (playernumber == 2) {
        y = 6;
    }

    List<Integer> openValues = new ArrayList<>();

    openValues.add(1);
    openValues.add(2);
    openValues.add(11);
    openValues.add(12);
    for (int x = 0; x < 2; x++) {
        openValues.add(3);
    }
    for (int x = 0; x < 3; x++) {
        openValues.add(4);
    }
    for (int x = 0; x < 4; x++) {
        openValues.add(5);
        openValues.add(6);
        openValues.add(7);
    }
    for (int x = 0; x < 5; x++) {
        openValues.add(8);
    }
    for (int x = 0; x < 8; x++) {
        openValues.add(9);
    }
    for (int x = 0; x < 6; x++) {
        openValues.add(10);
    }

    Collections.sort(openValues);
    for (int x = 1; x <= 10; x++) {
        for (int z = y; z <= 4; z++) {

            // 1x1 Marshal
            // 2x1 General
            // 3x2 Colonel
            // 4x3 Major
            // 5x4 Captain
            // 6x4 Lieutenant
            // 7x4 Sergeant
            // 8x5 Miner
            // 9x8 Scout
            // 10x6 Bomb
            // 11x1 Flag
            // 12x1 Spy

            Piece piece = new Piece(new Coords(x, z), openValues.get(0), playerColor);

            openValues.remove(0);
            pieces.add(piece);
        }
    }
}

public InputFrame(LogicInterpreter holder, int playerNumber, String playerColor, int height, int width) {
    this.height = height;
    this.width = width;
    playernumber = playerNumber;
    this.playerColor = playerColor;
    setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    addCoords();
    this.holder = holder;
    createPieces();
    jp = new Panel2(height, width);
    setResizable(false);
    jp.setBackground(new Color(235, 202, 158));
    setTitle("Player " + playerNumber + " Arrangement GUI     ||     Click Submit When Ready");
    jp.setPreferredSize(new Dimension(600, 600));
    jp.setLayout(null);
    jp.addMouseListener(new HandleMouse());
    getContentPane().add(jp);
    pack();
    setVisible(true);

    if(playernumber == 1)
        submit.setBounds(width / 10 * 4, height / 10 * 7, width / 10 * 2, height / 10 * 2);
    else
        submit.setBounds(width / 10 * 4, height / 10, width / 10 * 2, height / 10 * 2);
    submit.setFont(new Font("Arial", Font.BOLD, width * 20 / 600));
    submit.setBackground(Color.LIGHT_GRAY);
    submit.addActionListener(new CloseListener(this));
    jp.add(submit);
}

//More stuff down here about logic and stuff

public class Panel2 extends JPanel {

    private static final long serialVersionUID = 1L;
    int height = 0;
    int width = 0;

    public Panel2(int height, int width) {
        this.height = height;
        this.width = width;
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        for (int x = 0; x < width; x += width / 10) {
            for (int y = 0; y < height; y += height / 10) {
                boolean fill = false;
                for (Entry<Integer, ArrayList<Integer>> coords : lakeCoords.entrySet()) {
                    if ((coords.getKey() - 1 == x / 60 && coords.getValue().get(0) - 1 == y / 60)
                            || (coords.getKey() - 1 == x / 60 && coords.getValue().get(1) - 1 == y / 60)) {
                        fill = true;
                        break;
                    }
                }
                if (fill) {
                    g.setColor(Color.BLUE);
                    g.fillRect(x, y, width / 10, height / 10);
                    g.setColor(Color.BLACK);
                    g.drawRect(x, y, width / 10, height / 10);
                } else {
                    g.setColor(Color.BLACK);
                    g.drawRect(x, y, width / 10, height / 10);
                }
            }
        }

        if(hidePieces){
            for (Piece piece : pieces) {
                try {
                    g.drawImage(ImageIO.read(new File(playerColor + "_pieces/" + (playerColor.equals("blue") ? "Blue" : "Red") + "_Strat_Piece"
                            + ".png")), piece.getX() * width / 10 - width / 10,
                            piece.getY() * height / 10 - height / 10, width / 10, height / 10, null);
                } catch(Exception e){}
            }
        } else {
            for (Piece piece : pieces) {
                g.drawImage(piece.getImage(), piece.getX() * width / 10 - width / 10,
                        piece.getY() * height / 10 - height / 10, width / 10, height / 10, null);
            }

            if (selectedPiece != null) {
                g.setColor(Color.BLUE);
                g.drawImage(selectedPiece.getImage(), selectedPiece.getX() * width / 10 - width / 10,
                        selectedPiece.getY() * height / 10 - height / 10, width / 10, height / 10, null);
                g.drawRect(selectedPiece.getX() * width / 10 - width / 10,
                        selectedPiece.getY() * height / 10 - height / 10, width / 10, height / 10);
            }
        }
    }
}

必须在 EDT 中创建 Swing 组件。调用 sleep() 是 EDT 将阻止 UI,这绝不是一个好主意。有关 EDT 的详细信息,请参阅此内容:https://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html

setVisible(true);

....

jp.add(submit); // Note the add() is after the setVisible()

and the JButton on the first frame only is hidden until you hover it, but only the first time that the program runs after Eclipse is opened.

这意味着您在将所有组件添加到框架之前使框架可见。

所以基本逻辑的顺序是:

JPanel panel = new JPanel();
panel.add(...);
frame.add(panel);
frame.pack();
frame.setVisible(true);