尝试从 GUI 绘制烟花时出现问题

Issue when attempting to draw fireworks from GUI

我有两个 classes,一个叫用户界面,另一个叫 Canvas 我需要用户能够输入速度、角度和时间的值才能渲染烟花上了Canvas。但是,当我使用按钮触发获取 JTextFields 值的内容时,Canvas 不会重新绘制 ()。无论我输入什么值都不会发生 我在另一个 class 中定义了 x 和 y,但是 getter 和 setter 不会产生任何值。

为什么我调用repaint()时我的形状没有画在Canvase上?

public class Userinterface extends JPanel implements ActionListener{

    private static final long serialVersionUID = 1L;
    private static String str= "0";
    private static String str2= "0";
    private static String str3= "0";
    private JTextField angle= new JTextField(5);
    private JLabel alabel= new JLabel("Angle");
    private JTextField velocity= new JTextField(5);
    private JLabel vlabel= new JLabel("Velocity");
    private JButton Actionbutton= new JButton("launch");
    private JTextField time= new JTextField(5);
    private JLabel tlabel= new JLabel ("Time of fuse (s)");
    static int a;
    static int b;
    static int c;
    static int x;
    static int y;

    Userinterface(){
        setLayout(new FlowLayout(FlowLayout.CENTER));
        add(time);
        add(tlabel);
        add (angle);
        add(alabel);
        add (velocity);
        add(vlabel);
        add(Actionbutton);
        Actionbutton.addActionListener(this);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getSource()==Actionbutton) {
        str=angle.getText();
        str2=velocity.getText();
        str3=time.getText();
        a=Integer.parseInt(str);
        b=Integer.parseInt(str2);
        c=Integer.parseInt(str3);
        repaint();  // ISSUE: Canvas does not repaint here
    }   
}

public static int findx() {
    x=Fire_WorkMath.calculatex(b, c, a);
    return x;
}

public static int findy() {
    y=Fire_WorkMath.calculatey(b, c, a);
    return y;
}

public class Canvas extends JPanel {

    Userinterface one= new Userinterface();
    int ang;
    int time;
    int y;
    int x;

    private static final long serialVersionUID = 1L;

    public Canvas() {

    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        x=Userinterface.findx();
        y=Userinterface.findy();
        g.drawLine(0, 0, x, y);
    }
}

对象之间的共享状态有时会很复杂。在最基本的层面上,您要做的是将它们所依赖的对象的同一个实例传递给它们。

在此,您需要设置一个 "model" 可以在两个 classes 之间共享...

public class FireworkModel {

    private int angle;
    private int velocity;
    private int time;

    private List<ChangeListener> changeListeners;

    public FireworkModel() {
        changeListeners = new ArrayList<>();
    }

    public void addChangeListener(ChangeListener listener) {
        changeListeners.add(listener);
    }

    public void removeChangeListener(ChangeListener listener) {
        changeListeners.remove(listener);
    }

    protected void fireStateChanged() {
        ChangeEvent evt = new ChangeEvent(this);
        for (ChangeListener listener : changeListeners) {
            listener.stateChanged(evt);
        }
    }

    public void setAngle(int angle) {
        this.angle = angle;
        fireStateChanged();
    }

    public void setVelocity(int velocity) {
        this.velocity = velocity;
        fireStateChanged();
    }

    public void setTime(int time) {
        this.time = time;
        fireStateChanged();
    }

    public int getAngle() {
        return angle;
    }

    public int getVelocity() {
        return velocity;
    }

    public int getTime() {
        return time;
    }

    public int findx() {
        return Fire_WorkMath.calculatex(getVelocity(), getTime(), getAngle());
    }

    public int findy() {
        return Fire_WorkMath.calculatey(getVelocity(), getTime(), getAngle());
    }

}

现在,因为在您的示例中,UserInterfaceCanvas class 实际上都没有直接相互交谈,模型设置了一个 "observer pattern",它用于通知相关方模型的状态已经改变。

您还会注意到 findx/y 方法也已移至此处,这样需要它们的各方就可以轻松访问它们。

接下来,我们更改 Canvas(我已将其重命名为 FireworksPane,因为 SDK 中有 Canvas class)以利用此型号...

public class FireworksPane extends JPanel {

    private FireworkModel model;

    private static final long serialVersionUID = 1L;

    public FireworksPane(FireworkModel model) {
        this.model = model;
        model.addChangeListener(new ChangeListener() {
            @Override
            public void stateChanged(ChangeEvent e) {
                repaint();
            }
        });
    }

    public FireworkModel getModel() {
        return model;
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        int x = getModel().findx();
        int y = getModel().findy();
        g.drawLine(0, 0, x, y);
    }
}

最后,我们更新 UserInterface 以也使用模型...

public class Userinterface extends JPanel implements ActionListener {

    private final long serialVersionUID = 1L;
    private JTextField angle = new JTextField(5);
    private JLabel alabel = new JLabel("Angle");
    private JTextField velocity = new JTextField(5);
    private JLabel vlabel = new JLabel("Velocity");
    private JButton Actionbutton = new JButton("launch");
    private JTextField time = new JTextField(5);
    private JLabel tlabel = new JLabel("Time of fuse (s)");

    private FireworkModel model;

    Userinterface(FireworkModel model) {
        setLayout(new FlowLayout(FlowLayout.CENTER));
        add(time);
        add(tlabel);
        add(angle);
        add(alabel);
        add(velocity);
        add(vlabel);
        add(Actionbutton);
        Actionbutton.addActionListener(this);
        this.model = model;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == Actionbutton) {
            String str = angle.getText();
            String str2 = velocity.getText();
            String str3 = time.getText();
            int angle = Integer.parseInt(str);
            int velocity = Integer.parseInt(str2);
            int time = Integer.parseInt(str3);

            model.setAngle(angle);
            model.setVelocity(velocity);
            model.setTime(time);
        }
    }
}

两个 classes 都需要传递给它们的模型的相同实例,如果您希望它起作用...

FireworkModel model = new FireworkModel();
Userinterface userinterface = new Userinterface(model);
FireworksPane fireworksPane = new FireworksPane(model);
// Setup the remaining UI