我尝试在paintComponent之后使用方法重绘,但它不起作用

时间:2016-04-29 10:53:42

标签: java paintcomponent repaint

首先它会再长一点,因为我想展示我迄今为止所做的所有代码,所以请原谅..

这是我第一次参加java。 我正在尝试建造一个用鱼和水母绘制和使用线程的水族馆。 当我尝试添加动物时我想画它但没有成功,我构建了PaintComponent方法但是当我尝试使用重绘时我无法绘制.. 我错过了什么?

看起来就是这样,当我点击Add Animal窗口打开时,我选择了值,然后点击OK后,需要绘制动物

enter image description here

我希望我所做的其余事情还可以。非常感谢你的帮助!

paintComponentrepaint位于AquaPanel等级。

public class AquaFrame extends JFrame {

    private AquaPanel mPanel;
    private JLabel label1;
    private ImageIcon icon;
    private BufferedImage imag;

    public AquaFrame() {
        super("my Aquarium");
        setLayout(new BorderLayout());
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(700, 600);
        setResizable(false);
        setVisible(true);
        setLocationRelativeTo(null);

        mPanel = new AquaPanel(getGraphics());
        add(mPanel);
    }

    public void buildFrame(){   
        JMenuBar menuBar = new JMenuBar();
        setJMenuBar(menuBar);

        JMenu file = new JMenu("File");
        menuBar.add(file);
        JMenuItem exItem = new JMenuItem("Exit");
        file.add(exItem);
        exItem.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                System.exit(0);
            }
        });

        JMenu background = new JMenu("Background");
        menuBar.add(background);
        JMenuItem blue = new JMenuItem("Blue");
        blue.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                mPanel.setBackground(Color.BLUE);
            }
        });

        JMenuItem none = new JMenuItem("None");
        none.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                mPanel.setBackground(null);
            }
        });

        JMenuItem image = new JMenuItem("Image");
        image.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {

                try {
                    imag = ImageIO.read(new File("aquarium_background.jpg"));
                } catch (IOException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }
            }
        });

        background.add(image);
        background.add(blue);
        background.add(none);

        JMenu help = new JMenu("Help");
        JMenuItem helpItem = new JMenuItem("help");
        helpItem.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                JOptionPane.showMessageDialog(null,"GUI @ Threads");
            }
        });

        menuBar.add(help);
        help.add(helpItem);

        setVisible(true);
    }

    public void paint(Graphics g){
        g.drawImage(imag, 0, 0, null);
    }

    public static void main(String[] args) {        
        AquaFrame mFrame = new AquaFrame();
        mFrame.buildFrame();
    }

}


/******************************************/
public class AquaPanel extends JPanel {

    private JFrame infoTableFrame;
    private JTable infoTable;
    private Set<Swimmable > swimmables = new HashSet<Swimmable>();
    private AddAnimalDialog animalDialog;
    private int totalEatCounter;
    private Graphics g;

