Java 使用旧实例绘制组件

Java 使用旧实例绘制组件,java,swing,Java,Swing,我正在使用swing用java制作掷骰子程序。我有四节课: 死 鬼脸 public class DieFace { private int spotDiam,wOffset,hOffset,w,h; public int faceValue; public DieFace(){ Die die = new Die(); this.faceValue = die.getValue(); } public void draw(Graphics g, int paneWidth,

我正在使用swing用java制作掷骰子程序。我有四节课:

鬼脸

public class DieFace {
private int spotDiam,wOffset,hOffset,w,h;
public int faceValue;

public DieFace(){
    Die die = new Die();
    this.faceValue = die.getValue();
}

public void draw(Graphics g, int paneWidth, int paneHeight){
    //draw information
}
}
模具组件

public class DieFaceComponent extends JComponent{
private static final long serialVersionUID = 1L;

DieFace face; 

public DieFaceComponent(){
    face = new DieFace();
    System.out.println("DIEFACE" + face.faceValue);
    repaint();
}

public void paintComponent(Graphics g){
    revalidate();
    face.draw(g,super.getWidth(),super.getHeight());  

}
}
DieFaceViewer

public class DieFaceViewer{

static DieFaceComponent component;
static JFrame frame = new JFrame(); // Create a new JFrame object

public static void main(String[] args){
    final int FRAME_WIDTH = 500;
    final int FRAME_HEIGHT = 500;
    frame.setSize(FRAME_WIDTH, FRAME_HEIGHT); // Set initial size 
    frame.setTitle("Dice Simulator Version 1.0"); // Set title
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // Set default close operation
    component = new DieFaceComponent(); // Create a new DieFaceComponent object
    frame.setLayout(new BorderLayout());
    JButton btnRoll = new JButton("Roll!");
    btnRoll.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            component = new DieFaceComponent();
        }
    });

    frame.add(component, BorderLayout.CENTER); // Add DieFaceComponent object to frame
    frame.add(btnRoll, BorderLayout.SOUTH);
    frame.setVisible(true); // Set frame to visible
}
}

我的问题是,即使每次按下btnRoll键时都会创建一个新的Die、DieFace和DieFaceComponent对象,但用于绘制组件的值仍与初始实例相同。我做错什么了吗?提前感谢

您在
ActionListener
中创建了一个新的
DieFaceComponent
实例,但不使用它,它从未添加到任何内容中,因此它永远不可见。更好的解决方案将允许您触发对
DieFaceComponent
的更改,这将触发对
DieFace
的更改,这将触发对
Die
的更改,并使整个过程只需
重新绘制
本身,例如

public class Die {

    private int faceValue;

    public Die() {
        System.out.println("Creating new Dice Object");
        //setValue(roll());
        roll(); // Roll sets the value any way :P
    }

    public int roll() {
        int val = (int) (6 * Math.random() + 1);
        setValue(val);
        return val;
    }

    public int getValue() {
        return faceValue;
    }

    public void setValue(int spots) {
        faceValue = spots;
    }
}

public class DieFace {

    private int spotDiam, wOffset, hOffset, w, h;
    //public int faceValue;
    private Die die;

    public DieFace() {
        die = new Die();
        //Die die = new Die();
        // This is pointless, as you should simply as die for it's value
        // when ever you need it...
        //this.faceValue = die.getValue();
    }

    public void roll() {
        die.roll();
    }

    public void draw(Graphics g, int paneWidth, int paneHeight) {
        //draw information
    }
}

public class DieFaceComponent extends JComponent {

    private static final long serialVersionUID = 1L;

    DieFace face;

    public DieFaceComponent() {
        face = new DieFace();
        //System.out.println("DIEFACE" + face.faceValue);
        // Pointless, as you've probably not actually been added to anything
        // that could actuallyt paint you anyway...
        //repaint();
    }

    public void roll() {
        face.roll();
        repaint();
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        //revalidate();
        face.draw(g, super.getWidth(), super.getHeight());

    }
}
现在,您可以在
DieFace组件上调用
roll
,该组件将在
DieFace
上调用
roll
,该组件将在
Die
上调用
roll
,从而更新实际值
DieFaceComponent
随后将安排一次
repaint
以确保其在屏幕上更新

然后你可以用它,比如

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class DiceRoller {

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

    public DiceRoller() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new DiePane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class DiePane extends JPanel {

        public DiePane() {
            setLayout(new BorderLayout());

            DieFaceComponent component = new DieFaceComponent();
            JButton roll = new JButton("Roll");
            roll.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    component.roll();
                }
            });
            add(component);
            add(roll, BorderLayout.SOUTH);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

    }

}
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class DiceRoller {

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

    public DiceRoller() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new DiePane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class DiePane extends JPanel {

        public DiePane() {
            setLayout(new BorderLayout());

            Die die = new Die();
            DieFaceComponent component = new DieFaceComponent(die);
            JButton roll = new JButton("Roll");
            roll.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    die.roll();
                }
            });
            add(component);
            add(roll, BorderLayout.SOUTH);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.dispose();
        }

    }

    public class Die {

        private PropertyChangeSupport propertyChangeSupport;
        private int faceValue;

        public Die() {
            propertyChangeSupport = new PropertyChangeSupport(this);
            System.out.println("Creating new Dice Object");
            //setValue(roll());
            roll(); // Roll sets the value any way :P
        }

        public int roll() {
            int val = (int) (6 * Math.random() + 1);
            setValue(val);
            return val;
        }

        public int getValue() {
            return faceValue;
        }

        public void setValue(int spots) {
            int old = faceValue;
            faceValue = spots;
            propertyChangeSupport.firePropertyChange("value", old, faceValue);
        }

        public void addPropertyChangeListener(PropertyChangeListener listener) {
            propertyChangeSupport.addPropertyChangeListener(listener);
        }

        public void removePropertyChangeListener(PropertyChangeListener listener) {
            propertyChangeSupport.addPropertyChangeListener(listener);
        }
    }

    public class DieFace {

        private int spotDiam, wOffset, hOffset, w, h;
        private Die die;

        public DieFace(Die die) {
            this.die = die
        }

        public void draw(Graphics g, int paneWidth, int paneHeight) {
            //draw information
        }
    }

    public class DieFaceComponent extends JComponent {

        private static final long serialVersionUID = 1L;

        private DieFace face;

        public DieFaceComponent(Die die) {
            face = new DieFace(die);
            die.addPropertyChangeListener(new PropertyChangeListener() {
                @Override
                public void propertyChange(PropertyChangeEvent evt) {
                    repaint();
                }
            });
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            //revalidate();
            face.draw(g, super.getWidth(), super.getHeight());

        }
    }

}
现在,一个更好的解决方案是将
Die
作为您的主要入口点,允许它向感兴趣的各方生成通知,并让他们自己更新

也许像

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class DiceRoller {

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

    public DiceRoller() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new DiePane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class DiePane extends JPanel {

        public DiePane() {
            setLayout(new BorderLayout());

            DieFaceComponent component = new DieFaceComponent();
            JButton roll = new JButton("Roll");
            roll.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    component.roll();
                }
            });
            add(component);
            add(roll, BorderLayout.SOUTH);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

    }

}
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class DiceRoller {

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

    public DiceRoller() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new DiePane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class DiePane extends JPanel {

        public DiePane() {
            setLayout(new BorderLayout());

            Die die = new Die();
            DieFaceComponent component = new DieFaceComponent(die);
            JButton roll = new JButton("Roll");
            roll.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    die.roll();
                }
            });
            add(component);
            add(roll, BorderLayout.SOUTH);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.dispose();
        }

    }

    public class Die {

        private PropertyChangeSupport propertyChangeSupport;
        private int faceValue;

        public Die() {
            propertyChangeSupport = new PropertyChangeSupport(this);
            System.out.println("Creating new Dice Object");
            //setValue(roll());
            roll(); // Roll sets the value any way :P
        }

        public int roll() {
            int val = (int) (6 * Math.random() + 1);
            setValue(val);
            return val;
        }

        public int getValue() {
            return faceValue;
        }

        public void setValue(int spots) {
            int old = faceValue;
            faceValue = spots;
            propertyChangeSupport.firePropertyChange("value", old, faceValue);
        }

        public void addPropertyChangeListener(PropertyChangeListener listener) {
            propertyChangeSupport.addPropertyChangeListener(listener);
        }

        public void removePropertyChangeListener(PropertyChangeListener listener) {
            propertyChangeSupport.addPropertyChangeListener(listener);
        }
    }

    public class DieFace {

        private int spotDiam, wOffset, hOffset, w, h;
        private Die die;

        public DieFace(Die die) {
            this.die = die
        }

        public void draw(Graphics g, int paneWidth, int paneHeight) {
            //draw information
        }
    }

    public class DieFaceComponent extends JComponent {

        private static final long serialVersionUID = 1L;

        private DieFace face;

        public DieFaceComponent(Die die) {
            face = new DieFace(die);
            die.addPropertyChangeListener(new PropertyChangeListener() {
                @Override
                public void propertyChange(PropertyChangeEvent evt) {
                    repaint();
                }
            });
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            //revalidate();
            face.draw(g, super.getWidth(), super.getHeight());

        }
    }

}

这是一个简单的例子,其中,
Die
是信息的产生器,其他人都想知道信息何时发生变化。它也是模型-视图-控制器范例的一种变体

paintComponent
方法中不要调用
revalidate
,此外,您还应该调用
super.paintComponent
,然后在
ActionListener
中创建
DieFaceComponent
的新实例,但不使用它,它从未添加到任何内容中,因此永远不可见。一个更好的解决方案将允许您触发对
DieFaceComponent
的更改,这将触发对
DieFace
的更改,这将触发对
Die
的更改,并让整个过程只需
repaint
本身,感谢您的精彩帖子,这是作业的一部分,因此不幸的是,我必须坚持我被允许的类:/I我实现了您的第一个解决方案,但当我调用component.roll()时;,骰子的面值不会改变至少你可以建议一个更好的设计我会的,最大的问题是必须坚持过时的swing实现