【问题标题】:Why is paintComponent not drawing on the panel?为什么paintComponent不在面板上绘制?
【发布时间】:2018-02-16 12:43:15
【问题描述】:

我在将代码绘制到我的 jpanel 时遇到了一些问题。

除图形绘制外,一切运行正常。

还有其他答案说我需要用setSize设置面板的大小,但我已经这样做了。

其他答案说我需要打电话给super.paintComponent(g);,但我也这样做。

我错过了什么?

这是我的代码:

提前感谢您的帮助。

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import static java.awt.Color.*;

public class Main extends JPanel implements KeyListener {

    //Declare all class vars.
    private Snake snake = new Snake(50,50,50);

    //Declare all Player global booleans
    private boolean leftPressed, rightPressed, upPressed, downPressed;

    //Declare all Gamestate gobal booleans
//    private boolean running = true;

    public static void main(String[] args){
        Main main = new Main();

        main.createFrame();
        SwingUtilities.invokeLater(main::customUpdate);
    }



    private void createFrame() {
        JFrame frame = new JFrame("Snaek");
        JPanel panel = new JPanel();
        frame.setResizable(false);
        frame.setSize(800,800);
        frame.setLocationRelativeTo(null);
        frame.add(panel);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        panel.requestFocus();
        panel.addKeyListener(this);
        panel.setSize(new Dimension(frame.getWidth(), frame.getHeight()));
        Frame.getFrames();
    }

    private void customUpdate() {
        if(leftPressed) {
            snake.changeX(-1);
        } else if(upPressed) {
            snake.changeY(-1);
        } else if(downPressed) {
            snake.changeY(1);
        } else if(rightPressed) {
            snake.changeX(1);
        }
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        g.setColor(black);
        g.drawRect(snake.getX(), snake.getY(), snake.getSize(), snake.getSize());
        g.drawRect(100,100,200,200);
        repaint();
    }

    @Override
    public void keyTyped(KeyEvent e) {

    }

    @Override
    public void keyPressed(KeyEvent e) {
        switch (e.getKeyCode()) {
            case 37:
//                System.out.println("Left?");
                leftPressed = true;
                break;
            case 38:
//                System.out.println("Up?");
                upPressed = true;
                break;
            case 39:
//                System.out.println("Right?");
                rightPressed = true;
                break;
            case 40:
                System.out.println("Down?");
                downPressed = true;
                break;
            case 27: //Escape
                System.out.println(snake.getX());
                break;
            case 50: //Space
//                spacePressed = true;
                break;
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {
        System.out.println(e.getKeyCode());
        switch (e.getKeyCode()) {
            case 37:
//                System.out.println("Left?");
                leftPressed = false;
                break;
            case 38:
//                System.out.println("Up?");
                upPressed = false;
                break;
            case 39:
//                System.out.println("Right?");
                rightPressed = false;
                break;
            case 40:
//                System.out.println("Down?");
                downPressed = false;
                break;

        }
    }
}

【问题讨论】:

  • 不要在paintComponent 内调用repaint。相反,在需要时重新绘制(更改位置后)。但是你不能,因为你只打电话给customUpdate 一次。可能想要使用Timer 或切换到活动渲染。
  • There are other answers saying that I need to set the size of the panel with setSize - 我从未见过这样的答案。您不应该设置任何组件的大小。布局管理器的工作是设置组件的大小和位置。您应该做的是覆盖面板的getPreferredSize() 方法以返回首选大小。阅读 Custom Painting 上的 Swing 教程部分,了解更多信息和工作示例。

标签: java swing graphics


【解决方案1】:

您正在这里创建一个新的JPanel

JPanel panel = new JPanel();

然后将其添加到JFrame

frame.add(panel);

您应该将您的面板 (Main) 添加到其中

frame.add(this);

另外,正如上面 cmets 中 @VinceEmigh 所述,避免在 paintComponent() 方法中调用 repaint(),否则您可能会陷入无限循环、滞后或冻结在您的应用程序中。绘画方法仅供绘画。

另一个提示是使用KeyBindings 而不是KeyListener,否则您可能会陷入程序不响应关键事件...

我还将frame.setVisible(true); 行移动到createFrame() 方法的末尾...

【讨论】:

  • 这修复了它。非常感谢!
  • 很高兴它有帮助,请务必accept它:)
  • 为什么我应该在末尾而不是开头添加frame.setVisible?它会影响性能还是只是一种好的做法?
  • 我一定会接受这个答案,我只需要等到堆栈溢出让我:)
  • @wanderer0810 布局。使用布局时,必须在添加新组件或现有组件更改位置/大小时通知根容器。您可以通过调用revalidate() 来通知根容器,但只有在根容器已经显示时才需要它,这就是为什么它比setVisible last 更受欢迎
【解决方案2】:

您正在向 JFrame 添加一个默认面板。您想添加自定义 JPanel。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-04-14
    • 2015-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-07
    • 2018-03-25
    相关资源
    最近更新 更多