    public AquaPanel(Graphics g) {
        this.g = g;
        totalEatCounter = 0;
        infoTableFrame = new JFrame();
        infoTableFrame.setVisible(false);

        setLayout(new GridBagLayout());

        GridBagConstraints constraints = new GridBagConstraints();
        constraints.anchor = GridBagConstraints.PAGE_END;
        constraints.weighty = 1;

        JButton btAdd = new JButton("Add Animal");
        btAdd.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                if (swimmables.size() >= 5)
                {
                    JOptionPane.showMessageDialog(null, "You can't have more than 5 animals at the same time.");
                }
                else
                {
                    animalDialog = new AddAnimalDialog(AquaPanel.this);
                    animalDialog.setVisible(true);
                }
            }
        });

        JButton btSleep = new JButton("Sleep");
        btSleep.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                for (Swimmable swimmable : swimmables)
                {
                    swimmable.setSuspend();
                }
            }
        });

        JButton btWakeup = new JButton("Wake Up");
        btWakeup.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                for (Swimmable swimmable : swimmables)
                {
                    swimmable.setResume();
                }
            }
        });

        JButton btRst = new JButton("Reset");
        btRst.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                for (Swimmable swimmable : swimmables)
                {
                    swimmable.kill();
                }
                swimmables.clear();
            }
        });

        JButton btFood = new JButton("Food");
        btFood.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                if (swimmables.size() > 0)
                {
                    CyclicBarrier barrier = new CyclicBarrier(swimmables.size());
                    for (Swimmable swimmable : swimmables)
                    {
                        swimmable.setBarrier(barrier);
                        swimmable.setFood(true);
                    }
                    Graphics2D g2 = (Graphics2D) g;
                    g2.setStroke(new BasicStroke(3));
                    g2.setColor(Color.red);
                    g2.drawArc(getWidth() / 2, getHeight() / 2 - 5, 10, 10, 30, 210);
                    g2.drawArc(getWidth()/2, getHeight()/2+5, 10, 10, 180, 270);
                    g2.setStroke(new BasicStroke(1));
                }
            }
        });

        JButton btInfo = new JButton("Info");
        btInfo.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                    showInfoTable();
            }
        });

        JButton btExit = new JButton("Exit");
        btExit.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                System.exit(0);
            }
        });

        add(btAdd,constraints);
        add(btSleep,constraints);
        add(btWakeup,constraints);
        add(btRst,constraints);
        add(btFood,constraints);
        add(btInfo,constraints);
        add(btExit,constraints);
    }

    public void showInfoTable(){
        if (infoTableFrame.isVisible())
        {
            infoTableFrame.remove(infoTable);
            infoTableFrame.setVisible(false);
        }
        else
        {
            String[] col = {"Animal","Color","Size","Hor.speed","Ver.speed","Eat counter"};
            String[][] data = new String[swimmables.size()][col.length];
            int i=0;
            for (Swimmable swimmable : swimmables)
            {
                data[i][0] = swimmable.getAnimalName();
                data[i][1] = swimmable.getColor();
                data[i][2] = "" + swimmable.getSize();
                data[i][3] = "" + swimmable.getHorSpeed();
                data[i][4] = "" + swimmable.getVerSpeed();
                data[i][5] = "" + swimmable.getEatCount();
                ++i;
            }
            infoTable = new JTable(data, col);

            //TODO - not overriding values

            JScrollPane jPane = new JScrollPane(infoTable);
            infoTableFrame.add(jPane, BorderLayout.CENTER);
            infoTableFrame.setSize(300, 150);
            infoTableFrame.setVisible(true);
        }
    }

    public void addAnimal(Swimmable animal)
    {
        animal.setAquaPanel(this);
        swimmables.add(animal);
        animal.run();
        //myrepaint();
    /**********************************/    
        repaint();
    /**********************************/
    }


    public void onEatFood(Swimmable eater)
    {
        eater.eatInc();
        ++totalEatCounter;
        for (Swimmable swimmable : swimmables)
        {
            swimmable.setFood(false);
        }
    }

    /*public void myrepaint()
    {
        for (Swimmable swimmable : swimmables)
        {
            swimmable.drawAnimal(g);
        }
    }*/

    /************************************************/
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        for (Swimmable swimmable : swimmables)
        {
            swimmable.drawAnimal(g);
        }
    }
    /*********************************************/
}



public abstract class Swimmable extends Thread {

    protected AquaPanel aquaPanel;
    protected boolean isFood;
    protected boolean isSuspended;
    protected int horSpeed;
    protected int verSpeed;
    protected int x_dir, y_dir;
    protected int eatCount;
    protected CyclicBarrier barrier;
    protected int x0, y0;

    protected boolean isAlive;

    public Swimmable() {
        horSpeed = 0;
        verSpeed = 0;
        x_dir = 1;
        y_dir = 1;
        eatCount = 0;
    }

    public Swimmable(int hor, int ver) {
        horSpeed = hor;
        verSpeed = ver;
        x_dir = 1;
        y_dir = 1;
        eatCount = 0;
    }

