如何使用单击按钮删除和替换JPanel?

时间:2014-12-31 20:17:26

标签: java multithreading swing

我对Java Concurrency相对较新,这是我第一次具有这种性质的应用程序。

我一直在尝试添加一个名为Panel of Dice的自定义JPanel,当按钮按下" Throw"时,它会显示随机生成的5个骰子面。点击。我正在使用两个SwingWorker Threads HumanPlayer和SystemPlayer来更新自己的抛出并使用上面的面板在JFrame上显示结果。

但预期的小组替换不能按预期工作。以下是一个不完整的Throw按钮ActionListener实现。有人可以指出我的代码问题吗?

this.throwButton = new JButton("Throw");
        this.throwButton.addActionListener(

                new ActionListener() {

                    @Override
                    public void actionPerformed(ActionEvent event) {

                        int throwNumber = throwCount % 3;

                        if(throwNumber == 1 || throwNumber == 2) {
                            int response = JOptionPane.showConfirmDialog(null, "Do you want to reroll?");

                            if(response == 0) {
                                int number = Integer.parseInt(JOptionPane.showInputDialog("How many dice do you want throw?"));

                                if(number > 0 && number < 6) {
                                    container.remove(panel);
                                    container.remove(systemPanel);
                                    HumanPlayerCalculator human = new HumanPlayerCalculator(container, humanPlayer, game, currentScore, throwNumber, number, scoreButton);
                                    human.execute();
                                    throwCount++;
                                }
                                else {
                                    JOptionPane.showMessageDialog(null, "Invalid number entry.", "Input Error", JOptionPane.ERROR_MESSAGE);
                                }
                            }
                            else if(response == 1) {
                                if(throwNumber == 1) {
                                    humanPlayer.addScore(currentScore.getMandatoryThrow());
                                    throwCount += 2;
                                }
                                else if(throwNumber == 2) {
                                    humanPlayer.addScore(currentScore.getRerolls()[0]);
                                    throwCount += 1;
                                }
                                scoreButton.setEnabled(false);
                                newGameButton.setEnabled(true);
                            }
                            else {
                                //Do nothing
                            }
                        }
                        else {
                            container.remove(panel);
                            container.remove(systemPanel);
                            currentScore = new Score();
                            HumanPlayerCalculator human = new HumanPlayerCalculator(container, humanPlayer, game, currentScore, throwNumber, 5, scoreButton);
                            human.execute();
                            scoreButton.setEnabled(true);
                            systemScore = new Score();
                            SystemPlayerCalculator systemCalculator = new SystemPlayerCalculator(container, game.getSystemPlayer(), game, systemScore, throwNumber, 5);
                            systemCalculator.execute();
                            throwCount++;
                        }

                    }

                }

            );

PlayerCalculator.java

package ac.lk.iit.coursework2;

import java.awt.Container;
import java.io.Serializable;

import javax.swing.SwingWorker;

public abstract class PlayerCalculator extends SwingWorker<Throw, Object> implements Serializable {

    private Player player;
    private Game game;
    private Container container;
    private Score score;
    private int throwCount;
    private int diceCount;

    public PlayerCalculator() {

    }

    public PlayerCalculator(Player player, Game game, Container container, Score score, int count, int diceCount) {
        this.setPlayer(player);
        this.setGame(game);
        this.setContainer(container);
        this.setScore(score);
        this.setThrowCount(count);
        this.setDiceCount(diceCount);
    }

    public Player getPlayer() {
        return player;
    }

    public void setPlayer(Player player) {
        this.player = player;
    }

    public Game getGame() {
        return game;
    }

    public void setGame(Game game) {
        this.game = game;
    }

    public Container getContainer() {
        return container;
    }

    public void setContainer(Container container) {
        this.container = container;
    }

    public Score getScore() {
        return score;
    }

    public void setScore(Score score) {
        this.score = score;
    }

    public int getThrowCount() {
        return throwCount;
    }

    public void setThrowCount(int throwCount) {
        this.throwCount = throwCount;
    }

    public int getDiceCount() {
        return diceCount;
    }

