2016-03-03 74 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'方法感谢你的回答。它工作完美。干杯! –