    @Override
    public void run() {
        isAlive = true;
        while (isAlive) {
            try {
                sleep(10);
                if (isSuspended)
                {
                    wait();
                }
                else
                {
                    if (isFood)
                    {
                        barrier.await();
                        updateFrontsTowardsFood();
                        if (isNearFood())
                        {
                            aquaPanel.onEatFood(this);
                        }
                    }
                    else
                    {
                        updateFronts();
                    }
                    //aquaPanel.myrepaint();
                    aquaPanel.repaint();
                }
            }
            catch (Exception e)
            {
                //TODO - handle exception
            }

        }
    }

    public void kill()
    {
        isAlive = false;
    }

    public int getHorSpeed() {
        return horSpeed;
    }

    public int getVerSpeed() {
        return verSpeed;
    }

    public void setHorSpeed(int hor) {
        horSpeed = hor;
    }

    public void setVerSpeed(int ver) {
        verSpeed = ver;
    }

    abstract public int getSize();

    abstract public String getColor();

    public void setSuspend()
    {
        isSuspended = true;
    }

    public void setResume()
    {
        isSuspended = false;
    }

    public void eatInc()
    {
        ++eatCount;
    }

    public int getEatCount()
    {
        return eatCount;
    }

    public void setBarrier(CyclicBarrier b)
    {
        barrier = b;
    }

    public void setFood(boolean isFood)
    {
        this.isFood = isFood;
    }

    public void setAquaPanel(AquaPanel panel)
    {
        aquaPanel = panel;
        x0 = aquaPanel.getWidth() / 2;
        y0 = aquaPanel.getHeight() / 2;
    }

    abstract public String getAnimalName();

    abstract public void drawAnimal(Graphics g);

    abstract protected void updateFronts();
    abstract protected void updateFrontsTowardsFood();

    abstract protected boolean isNearFood();
}



public class Fish extends Swimmable {

    protected int x_front , y_front;
    private int size;
    private Color color;

    public Fish(Color col, int sz, int hor, int ver) {
        super(hor, ver);
        size = sz;
        color = col;
        x_front = 0;
        y_front = 0;
    }

    public void drawAnimal(Graphics g) {

        g.setColor(color);
        if (x_dir == 1) // fish swims to right side
        {
            // Body of fish
            g.fillOval(x_front - size, y_front - size / 4, size, size / 2);

            // Tail of fish
            int[] x_t = { x_front - size - size / 4, x_front - size - size / 4, x_front - size };
            int[] y_t = { y_front - size / 4, y_front + size / 4, y_front };
            Polygon t = new Polygon(x_t, y_t, 3);
            g.fillPolygon(t);

            // Eye of fish
            Graphics2D g2 = (Graphics2D) g;
            g2.setColor(new Color(255 - color.getRed(),255 - color.getGreen(),255- color .getBlue()));
            g2.fillOval(x_front-size/5, y_front-size/10, size/10, size/10);

            //Mouth of fish
            if(size>70)
                g2.setStroke(new BasicStroke(3));
            else if(size>30)
                g2.setStroke(new BasicStroke(2));
            else
                g2.setStroke(new BasicStroke(1));

            g2.drawLine(x_front, y_front, x_front-size/10, y_front+size/10);
            g2.setStroke(new BasicStroke(1));
        }

        else // fish swims to left side
        {
            // Body of fish
            g.fillOval(x_front, y_front - size / 4, size, size / 2);

            // Tail of fish
            int[] x_t = { x_front + size + size / 4, x_front + size + size / 4, x_front + size };
            int[] y_t = { y_front - size / 4, y_front + size / 4, y_front };
            Polygon t = new Polygon(x_t, y_t, 3);
            g.fillPolygon(t);

            // Eye of fish
            Graphics2D g2 = (Graphics2D) g;
            g2.setColor(new Color(255 - color.getRed(), 255 - color.getGreen(), 255 - color.getBlue()));
            g2.fillOval(x_front+size/10, y_front-size/10, size/10, size/10);

            // Mouth of fish
            if (size > 70)
                g2.setStroke(new BasicStroke(3));
            else if (size > 30)
                g2.setStroke(new BasicStroke(2));
            else
                g2.setStroke(new BasicStroke(1));
            g2.drawLine(x_front, y_front, x_front + size / 10, y_front + size / 10);
            g2.setStroke(new BasicStroke(1));
        }

    }

