无法使 JComboBox 更新 JFrame
Can't make JComboBox update JFrame
如果能提供一点帮助,我们将不胜感激。
问题
我们有一个幻想class,上面有一个组合框。从组合框中选择编队时,框架会使用按钮进行更新。但是因为当我给组合框添加action listener时,它只会让我在幻想class的构造函数中做,当在main方法中创建我的class时,我必须交幻想 class 和小队 class 到 TeamController
class 所以当创建幻想 class 时,动作列表不在组合框上,所以它是不工作。任何帮助将不胜感激。
主要Class
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);
}
}
奇幻class
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 - 团队控制器class
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;
}
}
所以您问题的基本答案是使用 Observer Pattern,其中控制器可以观察者更改视图并(大概)通知模型。
Swing 已经是 MVC 的一种形式(虽然是 M-VC),因此尝试在其上实现另一个 MVC 会让您头疼。
相反,退后一步。控制器不关心事情是如何完成的,它只关心它在完成时得到通知,所以它实际上不需要知道任何关于视图是如何实现的,只需要它符合一个已知的契约(它变成黑盒子)。
视图反过来不关心控制器或模型
这样,您可以以任何您想要的方式实现它们的视图,而无需更改控制器以适应它,只要您支持两者定义的接触
当我做这样的事情时,我总是从接口开始,这让我可以专注于需求而不需要担心细节,"I want you do this",而不关心"how you get it done".. .
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
为阵型的变化提供了一个观察者(我很懒,所以我重新使用了可用的代码),它并没有'说那是怎么产生的,只是阵型变化时,会产生事件
None 的其他接口实际上实现了 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
的实现是什么,并且应该只与接口的契约交互
现在,您可能想知道如何从 ActionListener
变成 ChangeListener
...
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);
}
}
举个例子
如果能提供一点帮助,我们将不胜感激。
问题
我们有一个幻想class,上面有一个组合框。从组合框中选择编队时,框架会使用按钮进行更新。但是因为当我给组合框添加action listener时,它只会让我在幻想class的构造函数中做,当在main方法中创建我的class时,我必须交幻想 class 和小队 class 到 TeamController
class 所以当创建幻想 class 时,动作列表不在组合框上,所以它是不工作。任何帮助将不胜感激。
主要Class
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);
}
}
奇幻class
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 - 团队控制器class
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;
}
}
所以您问题的基本答案是使用 Observer Pattern,其中控制器可以观察者更改视图并(大概)通知模型。
Swing 已经是 MVC 的一种形式(虽然是 M-VC),因此尝试在其上实现另一个 MVC 会让您头疼。
相反,退后一步。控制器不关心事情是如何完成的,它只关心它在完成时得到通知,所以它实际上不需要知道任何关于视图是如何实现的,只需要它符合一个已知的契约(它变成黑盒子)。
视图反过来不关心控制器或模型
这样,您可以以任何您想要的方式实现它们的视图,而无需更改控制器以适应它,只要您支持两者定义的接触
当我做这样的事情时,我总是从接口开始,这让我可以专注于需求而不需要担心细节,"I want you do this",而不关心"how you get it done".. .
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
为阵型的变化提供了一个观察者(我很懒,所以我重新使用了可用的代码),它并没有'说那是怎么产生的,只是阵型变化时,会产生事件
None 的其他接口实际上实现了 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
的实现是什么,并且应该只与接口的契约交互
现在,您可能想知道如何从 ActionListener
变成 ChangeListener
...
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);
}
}
举个例子