简体   繁体   English

我无法在JButton上获取paintComponent()以使其正常工作

[英]I can't get paintComponent() on JButton to work properly

I'm having a problem with the paintComponent() method of my JButton. 我的JButton的paintComponent()方法有问题。 I want to program my own Minesweeper game and when I try to repaint my Tiles(which extend JButton) they don't seem to update. 我想编写自己的Minesweeper游戏,当我尝试重绘我的Tiles(扩展JButton)时,它们似乎没有更新。 Here is my Tile class: 这是我的Tile类:

package mineSweeper;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.SwingUtilities;
import javax.swing.border.Border;

public class Tile extends JButton{
/**
 * 
 */
private static final long serialVersionUID = 5476927382697663397L;
public static final int UNPRESSED = 0;
public static final int PRESSED = 1;
public static final int FLAG = 2;
public static final int BOMB = 3;
public static final int XBOMB = 4;
public static final int HEIGHT = 16;
public static final int WIDTH = 16;
private int paintMode = UNPRESSED;

public Tile(int x, int y){
    super();
    setBounds(x*WIDTH, y*HEIGHT, WIDTH, HEIGHT);
    setPreferredSize(new Dimension(WIDTH, HEIGHT));
    setMargin(new Insets(0, 0, 0, 0));
    setBorder(BorderFactory.createEmptyBorder());
    addActionListener(new ActionListener(){
        public void actionPerformed(ActionEvent e) {
            setEnabled(false);
            setPaintMode(PRESSED);
            repaint();
        }
    });
}

public void reset(){
    setEnabled(true);
    setPaintMode(UNPRESSED);
    repaint();
}

@Override
public void paintComponent(Graphics g){
    super.paintComponent(g);
    if (getPaintMode()==UNPRESSED)
    {
        setBackground(Color.LIGHT_GRAY);
        g.setColor(Color.WHITE);
        g.drawLine(0, 0, WIDTH-1, 0);
        g.drawLine(0, 1, WIDTH-2, 1);
        g.drawLine(0, 0, 0, HEIGHT-1);
        g.drawLine(1, 0, 1, HEIGHT-2);
        g.setColor(Color.GRAY);
        g.drawLine(WIDTH, HEIGHT, 1, HEIGHT);
        g.drawLine(WIDTH, HEIGHT-1, 2, HEIGHT-1);
        g.drawLine(WIDTH, HEIGHT, WIDTH, 1);
        g.drawLine(WIDTH-1, HEIGHT, WIDTH-1, 2);
    }
    if (getPaintMode()==PRESSED)
    {
        setBackground(Color.LIGHT_GRAY);
        g.drawLine(0, 0, WIDTH, 0);
        g.drawLine(0, 0, 0, HEIGHT);
    }
    g.dispose();
}

public int getPaintMode() {
    return paintMode;
}

public void setPaintMode(int mode) {
    mode = paintMode;
}
}

and the class Board 和班级委员会

package mineSweeper;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

public class Board extends JFrame{

/**
 * 
 */
private static final long serialVersionUID = 2769769568511334271L;

public static Tile[][] tile;
public JPanel panel = new JPanel(null);
public JButton resetButton = new ResetButton("Click here to Reset");
String input;
private static int screenWidth = 400;
private static int screenHeight = 400;
private static final int MAXROWS = 60;
private static final int MAXCOLUMS = 60;
private static final int MINROWS = 2;
private static final int MINCOLUMS = 6;
private static final int RESETBUTTONSIZE = 40;

public Board(){
    super("MineSweeper");
    askForInputs();
    resetButton.setBounds(0, screenHeight, screenWidth, RESETBUTTONSIZE);
    tile = new Tile[getColums()][getRows()];
    pack();
    setSize(screenWidth + getInsets().left + getInsets().right, screenHeight + getInsets().top + getInsets().bottom + RESETBUTTONSIZE);
    getContentPane().add(panel);
    panel.add(resetButton);
    setResizable(false);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    for (int x = 0; x < getColums(); x++)
    {
        for (int y = 0; y < getRows(); y++)
        {
            tile[x][y] = new Tile(x,y);
            panel.add(tile[x][y]);
        }
    }
    setVisible(true);
}

private void askForInputs() {
    try{
    input = JOptionPane.showInputDialog(null, "Enter number of rows ( Maximum " + MAXROWS + " / Minimum " + MINROWS +")" );
    Integer.parseInt(input);
    }
    catch(Exception ex){input = "";}
    if (!(input == null) && !(input.isEmpty()) && !(Integer.parseInt(input) < MINROWS)){
        if (Integer.parseInt(input) > MAXROWS)
            screenHeight = MAXROWS * Tile.HEIGHT;
    }
    else input = String.valueOf(MAXROWS/4);
    screenHeight = Integer.parseInt(input) * Tile.HEIGHT;

    try{
    input = JOptionPane.showInputDialog(null, "Enter number of colums ( Maximum " + MAXCOLUMS + " / Minimum " + MINCOLUMS + ")" );
    Integer.parseInt(input);
    }
    catch(Exception ex){input = "";}
    if (!(input == null) && !(input.isEmpty()) && !(Integer.parseInt(input) < MINCOLUMS))
    {
    if (Integer.parseInt(input) > MAXCOLUMS)
        screenWidth = MAXCOLUMS * Tile.WIDTH;
    }
    else input = String.valueOf(MAXCOLUMS/4);
    screenWidth = Integer.parseInt(input) * Tile.WIDTH;
}

public static void reset(){
    for (int x = 0; x < getColums(); x++)
    {
        for (int y = 0; y < getRows(); y++)
        {
            tile[x][y].reset();
        }
    }
}

public static int getScreenWidth() {
    return screenWidth;
}
public static void setScreenWidth(int screenWidth) {
    Board.screenWidth = screenWidth;
}
public static int getScreenHeight() {
    return screenHeight;
}
public static void setScreenHeight(int screenHeight) {
    Board.screenHeight = screenHeight;
}
public static  int getColums(){
    return getScreenWidth() / Tile.WIDTH;
}
public static  int getRows(){
    return getScreenHeight() / Tile.HEIGHT;
}
public static void main (String args[]){
    new Board();
}
}

Don't mind the unused imports. 不要介意未使用的进口。 So my problem is: when I click a Tile I see I clicked it and I can't click it again but it looks the same like before. 所以我的问题是:当我单击图块时,我看到它单击了,但是我无法再次单击它,但是它看起来和以前一样。 What am I doing wrong please help. 我做错了什么,请帮忙。

There's a number of things pop out at me, but you're main problem is this... 有很多事情发生在我身上,但是你的主要问题是……

public class Tile extends JButton {
    //...
    public void setPaintMode(int mode) {
        mode = paintMode;
    }
}

You never actually assign the current mode to the paintMode variable, the assignment is backwards. 您实际上从未将当前模式分配给paintMode变量,而是反向分配。

I'd recommend using JFrame#setExtendedState to set the frame MAXIMIZED_BOTH state over the setSize hack you're currently using, it'll at least reduce the amount of code. 我建议使用JFrame#setExtendedState通过当前使用的setSize hack设置帧MAXIMIZED_BOTH状态,这至少会减少代码量。

I'd also recommend using a GridLayout or GridBagLayout of a null layout any day. 我还建议您每天都使用null布局的GridLayoutGridBagLayout

Have you considered using a JToggleButton , it's basically what you're doing now? 您是否考虑过使用JToggleButton ,这基本上就是您现在正在做的事情?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM