3

当我运行我的代码时,我希望JPanel在我的 中看到 a JFrame,但什么也没有出现。我在框架中有一个按钮,它会显示出来。但是JPanel没有出现,我什至把它涂成红色。这是我的代码JPanel

import java.awt.*;
import javax.swing.JPanel;
public class graphic extends JPanel {
    private static final long serialVersionUID = -3458717449092499931L;
    public Game game;
    public graphic(Game game){
    this.game = game;
    this.setPreferredSize(new Dimension(400,400));
    this.setBackground(Color.RED);
}
public void paintComponent(Graphics g){
    for (Line l:game.mirrors){
        g.setColor(Color.BLACK);
        g.drawLine(l.start.x, l.start.y, l.end.x, l.end.y);
    }
}
}

还有我的 JFrame 代码:

import java.awt.Container;
import java.awt.event.*;
import java.util.Timer;
import java.util.TimerTask;

import javax.swing.*;
public class Viewer implements ActionListener {
public JFrame frame;
public JButton drawShoot;
public boolean draw;
public Game game;
public graphic graphic;
public TimerTask timert;
public Timer timer;
public Viewer(){
    draw = true;
    game = new Game();
}
public static void main(String args[]){
    Viewer v = new Viewer();
    v.setup();
}
public void setup(){
    frame = new JFrame("Laser Stimulator");
    drawShoot = new JButton("Edit Mode");
    graphic = new graphic(game);
    graphic.repaint();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setBounds(300, 300, 600, 600);
    Container contentPane = frame.getContentPane();
    SpringLayout layout = new SpringLayout();
    contentPane.setLayout(layout);
    drawShoot.addActionListener(this);
    timert = new TimerTask() {
        @Override
        public void run() {

        }
    };
    timer =new Timer();
    timer.scheduleAtFixedRate(timert, 0, 1000/30);
    contentPane.add(graphic);
    layout.putConstraint(SpringLayout.NORTH, graphic, 0, SpringLayout.NORTH, contentPane);
    layout.putConstraint(SpringLayout.WEST, graphic, 0, SpringLayout.WEST, contentPane);
    frame.setVisible(true);
}
@Override
public void actionPerformed(ActionEvent e) {
    if (e.getSource()==drawShoot){
        draw = !draw;
        drawShoot.setText((draw)?"Edit Mode":"Shoot Mode");
    }
}
}
4

2 回答 2

5

所以基本问题是你没有尊重油漆链。您必须super.paintXxx在覆盖绘制方法时调用...

这个方法必须调用super.paintComponent(g),因为它负责清除背景;)

public void paintComponent(Graphics g) {
    for (Line l : game.mirrors) {
        g.setColor(Color.BLACK);
        g.drawLine(l.start.x, l.start.y, l.end.x, l.end.y);
    }
}

在此处输入图像描述

public class QuickTestPaintPane {

    public static void main(String[] args) {
        new QuickTestPaintPane();
    }

    public QuickTestPaintPane() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException ex) {
                } catch (InstantiationException ex) {
                } catch (IllegalAccessException ex) {
                } catch (UnsupportedLookAndFeelException ex) {
                }

                Viewer v = new Viewer();
                v.setup();

            }
        });
    }

    public class Viewer implements ActionListener {

        public JFrame frame;
        public JButton drawShoot;
        public boolean draw;
//        public Game game;
        public graphic graphic;
        public TimerTask timert;
        public Timer timer;

        public Viewer() {
            draw = true;
//            game = new Game();
        }

        public void setup() {
            frame = new JFrame("Laser Stimulator");
            drawShoot = new JButton("Edit Mode");
            graphic = new graphic();
//            graphic.repaint();
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setBounds(300, 300, 600, 600);
//            Container contentPane = frame.getContentPane();
            SpringLayout layout = new SpringLayout();
            frame.setLayout(layout);
            drawShoot.addActionListener(this);
            timert = new TimerTask() {
                @Override
                public void run() {
                }
            };
            timer = new Timer();
            timer.scheduleAtFixedRate(timert, 0, 1000 / 30);
            frame.add(graphic);
            layout.putConstraint(SpringLayout.NORTH, graphic, 0, SpringLayout.NORTH, frame.getContentPane());
            layout.putConstraint(SpringLayout.WEST, graphic, 0, SpringLayout.WEST, frame.getContentPane());
            frame.setVisible(true);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            if (e.getSource() == drawShoot) {
                draw = !draw;
                drawShoot.setText((draw) ? "Edit Mode" : "Shoot Mode");
            }
        }
    }

    public class graphic extends JPanel {

        private static final long serialVersionUID = -3458717449092499931L;
//        public Game game;

//        public graphic(Game game) {
        public graphic() {
//            this.game = game;
            this.setPreferredSize(new Dimension(400, 400));
            this.setBackground(Color.RED);
        }

        public void paintComponent(Graphics g) {
            super.paintComponent(g);

            Graphics2D g2d = (Graphics2D) g;
            g2d.setColor(Color.BLACK);
            g2d.drawLine(0, 0, getWidth(), getHeight());
//            for (Line l : game.mirrors) {
//                g.setColor(Color.BLACK);
//                g.drawLine(l.start.x, l.start.y, l.end.x, l.end.y);
//            }
        }
    }
}
于 2012-11-04T04:58:09.697 回答
4

@MadProgrammer 已经回答了这个问题(给他+1)。在大多数被覆盖的方法中,都会调用它们的super不要忘记尊重这一点,否则这些小问题就会开始浮出水面。

另一个注意事项:

  • 不要打电话setBounds(..)JFrame我看不出你为什么需要它)而是JFrame#pack()在设置JFrame可见之前打电话。

  • 从 Java 6开始不需要这样做frame.getContentPane()。只需使用: frame.add()frame.setLayout(..).

    作为一种便利add及其变体,removesetLayout已被覆盖以根据需要转发到contentPane

  • 你也有这个:

    graphic = new graphic(game);
    graphic.repaint();
    

    我不明白为什么在组件第一次可见时调用repaint()将是必要的repaint()

  • 而不是覆盖getPreferredSizeJPanel不是调用setPreferredSize()

  • ActionListener除非将通过其他类访问,否则不要在类中实现 an 。而是像这样使用匿名Listener

    refresh.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (e.getSource() == drawShoot) {
                    draw = !draw;
                    drawShoot.setText((draw) ? "Edit Mode" : "Shoot Mode");
                }
            }
    
    });
    
于 2012-11-04T07:27:17.663 回答