2016-03-03 104 views
0

有一點幫助將非常感激。無法使JComboBox更新JFrame

問題

我們有一個幻想課,上面有一個組合框。從組合框中選擇一個編隊時,該框架會通過按鈕進行更新。但是,因爲當我將動作偵聽器添加到組合框時,它只會讓我在幻想類的構造函數中創建我的類時使用,我必須將幻想類和班級類交給TeamController類,因此創建幻想類時,動作列表器不在組合框中,因此它不起作用。任何幫助將不勝感激。

主類

public class Main { 

    public static void main(String[] args) { 
    Fantasy f = new Fantasy(); 
    Squad s = new Squad(); 
    TeamController tc = new TeamController(f, s); 
    TextController txC = new TextController(s); 
    f.updateController(tc, txC); 
    f.setVisible(true); 
    } 

} 

幻想類

public class Fantasy extends JFrame { 
    private JPanel goalPanel; 
    private JPanel defendPanel; 
    private JPanel midPanel; 
    private JPanel attPanel; 
    private JPanel bench; 
    private JComboBox formation; 
    private Button myButton; 
    private TeamController control; 
    private TextController tControl; 
    private List <Button> buttons; 

    public Fantasy() { 
    super("Fantasy Football"); 
    buttons = new ArrayList <Button>(); 
    createWidgets(); 
    } 

    public void createWidgets() { 
    JPanel formPanel = new JPanel(new GridLayout(1, 0)); 
    goalPanel = new JPanel(new FlowLayout()); 
    defendPanel = new JPanel(new FlowLayout()); 
    midPanel = new JPanel(new FlowLayout()); 
    attPanel = new JPanel(new FlowLayout()); 
    bench = new JPanel(new FlowLayout()); 

    JComboBox formation = new JComboBox(); 
    String[] addFormation = { 
     "4 - 4 - 2", "4 - 3 - 3", "3 - 5 - 2", "5 - 3 - 2", "3 - 4 - 3", "4 - 5 - 1" 
    }; 

    for (String newForm: addFormation) { 
     formation.addItem(newForm); 
    } 

    formation.addActionListener(control); 

    setLayout(new GridLayout(6, 0)); 
    add(formPanel); 
    formPanel.add(formation); 
    add(goalPanel); 
    add(defendPanel); 
    add(midPanel); 
    add(attPanel); 
    add(bench); 

    pack(); 
    setDefaultCloseOperation(EXIT_ON_CLOSE); 
    } 

    public JComboBox getForm() { 
    return formation; 
    } 

    public JPanel getGoal() { 
    return goalPanel; 
    } 

    public JPanel getDef() { 
    return defendPanel; 
    } 

    public JPanel getMid() { 
    return midPanel; 
    } 

    public JPanel getAtt() { 
    return attPanel; 
    } 

    public JPanel getBench() { 
    return bench; 
    } 

    public void createDefender(String text, String ID) { 
    addButtons(text, ID, defendPanel); 
    } 

    public void createMid(String text, String ID) { 
    addButtons(text, ID, midPanel); 
    } 

    public void createAtt(String text, String ID) { 
    addButtons(text, ID, attPanel); 
    } 

    public void addButtons(String text, String ID, JPanel panel) { 
    myButton = new Button(text, ID); 
    myButton.getButton().addActionListener(control); 
    myButton.getText().addTextListener(tControl); 
    buttons.add(myButton); 
    panel.add(myButton); 
    } 

    public void updateController(TeamController control, TextController tControl) { 
    this.control = control; 
    this.tControl = tControl; 
    } 

    public List <Button> getButtons() { 
    return buttons; 
    } 

} 

ActionListner - TeamController類

public class TeamController implements ActionListener { 
    private Fantasy fantasy; 
    private Squad squad; 
    private JComboBox form; 
    private ArrayList <Button> button; 

    public TeamController(Fantasy fantasy, Squad squad) { 
    this.fantasy = fantasy; 
    this.form = fantasy.getForm(); 
    this.button = (ArrayList <Button>) fantasy.getButtons(); 
    this.squad = squad; 
    } 


    public void actionPerformed(ActionEvent e) { 
    if (e.getSource() == form) { 
     comboChooser((JComboBox) e.getSource()); 
    } else { 
     fileChooser((Button) e.getSource()); 
    } 
    } 

    public void comboChooser(JComboBox form) { 
    //restart the pane 
    fantasy.getContentPane().removeAll(); 
    fantasy.createWidgets(); 
    //add the goalie buttons and labels in 
    fantasy.addButtons("GoalKeeper", squad.getAllGoal().get(0).getID(), fantasy.getGoal()); 
    //2. break it up into each def mid att 
    //JComboBox format = form; 
    String[] split = ((String) form.getSelectedItem()).split("-"); 
    int[] splits = new int[3]; 
    for (int i = 0; i < split.length; i++) { 
     splits[i] = Integer.parseInt(split[i].trim()); 
    } 
    //3. create number of widgets for each posit in each panel 
    //4. add leftover to bench 

    makeDefender(splits[0], squad.getAllDef()); 
    makeMid(splits[1], squad.getAllMid()); 
    makeAttack(splits[2], squad.getAllAtt()); 

    fantasy.pack(); 
    } 

