彩绘JPanel不会出现在JFrame中

时间:2012-11-04 04:45:43

标签: java swing jframe jpanel paintcomponent

当我运行代码时,我希望在JPanel中看到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");
    }
}
}

2 个答案:

答案 0 :(得分: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);
    }
}

enter image description here

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);
//            }
        }
    }
}

答案 1 :(得分:4)

@MadProgrammer已经回答了这个问题(给他+1)。在大多数覆盖方法中,有人要求他们的 super 不要忘记尊重这个,否则这些小小的打嗝就会浮出水面。

另一方面说明:

  • 请勿在{{1​​}}上致电setBounds(..)(我无法理解您的需要),而是在设置JFrame可见之前致电JFrame#pack()

    < / LI>
  • 从Java 6开始,无需执行JFrame。只需使用: frame.getContentPane()frame.add()

      

    作为一种契约frame.setLayout(..)及其变体,addremove已经存在   根据需要覆盖转发到 contentPane

  • 你也有:

    setLayout

    我无法理解为什么在第一次看到组件时会调用graphic = new graphic(game); graphic.repaint(); 来调用repaint()

  • 相反覆盖repaint() getPreferredSize而不是调用JPanel

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

    Listener