为什么我的带图像的 jbutton 不显示图形 java

why won't my jbutton with image show up with graphics java

我的 jbutton 不显示时遇到了问题。如果我不使用 paintComponent,那么我的带有图像的 JButtons 就没有问题。但是现在,图像没有显示出来。如果我将鼠标悬停在它应该出现的位置上,图像会显示一秒钟。所以好像按钮还在,可能就在背景下面?

public class Game extends JPanel implements KeyListener, ActionListener {

    //layout variables
    private ImageIcon right,left,up,down;
    private JButton rightButton,leftButton,upButton,downButton;

    //play variables
    private boolean play=false;
    private int score=0;

    private int paddleX= 200; //paddle X position
    private int paddleY= 300; //paddle Y pos
    private int ballX= 210; //ball x position
    private int ballY= 260; //ball y position
    private int ballXdir=-1; //x direction
    private int ballYdir=-2; //y direction

    private Timer time; //my timer

    public Game() {
        Display(); //display the layout
        addKeyListener(this);
        setFocusable(true);
        setFocusTraversalKeysEnabled(false);
        time= new Timer(8,this);
        time.start();
    }

    public void Display(){

        //setLayout
        this.setLayout(null);

        //Setting the Images
        //right = new ImageIcon(getClass().getResource("images\rightIcon.png"));
        left = new ImageIcon(getClass().getResource("images\leftIcon.png"));
        up = new ImageIcon(getClass().getResource("images\upIcon.png"));
        down = new ImageIcon(getClass().getResource("images\downIcon.png"));

        //Setting the JButtons for the arrow images
        rightButton= new JButton("right");
        rightButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if(paddleX>=400){
                    paddleX=400;
                }
                else{
                    moveRight();
                }
                repaint();
            }
        });
        //rightButton.setOpaque(false);
        //rightButton.setContentAreaFilled(false);
        //rightButton.setBorderPainted(false);

        leftButton= new JButton(left);
        leftButton.setOpaque(false);
        leftButton.setContentAreaFilled(false);
        leftButton.setBorderPainted(false);

        upButton= new JButton(up);
        upButton.setOpaque(false);
        upButton.setContentAreaFilled(false);
        upButton.setBorderPainted(false);

        downButton= new JButton(down);
        downButton.setOpaque(false);
        downButton.setContentAreaFilled(false);
        downButton.setBorderPainted(false);

        //setting image bounds and adding it to screen
        rightButton.setBounds(135,450,50,50);
        leftButton.setBounds(45,450,50,50);
        upButton.setBounds(90,400,50,50);
        downButton.setBounds(90,500,50,50);

        //rightButton.addActionListener(this);
        leftButton.addActionListener(this);

        add(upButton);
        add(downButton);
        add(leftButton);
        add(rightButton);



    }

    //painting the screen with graphics
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setColor(Color.BLACK);
        g.fillRect(25,25,425,300); //game area

        //drawing the paddle
        g.setColor(Color.YELLOW);
        g.fillRect(paddleX,paddleY,50,8);

        //drawing the ball
        g.setColor(Color.PINK);
        g.fillOval(ballX,ballY,20,20);

        g.dispose();
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        time.start();

        if(e.getSource()==right) {
            if(paddleX>=400){
                paddleX=400;
            }
            else{
                moveRight();
            }           
        }

        if(e.getSource()==left) {
            if(paddleX<35){
                paddleX=35;
            }
            else{
                moveLeft();
            }
        }

        repaint();

    }
    @Override
    public void keyPressed(KeyEvent e) {
        if(e.getKeyCode()==KeyEvent.VK_RIGHT){
            if(paddleX>=400){
                paddleX=400;
            }
            else{
                moveRight();
            }

        }
        if(e.getKeyCode()==KeyEvent.VK_LEFT){
            if(paddleX<35){
                paddleX=35;
            }
            else{
                moveLeft();
            }
        }

    }
    @Override
    public void keyReleased(KeyEvent arg0) {

    }

    @Override
    public void keyTyped(KeyEvent arg0) {

    }

    public void moveRight(){
        play=true;
        paddleX+=10;
    }

    public void moveLeft(){
        play=true;
        paddleX-=10;
    }


}

我强烈建议您看看 Performing Custom Painting and Painting in AWT and Swing,因为它将解释绘画系统的工作原理。

基本上,您会通过 paintComponent 方法向您传递对当前用于执行当前绘制过程的 Graphics 上下文的引用。这是共享资源。绘制过程中涉及的所有组件都传递相同的 Graphics 上下文。

通过调用 dispose,您将释放上下文的所有底层资源,这在某些系统上可以防止绘制其他组件。

But they paint when I move my mouse over them

因为组件可以独立于其父组件进行绘制,但您还对父组件调用 repaint,您猜对了,它会绘制它的子组件。

建议

  • 创建一个专门用于执行自定义绘画操作(以及可能的其他一些基本游戏功能)的自定义组件
  • 创建另一个组件来容纳按钮(并使用适当的布局)
  • 使用它们之间共享的某种数据模型。该模型将保存“动作”的状态(即 up/down/left/right),“引擎”将使用此信息来更新游戏状态。
  • 利用 Key bindings API 解决与 KeyListener
  • 相关的不可靠性问题