我正在研究Java添加一个按钮,在单击时触发功能。这是从主类执行以创建游戏窗口的GUI文件。我找到的唯一方法是:
package Kingdomino;
import java.awt.BorderLayout;
...
public class createAndShowGUI extends JPanel {
static public JComboBox createNumPlayersMenu(){
String[] lista = {"2 players","3 players","4 players"};
JComboBox numPlayersMenu = new JComboBox(lista);
numPlayersMenu.setSelectedIndex(2);
numPlayersMenu.setMaximumSize(new Dimension(200,30));
return numPlayersMenu;
}
static public JComboBox createPlayerColorMenu(){
String[] lista = {"blue","green","red","pink"};
JComboBox playerColor = new JComboBox(lista);
playerColor.setSelectedIndex(2);
playerColor.setMaximumSize(new Dimension(200,30));
return playerColor;
}
static public JButton createPlayButton() {
JButton createPlayButton = new JButton();
createPlayButton.setText("Play");
return createPlayButton;
}
static public void main() throws IOException {
JFrame frame = new JFrame("FrameDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.setJMenuBar(createMenuBar());
JPanel jpanel = new JPanel();
frame.getContentPane().add(jpanel, BorderLayout.CENTER);
Box verticalBox = Box.createVerticalBox();
jpanel.add(verticalBox, BorderLayout.CENTER);
JLabel label = new JLabel();
label.setText("Hi");
verticalBox.add(label);
Box horizontalBox = Box.createHorizontalBox();
horizontalBox.setMaximumSize(new Dimension(700,50));
JComboBox numPlayersMenu = createNumPlayersMenu();
horizontalBox.add(numPlayersMenu);
JComboBox playerColor = createPlayerColorMenu();
horizontalBox.add(playerColor);
verticalBox.add(horizontalBox);
JButton btnNewButton = createPlayButton();
btnNewButton.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
String num1 = numPlayersMenu.getSelectedItem().toString();
String num2 = playerColor.getSelectedItem().toString();
label.setText( "Selected number of players: "+num1 + " // selected color: " + num2 );
}
});
verticalBox.add(btnNewButton);
frame.pack();
frame.setVisible(true);
}
}
问题是,如果我想实现的函数比几行代码更复杂,我想用不同的方法实现它,而不是在 main()的代码中
我尝试过很多方法来尝试这样做,但都没有效果。这个方法似乎最简单,最干净,但我不喜欢在main()方法中定义一个函数,我宁愿把它放在外面并在动作监听器中引用它。
我确信必须有办法做到这一点,但我无法弄明白。有帮助吗?谢谢!
答案 0 :(得分:0)
我的评论中的建议可能看起来似乎过于复杂,因为建议你重新思考你的代码,你努力使它更符合面向对象,并且在短期内这可能是是的,但从中期和长期来看,情况恰恰相反,因为现在你的游戏非常简单,你只是想设置两个属性,int和一个颜色,但是一旦你做出来这只是稍微复杂一点,将一切都留在静态领域所带来的复杂性可能会变得无法抗拒。
所以说到了,我的建议是什么?首先从视图(GUI代码)中提取模型(非GUI状态),这里模型非常简单,一个包含int的类,一个Color,一个包含构造函数,字段,getter / setter,以及其他任何需要的东西,如下:
import java.awt.Color;
// class that holds the non-GUI "state" of the game
// Also holds non-GUI behaviors as well via its methods
public class Game {
// fields to hold state
private int numberOfPlayers;
private Color color;
public Game() {
this(0, Color.WHITE);
}
public Game(int numberOfPlayers, Color color) {
this.numberOfPlayers = numberOfPlayers;
this.color = color;
}
public int getNumberOfPlayers() {
return numberOfPlayers;
}
public void setNumberOfPlayers(int numberOfPlayers) {
this.numberOfPlayers = numberOfPlayers;
}
public Color getColor() {
return color;
}
public void setColor(Color color) {
this.color = color;
}
// other behavior methods here
}
然后让我们创建一个JPanel来保存并显示两个JComboBox,比如称为UserSelectionPanel:
public class UserSelectionPanel extends JPanel {
private static final String[] NUMBER_OF_PLAYERS_ITEMS = {
"2 Players", "3 Players", "4 Players"};
// using "parallel arrays" below, not a good thing long-term
private static final String[] COLOR_ITEMS = {
"Blue", "Green", "Red", "Pink"
};
private static final Color[] COLORS = {
Color.BLUE, Color.GREEN, Color.RED, Color.PINK
};
private static final Color DEFAULT_COLOR = Color.WHITE;
JComboBox<String> numberOfPlayersCombo = new JComboBox<>(NUMBER_OF_PLAYERS_ITEMS);
JComboBox<String> colorsCombo = new JComboBox<>(COLOR_ITEMS);
我们也可以提供这种getter方法,以便我们可以提取用户选择的内容,例如播放器编号:
public int getNumberOfPlayers() {
int selection = numberOfPlayersCombo.getSelectedIndex();
if (selection < 0) {
return 0;
} else {
return selection + 2;
}
}
整个事情看起来像:
import java.awt.Color;
import java.awt.GridLayout;
import javax.swing.*;
@SuppressWarnings("serial")
public class UserSelectionPanel extends JPanel {
private static final String[] NUMBER_OF_PLAYERS_ITEMS = {
"2 Players", "3 Players", "4 Players"};
// using "parallel arrays" below, not a good thing long-term
private static final String[] COLOR_ITEMS = {
"Blue", "Green", "Red", "Pink"
};
private static final Color[] COLORS = {
Color.BLUE, Color.GREEN, Color.RED, Color.PINK
};
private static final Color DEFAULT_COLOR = Color.WHITE;
JComboBox<String> numberOfPlayersCombo = new JComboBox<>(NUMBER_OF_PLAYERS_ITEMS);
JComboBox<String> colorsCombo = new JComboBox<>(COLOR_ITEMS);
public UserSelectionPanel() {
setLayout(new GridLayout(0, 2, 10, 10));
add(new JLabel("Number of Players:"));
add(numberOfPlayersCombo);
add(new JLabel("Color:"));
add(colorsCombo);
}
public Color getSelectedColor() {
int selection = colorsCombo.getSelectedIndex();
if (selection < 0) {
return DEFAULT_COLOR;
} else {
return COLORS[selection];
}
}
public int getNumberOfPlayers() {
int selection = numberOfPlayersCombo.getSelectedIndex();
if (selection < 0) {
return 0;
} else {
return selection + 2;
}
}
}
然后我们可以轻松地在JOptionPane中显示这个JPanel,如果我们想要显示它,并从中获取信息
接下来是播放游戏的主JFrame中显示的主要JPanel。我们在这一点上非常简单,只需持有一个显示玩家数量的JLabel,一个在JOptionPane中显示UserSelectionPanel的JButton,主要的JPanel背景颜色将反映所选择的颜色。我们还可以给它一个Game对象,以便在进行用户选择时更新Game对象的状态。像这样:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import javax.swing.*;
@SuppressWarnings("serial")
public class MainGamePanel extends JPanel {
private static final int PREF_W = 600;
private static final int PREF_H = 450;
private UserSelectionPanel userSelectionPanel = new UserSelectionPanel();
private Game game;
private JLabel numberOfPlayersLabel = new JLabel("0");
public MainGamePanel(Game game) {
JPanel topPanel = new JPanel();
topPanel.setOpaque(false); // so color shows through
// display the number of players here
topPanel.add(new JLabel("Number of Players:"));
topPanel.add(numberOfPlayersLabel);
// to hold button that displays dialog
JPanel middlePanel = new JPanel(new GridBagLayout());
middlePanel.setOpaque(false); // same reason
middlePanel.add(new JButton(new AbstractAction("Set-Up Game") {
@Override
public void actionPerformed(ActionEvent e) {
setUpGameActionPerformed();
}
}));
setPreferredSize(new Dimension(PREF_W, PREF_H));
this.game = game;
setBackground(game.getColor());
setLayout(new BorderLayout());
add(topPanel, BorderLayout.PAGE_START);
add(middlePanel);
}
private void setUpGameActionPerformed() {
// set up the JOptionPane
Component parentComponent = MainGamePanel.this;
UserSelectionPanel message = userSelectionPanel; // *** our all-imporant JPanel
String title = "Set-up Game";
int optionType = JOptionPane.OK_CANCEL_OPTION;
int messageType = JOptionPane.PLAIN_MESSAGE;
// display the JOptionPane
int result = JOptionPane.showConfirmDialog(parentComponent, message, title,
optionType, messageType);
// if the user pressed "OK" then make the changes
if (result == JOptionPane.OK_OPTION) {
// update the state of the GUI
int numberOfPlayers = userSelectionPanel.getNumberOfPlayers();
Color color = userSelectionPanel.getSelectedColor();
// and update our Game field, game:
game.setNumberOfPlayers(numberOfPlayers);
game.setColor(color);
numberOfPlayersLabel.setText(String.valueOf(numberOfPlayers));
setBackground(color);
}
}
}
我们可以像这样运行整个事情:
import javax.swing.*;
public class SimpleGameMain {
private static void createAndShowGui() {
Game game = new Game();
MainGamePanel mainPanel = new MainGamePanel(game);
JFrame frame = new JFrame("OOP Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
那么为什么要经历所有这些混乱?因为您当前的游戏设置非常简单,只要您尝试使其更加复杂和有趣,就会很难 进行调试和增强。如果你以这种方式分离出问题,如果你利用OOP,你就有更好的机会创造出可以增长和改进的东西。