将图纸添加到面板

时间:2015-08-04 15:29:52

标签: java jpanel graphics2d

这应该很简单,但我无法使其发挥作用。

我有两个类,一个应绘制圆形,另一个用按钮设置框架和面板。单击该按钮时,框架上将出现一个圆圈。我很困惑为什么它没有出现。这可能是非常简单的事,抱歉。

package ballsOnPane;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

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

public class Display implements ActionListener{

    private JFrame frame;
    private JPanel panel;
    private JButton button;


    public static void main(String[] args) {
        Display display = new Display();
    }

    public Display() {
        frame = new JFrame();
        frame.setSize(800, 500);
        frame.setTitle("Show balls");
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new BorderLayout());
        panel = new JPanel();
        frame.add(panel, BorderLayout.CENTER);
        button = new JButton("New Ball");
        frame.add(button, BorderLayout.SOUTH);
        button.addActionListener(this);
    }

    @Override
    public void actionPerformed(ActionEvent e) {

        Ball ball = new Ball(100, 100, 50);
        panel.add(ball);

    }

} 

和球类:

package ballsOnPane;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Ellipse2D;

import javax.swing.JPanel;

public class Ball extends JPanel{

    private int x;
    private int y;
    private int r;

    public Ball(int x, int y, int r){
        this.x = x;
        this.y = y;
        this.r = r;
    }

    public void paintComponent(Graphics g) {
        Graphics2D g2 =(Graphics2D) g;

        Ellipse2D circ = new Ellipse2D.Float(x, y, r, r);
        g2.draw(circ);


        }

}

2 个答案:

答案 0 :(得分:2)

将组件添加到可见GUI时,基本代码为:

panel.add(...);
panel.revalidate(); // to invoke the layout manager
panel.repaint(); // to repaint the components

否则添加的组件大小为(0,0),因此无需绘制任何内容。按钮也是如此。它应该在框架可见之前添加,或者您也需要执行revalidate()/ repaint()。

在这种情况下,您还有第二个问题:

frame.add(panel, BorderLayout.CENTER);

首先将一个空面板添加到BorderLayout的CENTER,然后当您单击按钮时将球添加到CENTER。

Swing将绘制最后添加的最后一个组件。所以球被涂上颜色,然后空的面板被涂在上面。

摆脱面板,没有任何意义。

编辑:

出于某种原因,当您点击按钮时,我认为您将球添加到框架而不是面板。

如果您确实将Ball直接添加到框架中,我上面的解释是正确的。

但是,我的解释是不正确的,因为ActionListener中的代码确实将Ball添加到面板中。正确的解释如下。

当您将Ball添加到面板时,您不会看到Ball,因为默认情况下,JPanel使用FlowLayout,而FlowLayout会考虑添加到其中的任何组件的首选大小。您没有实现getPreferredSize()方法,因此大小为(0,0),因此无需绘制任何内容。

因此,如果您在Ball类中实现getPreferredSize()方法,则Ball将在面板上显示。此外,每次单击按钮时,您都可以显示新的球。

答案 1 :(得分:0)

当camickr回答时,您需要revalidate()(或同时调用invalidate()& validate(),两者都可以),然后repaint()小组。

invalidate方法将面板标记为“不正确”''基本上标记为检查。

Validate执行组件的布局。

Revalidate同时执行这两项操作,但验证是同步的,而revalidate则不是。

在您验证面板后,您需要调用重绘以重绘该面板。

作为旁注,JavaFX is replacing Swing/AWT,在我看来,更容易使用。你可能想看看它。 :)

在JavaFX中执行类似于您当前正在执行的操作的简短代码示例:

public class test extends Application{

Scene scene;

@Override
public void start(Stage primaryStage) throws Exception{

    StackPane root = new StackPane();
    root.setBackground(
            new Background(new BackgroundFill(Color.ALICEBLUE,null,null)));

    Button begin = new Button("Add Circle");
    begin.setOnAction((ActionEvent e)->{ 
        Circle c = new Circle(200,200,100,Color.RED);
        root.getChildren().add(c);
    });

    root.getChildren().add(begin);

    scene = new Scene(root, 700, 700);
    primaryStage.setScene(scene);
    primaryStage.show();

}


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