2015-11-05 46 views
0

我正在使用swing在java中製作一個骰子滾動程序。我有4類:使用舊實例的paintComponent

模具

public class Die{ 
private int faceValue; 

public Die(){ 
    System.out.println("Creating new Dice Object"); 
    setValue(roll()); 
} 

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; 
} 
} 

DieFace

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 
} 
} 

DieFaceComponent

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對象,用於繪製組件的值與初始實例保持相同。有什麼我做錯了嗎?在此先感謝

+1

不要在'paintComponent'方法中調用'revalidate',也應該在做任何自定義繪畫之前調用'super.paintComponent'作爲一般規則thumb – MadProgrammer

+1

您在'ActionListener'中創建了一個'DieFaceComponent'的新實例,但是它什麼都沒做,它從來沒有添加到任何東西,所以它永遠不可見。更好的解決方案可以讓你觸發對'DieFaceComponent'的更改,它觸發了對'DieFace'的更改,它觸發了對'Die'的更改並且整個事情都只是'重新繪製'本身 – MadProgrammer

回答

2

您在ActionListener中創建了一個DieFaceComponent的新實例,但它什麼也沒做,它從來沒有添加到任何東西,所以它永遠不可見。更好的解決方案將允許你觸發改變DieFaceComponent,從而引發了變化DieFace從而引發了變化Die和有整件事只是repaint本身,例如...

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()); 

    } 
} 

現在,你可以致電roll,電話DieFaceComponent,電話roll,電話DieFace,電話roll,電話Die,將更新實際值。然後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); 
     } 

    } 

} 

現在,一個更好的解決辦法是有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 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()); 

     } 
    } 

} 

這是一個Observer Pattern,其中個簡單的例子是信息的生成者,每個人都有興趣知道它何時發生變化。它也是模型 - 視圖 - 控制器範例的一個變體

+0

嗨,感謝這篇文章,這是一個任務的一部分,所以不幸的是我必須堅持我允許的類:/我實現了你的第一個解決方案,但是當我調用component.roll()時,骰子的faceValue不會改變 – Defa1t

+0

至少你可以建議一個更好的設計 – MadProgrammer

+0

我肯定,最大的問題是必須堅持過時的鞦韆實施 – Defa1t