向面板添加绘图



这应该是足够简单,但我不能使它工作。

我有两个类,一个应该画一个圆圈,另一个设置一个框架和一个按钮面板。点击按钮后,框架上会出现一个圆圈。我很困惑为什么它没有出现。可能很简单,抱歉。

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

        }
}

当您向可见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的中心添加一个空面板,然后当你点击按钮时,你将球添加到中心。

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

去掉面板,它没有用。

编辑:

由于某些原因,当你点击按钮时,我以为你是在将球添加到框架中,而不是添加到面板中。

我上面的解释是正确的,如果你真的把球直接添加到框架中。

然而,我的解释是不正确的,因为你在ActionListener中的代码确实将球添加到面板。正确的解释如下。

当你将小球添加到面板时,你看不到小球,因为默认情况下JPanel使用FlowLayout,而FlowLayout尊重添加到它的任何组件的首选大小。你没有实现getPreferredSize()方法,所以尺寸是(0,0),所以没有什么可以绘制的。

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

如果camickr接听,您需要拨打revalidate()(或同时拨打invalidate() &validate(),两者都将工作),然后repaint()面板。

invalidate方法将面板标记为"不正确";基本上是标记供检查。

Validate执行组件的布局。

Revalidate两者都做,但是validate是同步的,而Revalidate不是。

验证面板后,需要调用repaint来重新绘制该面板。


作为旁注,JavaFX正在取代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);
}
}

最新更新