    public void setDiceCount(int diceCount) {
        this.diceCount = diceCount;
    }

}

HumanPlayerCalculator.java类

package ac.lk.iit.coursework2;

import java.awt.BorderLayout;
import java.awt.Container;
import java.util.ArrayList;
import java.util.concurrent.ExecutionException;

import javax.swing.JButton;
import javax.swing.JOptionPane;

public class HumanPlayerCalculator extends PlayerCalculator {

    private JButton button;

    public HumanPlayerCalculator() {
        super();
    }

    public HumanPlayerCalculator(Container container, HumanPlayer player, Game game, Score score, int throwCount, int count, JButton button) {
        super(player, game, container, score, throwCount, count);
        this.setDiceCount(count);
        this.setThrowButton(button);
    }

    public JButton getThrowButton() {
        return button;
    }

    public void setThrowButton(JButton throwButton) {
        this.button = throwButton;
    }

    @Override
    protected Throw doInBackground() throws Exception {
        Throw aThrow = new Throw(this.getDiceCount());
        ArrayList<Die> faces = aThrow.getFaces();
        //Testing
        System.out.println("You:");
        for(int i = 0 ; i < faces.size() ; i++) {
            System.out.print(faces.get(i).getValue() + " ");
        }
        System.out.println();
        System.out.println("Faces = " + faces.size());
        //Testing
        getContainer().add(new PanelOfDice("You", faces, "Current total = " + this.getPlayer().getScore()), BorderLayout.CENTER);
        this.getContainer().validate();
        this.getContainer().getComponent(0).repaint();
        return aThrow;
    }

    protected void done() {
        try {
            if(this.getThrowCount() == 0) {
                this.getScore().setMandatoryThrow(get());
            }
            else if(this.getThrowCount() == 1) {
                this.getScore().setRerolls(get(), 1);
            }
            else {
                this.getPlayer().addScore(get());
                this.getThrowButton().setEnabled(false);
            }
        }
        catch(ExecutionException executionException) {
            executionException.printStackTrace();
            JOptionPane.showMessageDialog(null, "Error in system. Please try again.", "System Error", JOptionPane.ERROR_MESSAGE);
        }
        catch(InterruptedException interruptedException) {
            interruptedException.printStackTrace();
            JOptionPane.showMessageDialog(null, "Error in system. Please try again.", "System Error", JOptionPane.ERROR_MESSAGE);
        }
    }

}

SystemPlayerCalculator.java

package ac.lk.iit.coursework2;

import java.awt.BorderLayout;
import java.awt.Container;
import java.util.ArrayList;
import java.util.concurrent.ExecutionException;

import javax.swing.JOptionPane;

public class SystemPlayerCalculator extends PlayerCalculator {

    public SystemPlayerCalculator(Container container, SystemPlayer player, Game game, Score score, int throwCount, int count) {
        super(player, game, container, score, throwCount, count);
    }

    @Override
    protected Throw doInBackground() throws Exception {
        Throw aThrow = new Throw(this.getDiceCount());
        ArrayList<Die> faces = aThrow.getFaces();
        Thread.sleep(5000);
        //Testing
        System.out.println("Computer:");
        for(int i = 0 ; i < faces.size() ; i++) {
            System.out.print(faces.get(i).getValue() + " ");
        }
        System.out.println();
        System.out.println("Faces = " + faces.size());
        //Testing
        getContainer().add(new PanelOfDice("Computer", faces, "Current total = " + this.getPlayer().getScore()), BorderLayout.SOUTH);
        this.getContainer().validate();
        this.getContainer().getComponent(1).repaint();
        return aThrow;
    }

    protected void done() {
        try {
            if(this.getThrowCount() == 0) {
                this.getScore().setMandatoryThrow(get());
            }
            else if(this.getThrowCount() == 1) {
                this.getScore().setRerolls(get(), 1);
            }
            else {
                this.getPlayer().addScore(get());
            }
        }
        catch(ExecutionException executionException) {
            JOptionPane.showMessageDialog(null, "Error in system. Please try again.", "System Error", JOptionPane.ERROR_MESSAGE);
        }
        catch(InterruptedException interruptedException) {
            JOptionPane.showMessageDialog(null, "Error in system. Please try again.", "System Error", JOptionPane.ERROR_MESSAGE);
        }
    }

}