    public String getAnimalName() {
        return "Fish";
    }

    public int getSize() {
        return size;
    }

    public String getColor() {
        if (color == Color.RED)
            return "RED";
        else if (color == Color.GREEN)
            return "GREEN";
        else if (color == Color.ORANGE)
            return "ORANGE";
        else
            return "UNKNOWN";
    }

    protected void updateFronts()
    {
        x_front += x_dir * horSpeed;
        y_front += y_dir * verSpeed;
        if (x_front > x0*2 || x_front < 0)
            x_dir *= -1;
        if (y_front > y0*2 || y_front < 0)
            y_dir *= -1;
    }

    protected void updateFrontsTowardsFood()
    {
        //TODO - copy from word
    }

    protected boolean isNearFood()
    {
        return ((Math.abs(x_front-x0) <= 5) && (Math.abs(y_front-y0) <= 5));
    }

}



public class Jellyfish extends Swimmable {

    private int x_front , y_front;
    private int size;
    private Color color;

    public Jellyfish(Color col, int sz, int hor, int ver) {
        super(hor, ver);
        size = sz;
        color = col;
        x_front = 0;
        y_front = 0;
    }

    public void drawAnimal(Graphics g) {
        int numLegs;
        if (size < 40)
            numLegs = 5;
        else if (size < 80)
            numLegs = 9;
        else
            numLegs = 12;
        g.setColor(color);
        g.fillArc(x_front - size / 2, y_front - size / 4, size, size / 2, 0, 180);
        for (int i = 0; i < numLegs; i++)
            g.drawLine(x_front - size / 2 + size / numLegs + size * i / (numLegs + 1), y_front,
                    x_front - size / 2 + size / numLegs + size * i / (numLegs + 1), y_front + size / 3);
    }


    public String getAnimalName() {
        return "Jellyfish";
    }

    public int getSize() {
        return size;
    }

    public String getColor() {
        if (color == Color.RED)
            return "RED";
        else if (color == Color.GREEN)
            return "GREEN";
        else if (color == Color.ORANGE)
            return "ORANGE";
        else
            return "UNKNOWN";
    }

    public void updateFronts()
    {
        x_front += x_dir * horSpeed;
        y_front += y_dir * verSpeed;
        if (x_front > x0*2 || x_front < 0)
            x_dir *= -1;
        if (y_front > y0*2 || y_front < 0)
            y_dir *= -1;
    }

    protected void updateFrontsTowardsFood()
    {
        //TODO - copy from word
    }

    protected boolean isNearFood()
    {
        return ((Math.abs(x_front-x0) <= 5) && (Math.abs(y_front-y0) <= 5));
    }
}



public class AddAnimalDialog extends JDialog {

    private JButton btOk, btCancel;
    private JTextField tfSize, tfHspeed, tfVspeed;
    private ButtonGroup groupType, groupColor;
    private JRadioButton rbFish, rbJellyfish, rbRed, rbGreen, rbOrange;
    JPanel panel;

