2014-12-31 36 views
0

我對Java併發性比較陌生,這是我的這種性質的第一個應用程序之一。如何使用按鈕單擊刪除並替換JPanel?

我一直在試圖添加一個名爲Panel of Dice的自定義JPanel,當單擊一個按鈕「Throw」時,它顯示隨機生成的5個骰子面。我使用了兩個SwingWorker Threads HumanPlayer和SystemPlayer,它們更新了它們自己的throws,並使用上面的面板在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之遙,將REPL在線程定時等待之後調用HumanPlayer的throw顯示,雖然它們被放置在基於BorderLayout的不同位置。我無法弄清楚爲什麼會發生這種情況。

有人可以幫助我在這種情況下?

+0

沒有答案,但我會大大簡化所有這一切**不**使用SwingWorker或線程直接,而是通過使用Swing Timer和CardLayout。 –

+0

...或甚至比CardLayout更好 - 使用JLabel來顯示骰子的面部,只需換出ImageIcons以顯示不同的面部。 –

+1

最後考慮創建併發布[最小,完整和可驗證示例程序](http://stackoverflow.com/help/mcve)。我們不想看到你的整個程序,而是你應該將你的代碼壓縮到仍然編譯的最小位,沒有額外的代碼與你的問題無關,但仍然表明你的問題。 –

回答

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父級容器上,因爲您想強制父容器自行更新。