Java 将图形添加到面板

Java 将图形添加到面板,java,jpanel,graphics2d,Java,Jpanel,Graphics2d,这应该足够简单,但我不能让它工作 我有两个类,一个应该画一个圆,另一个设置一个框架和一个按钮面板。单击按钮时,框架上会出现一个圆圈。我不明白为什么它没有出现。很可能很简单,对不起 package ballsOnPane; import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import

这应该足够简单,但我不能让它工作

我有两个类,一个应该画一个圆,另一个设置一个框架和一个按钮面板。单击按钮时,框架上会出现一个圆圈。我不明白为什么它没有出现。很可能很简单,对不起

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),因此没有任何可绘制的内容


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

正如camickr回答的那样,您需要
重新验证()
(或者调用这两个
无效()
验证()
,两者都可以工作),然后
重新绘制()
面板

失效方法将面板标记为“不正确”;基本上是做标记检查

验证执行组件的布局

重新验证日期同时执行这两项操作,但是,验证是同步的,而重新验证日期不是同步的

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


作为旁注,在我看来,它更容易使用。你可能想调查一下。:)

一个简短的代码示例,用于在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);
}
}

你至少看不到其中一个圆圈吗?不,我制作了其他类似的程序,在这些程序中我成功地在面板上获取了图像,并且我尝试了使用相同的格式,但没有显示任何内容。LuxxMiner也谢谢你,这有助于:)谢谢!现在这很有道理。并修复了许多其他与Java相关的问题)不,不,不。。。保留面板。你真的不应该在画框上画画。代码是正确的-它将球添加到面板,而不是框架。但球没有指定首选大小,因此默认为零。此外,所有这些都没有在事件线程上执行,因此GUI不会正确显示。@FredK,在我的建议中,他不会将
Ball
面板添加到框架的内容窗格中,这非常好。框架的内容窗格是一个JPanel,不需要创建第二个面板。@Ash,正如FredK指出的那样,Ball类不会覆盖
getPreferredSize()
方法,只会显示,因为您使用的是BorderLayout。要正确绘制,请阅读上Swing教程中的部分,以获得更好的工作示例。