    public AddAnimalDialog(AquaPanel aquaPanel) {
        this.setLayout(new FlowLayout());
        panel = new JPanel();
        panel.setLayout(new GridLayout(10, 20));
        panel.add(new JLabel("Size(20-320): "));
        panel.add(tfSize = new JTextField());
        panel.add(new JLabel("Horizontal speed(1-10): "));
        panel.add(tfHspeed = new JTextField());
        panel.add(new JLabel("Vertical speed(1-10): "));
        panel.add(tfVspeed = new JTextField());
        panel.add(new JLabel("Type: "));
        panel.add(new JLabel("                     "));
        panel.add(rbFish = new JRadioButton("fish"));
        panel.add(rbJellyfish = new JRadioButton("jellyfish"));
        panel.add(new JLabel("Color: "));
        panel.add(new JLabel("                     "));
        panel.add(rbRed = new JRadioButton("Red"));
        panel.add(rbGreen = new JRadioButton("Green"));
        panel.add(rbOrange = new JRadioButton("Orange"));

        // Group the radio buttons.
        groupType = new ButtonGroup();
        groupType.add(rbFish);
        groupType.add(rbJellyfish);
        rbFish.setSelected(true);
        groupColor = new ButtonGroup();
        groupColor.add(rbRed);
        groupColor.add(rbGreen);
        groupColor.add(rbOrange);
        rbRed.setSelected(true);
        panel.add(new JLabel(""));
        panel.add(btOk = new JButton("OK"));
        panel.add(btCancel = new JButton("Cancel"));
        this.add(panel);
        this.setLocationRelativeTo(null);
        this.setResizable(false);
        this.pack();

        this.btOk.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                try {
                    int size = Integer.parseInt(tfSize.getText());
                    int hSpeed = Integer.parseInt(tfHspeed.getText());
                    int vSpeed = Integer.parseInt(tfVspeed.getText());

                    if (checkValues(size, hSpeed, vSpeed)) {
                        Color clr = Color.RED;
                        if (rbRed.isSelected()) {
                            clr = Color.RED;
                        } else if (rbGreen.isSelected()) {
                            clr = Color.GREEN;
                        } else if (rbOrange.isSelected()) {
                            clr = Color.ORANGE;
                        } else {
                            JOptionPane.showMessageDialog(null, "You must choose a color!");
                        }

                        if (rbFish.isSelected()) {
                            setVisible(false);
                            aquaPanel.addAnimal(new Fish(clr, size, hSpeed, vSpeed));
                        } else if (rbJellyfish.isSelected()) {
                            setVisible(false);
                            aquaPanel.addAnimal(new Jellyfish(clr, size, hSpeed, vSpeed));
                        } else {
                            JOptionPane.showMessageDialog(null, "You must choose animal type!");
                        }
                    }
                } catch (NumberFormatException e) {
                    JOptionPane.showMessageDialog(null, "One of the number values has wrong format, please check it");
                }
            }
        });
        this.btCancel.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                setVisible(false);
                System.out.println("Click the Close button if you want to stop adding windows");
            }
        });
    }

    private boolean checkValues(int size, int hspeed, int vspeed) {
        if ((size > 320 || size < 20) || (hspeed < 1 || hspeed > 10) || (vspeed < 1 || vspeed > 10)) {
            JOptionPane.showMessageDialog(null, "One of the values is out of bounds, please follow the restrictions.");
            return false;
        }
        return true;
    }

}

2 个答案:

答案 0 :(得分:1)

有许多基本问题......

主要问题在于您的Swimmable run方法,它阻止了事件调度线程,阻止它能够响应UI事件,包括重绘事件。有关详细信息,请参阅Concurrency in Java

你永远不应该使用getGraphics,除了能够返回null之外,你绘制的任何东西都是在正常的绘画周期之外绘制的,并且会在下次重新绘制组件时绘制。有关详细信息,请参阅Painting in AWT and SwingPerforming Custom Painting

您当前的方法不会很好地扩展,您添加的鱼越多,它们消耗的资源就越多,并且会影响程序跟上所有不同更改和重新绘制请求的能力。

更好的解决方案是进行单一的更新&#34;循环,它负责告诉每个Swimmable它需要更新,然后在每个循环中安排一个repaint。就个人而言,我从一个Swing Timer开始,因为它&#34;滴答&#34;在EDT中,使得修改paintComponent方法所需的对象状态更加安全。

有关详细信息,请参阅How to use Swing Timers

我建议您查看this,其中基本上描述了您尝试做的事情以及我建议您应该做的事情

答案 1 :(得分:0)

在调用addAnimal方法后尝试在JFrame类中调用repaint。这里也有revalidate()方法,它们的区别在于本文:Java Swing revalidate() vs repaint()