这应该很简单,但我无法使其发挥作用。
我有两个类,一个应绘制圆形,另一个用按钮设置框架和面板。单击该按钮时,框架上将出现一个圆圈。我很困惑为什么它没有出现。这可能是非常简单的事,抱歉。
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);
}
}
答案 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);
}
}