此时,SystemPlayer的投掷将在线程定时等待后替换HumanPlayer的投掷显示,尽管它们根据BorderLayout放置在不同的位置。我无法弄清楚为什么会这样。

在这种情况下有人可以帮助我吗?

1 个答案:

答案 0 :(得分:1)

最简单的选择之一是使用CardLayout,有关详细信息,请参阅How to Use CardLayout

enter image description here

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
import java.util.concurrent.ExecutionException;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.LineBorder;

public class Test1 {

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

    public Test1() {
        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 TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private JPanel content;
        private CardLayout cardLayout;

        private ColorPane colorPane;
        private NumberPane numberPane;

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

            colorPane = new ColorPane();
            numberPane = new NumberPane();

            cardLayout = new CardLayout();

            content = new JPanel(cardLayout);
            content.add(new JPanel(), "blank");
            content.add(colorPane, "colorPane");
            content.add(numberPane, "numberPane");

            add(content);

            JPanel panel = new JPanel();
            JButton rndColor = new JButton("Color");
            rndColor.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    ColorWorker colorWorker = new ColorWorker(colorPane);
                    colorWorker.execute();
                    cardLayout.show(content, "colorPane");
                }
            });
            JButton rndNumber = new JButton("Number");
            rndNumber.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    NumberWorker numberWorker = new NumberWorker(numberPane);
                    numberWorker.execute();
                    cardLayout.show(content, "numberPane");
                }
            });
            panel.add(rndColor);
            panel.add(rndNumber);

            add(panel, BorderLayout.SOUTH);
        }

        public class ColorPane extends JPanel {

            public ColorPane() {
            }

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

        }

        public class ColorWorker extends SwingWorker<Color, Color> {

            private ColorPane colorPane;

            public ColorWorker(ColorPane colorPane) {
                this.colorPane = colorPane;
            }

            @Override
            protected void process(List<Color> chunks) {
                colorPane.setBackground(chunks.get(chunks.size() - 1));
            }

            @Override
            protected Color doInBackground() throws Exception {
                int randomColors = 1 + (int) (Math.random() * 100);
                Color color = null;
                for (int index = 0; index < randomColors; index++) {
                    int red = (int) (Math.random() * 255);
                    int green = (int) (Math.random() * 255);
                    int blue = (int) (Math.random() * 255);
                    color = new Color(red, green, blue);
                    publish(color);
                    Thread.sleep(40);
                }
                System.out.println(color);
                return color;
            }

            @Override
            protected void done() {
                try {
                    Color color = get();
                    colorPane.setBackground(color);
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                } catch (ExecutionException ex) {
                    ex.printStackTrace();
                }
            }

        }

        public class NumberPane extends JPanel {

            private JLabel label;

            public NumberPane() {
                setLayout(new GridBagLayout());
                label = new JLabel("...");
                add(label);
            }

            public void setNumber(int number) {
                label.setText(Integer.toString(number));
                revalidate();
                repaint();
            }

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

        }

        public class NumberWorker extends SwingWorker<Integer, Integer> {

            private NumberPane numberPane;

            public NumberWorker(NumberPane colorPane) {
                this.numberPane = colorPane;
            }

            @Override
            protected void process(List<Integer> chunks) {
                numberPane.setNumber(chunks.get(chunks.size() - 1));
            }

            @Override
            protected Integer doInBackground() throws Exception {
                int randomNumbers = (int) (Math.random() * 100);
                int number = 0;
                for (int index = 0; index < randomNumbers; index++) {
                    number = (int) (Math.random() * 1024);
                    publish(number);
                    Thread.sleep(40);
                }
                return number;
            }

            @Override
            protected void done() {
                try {
                    int number = get();
                    numberPane.setNumber(number);
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                } catch (ExecutionException ex) {
                    ex.printStackTrace();
                }
            }

        }

    }

}

如果您无法使用CardLayout,则需要根据需要在容器上致电revalidaterepaint强制父容器自行更新。