    public void fileChooser(Button button) { 
    final JFileChooser fileChooser = new JFileChooser("C:\\Users\\Michael\\Documents\\Java WorkSpace\\ExerciseThree\\Minor Piece of Coursework 3 Resources\\squad"); 
    int getVal = fileChooser.showOpenDialog(button.getButton()); 
    if (getVal == JFileChooser.APPROVE_OPTION) { 
     File file = fileChooser.getSelectedFile(); 
     button.getButton().setVisible(false); 
     button.add(button.updateButton(file), BorderLayout.CENTER); 
     Player selectedPlayer = squad.getByID(button.getName()); 
     selectedPlayer.setPath(file.getPath()); 
     String playerName = file.getName(); 
     if (playerName.endsWith(".jpg")) { 
     playerName.substring(0, playerName.length() - 4); 
     selectedPlayer.setName(playerName); 
     } 
     button.getText().setText(playerName); 
    } else { 
     System.out.println("Cancelled your choice"); 
    } 

    } 

    public void makeDefender(int number, List <Defender> list) { 
    for (int i = 0; i < number; i++) { 
     String ID = list.get(i).getID(); 
     fantasy.createDefender("Defender", ID); 
    } 
    } 

    public void makeMid(int number, List <Midfielder> list) { 
    for (int i = 0; i < number; i++) { 
     String ID = list.get(i).getID(); 
     fantasy.createMid("Midfielder", ID); 
    } 
    } 

    public void makeAttack(int number, List <Striker> list) { 
    for (int i = 0; i < number; i++) { 
     String ID = list.get(i).getID(); 
     fantasy.createAtt("Striker", ID); 
    } 
    } 

    public void updateSquad(Squad squad) { 
    this.squad = squad; 
    } 
} 
+1

提供在'Fantasy'類可以通過你的'TeamController'被調用時,它的構造函數被調用,其註冊我使用嚴格的'JComboBox' – MadProgrammer

+0

@MadProgrammer一個'addActionListener'方法MVC。所以我將無法在我的視圖中使用控制器 –

+0

我沒有要求您將控制器傳遞到視圖中,我要求您將「ActionListener」傳遞給視圖,以便它可以生成事件「ActionListener」(控制器)的實現可以作出反應,通常情況下,與你首先嚐試做的事情沒有什麼不同。如果你不能在視圖中使用控制器,那麼在'Fantasy'類中有什麼'private TextController tControl'?我的解決方案將擺脫這個 – MadProgrammer

回答

3

所以基本回答你的問題是使用Observer Pattern,其中控制器可以觀察者轉換視圖使(和推測)通知模型。 Swing已經是MVC的一種形式(阿爾比M-VC),所以試圖在其上實現另一個MVC會讓你頭疼。

取而代之,退後一步。控制器不關心事情是如何完成的,它只關心它在完成時得到通知,所以它實際上並不需要知道任何關於如何實現視圖的事情,只是它符合已知的合同(它成爲一個黑匣子)。

反過來視圖不關心控制器或模型什麼

這樣,您就可以實現他們你想要的任何方式查看和永遠不必改變控制器,以適應它,只要你支持由兩個定義的聯繫人

當我這樣做時,我總是從接口開始,這使我可以專注於需求,而不必擔心細節,「我希望你這樣做」,而不需要關心關於「如何完成」...

public interface FantasyView { 

    public String getFormation(); 
    public void setFormation(String formation); // Maybe throw an IllegalArgumentException or use an object or enum 

    // Other information which the might be useful to return 
    public void addFormationChangedObserver(ChangeListener listener); 
    public void removeFormationChangedObserver(ChangeListener listener); 

    public JComponent getView(); 

} 

public interface SquadModel { 
    // Some getters and setters 
    // Some observers so the controller and get notified by changes and 
    // update the view accordingly... 
} 

public interface TeamController { 
    public FantasyView getView(); 
    public SquadModel getModel(); 
} 

正如你所看到的,FantasyView通過ChangeListener(我懶惰,所以我重新使用可用的代碼)提供了觀察者的變化形成,它沒有說明如何生成,只有當形成變化,它會產生一個事件。

沒有其他接口實際實現ChangeListener,所以它本身不是合同的要求,但如果您想知道何時更改地層,您將需要提供一個接口。

現在,可能實現該控制器可能看起來像......

public class DefaultTeamController implements TeamController { 

    private FantasyView view; 
    private SquadModel model; 

    public DefaultTeamController(FantasyView view, SquadModel model) { 
     this.view = view; 
     this.model = model; 

     view.addFormationChangedObserver(new ChangeListener() { 
      @Override 
      public void stateChanged(ChangeEvent e) { 
       SquadModel model = getModel(); 
       // update model accordingly 
      } 
     }); 

     // Add observers to model... 
    } 

    @Override 
    public FantasyView getView() { 
     return view; 
    } 

    @Override 
    public SquadModel getModel() { 
     return model; 
    } 

} 

已控制器被暴露有何看法?不,它只是將ChangeListener的實例註冊到視圖中。認爲不應該進行假設什麼的ChangeListener的實施,應該只與合同接口的

互動現在,你可能想知道你是如何從一個ActionListenerChangeListener ....

JComboBox formation = new JComboBox(); 
//... 
formation.addActionListener(new ActionListener() { 
    @Override 
    public void actionPerformed(ActionEvent e) { 
     fireFormationChanged(); 
    } 
}); 

//... 

protected void fireFormationChanged() { 
    // changeListeners is a simple List of ChangeListener 
    // this is instance of FantasyView 
    ChangeEvent evt = new ChangeEvent(this); 
    for (ChangeListener listener : changeListeners) { 
     listener.stateChanged(evt); 
    } 
} 

爲例

+0

中提供了一個'add/removeActionListener'方法感謝你的回答。它工作完美。乾杯! –