Java 如何添加触发别处定义的函数的actionEvent?
我正在开发Java,添加了一个按钮,当点击时会触发一个函数。这是从主类执行的GUI文件,用于制作游戏窗口。我找到的唯一方法是:Java 如何添加触发别处定义的函数的actionEvent?,java,swing,Java,Swing,我正在开发Java,添加了一个按钮,当点击时会触发一个函数。这是从主类执行的GUI文件,用于制作游戏窗口。我找到的唯一方法是: package Kingdomino; import java.awt.BorderLayout; ... public class createAndShowGUI extends JPanel { static public JComboBox createNumPlayersMenu(){ String[] lista = {"2 p
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方法中定义函数,我宁愿将它放在外部,并在action侦听器中引用它
我相信一定有办法做到这一点,但我一直没能想出办法。有什么帮助吗?谢谢大家! 同样,我在评论中的建议似乎过于复杂化了,建议您重新思考代码,努力使其更符合面向对象,短期内这可能是正确的,但从中期和长期来看,情况正好相反,因为现在您的游戏非常简单,你只是试着设置两个属性,int和Color,但是一旦你把它变得更复杂一点,把所有东西都放在静态领域所带来的复杂性就会变得难以承受 既然如此,我的建议是什么?首先从view 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
}
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());
}
}
然后,让我们创建一个JPanel,它保存并显示两个JComboxes,如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);
我们可以这样做:
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
}
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发挥优势,您就有更好的机会创建可以增长和改进的东西。静态方法中的代码太多,没有创建真正符合OOP的对象的代码,就好像您是以意识流的方式创建此程序一样。不要。在编码之前规划类,使它们成为行为良好的对象,具有状态和行为的对象,然后重新开始。这将如何帮助我解决问题?只是真诚地问一下,我不认为有必要做一些不能改善或解决我的问题的事情,只是让代码变得更复杂。如果它真的有用的话,我会去做。就是这样,你所做的就是让你的代码变得不必要的复杂和不起作用。所以,是的,你应该放弃这个代码,重新开始。同样,意识流类型的代码也不值得这么做。例如,您发布的代码没有字段-那么除了通过参数之外,您如何在方法之间共享状态?这个状态在程序运行时是如何保持和改变的?感谢你发表了大量的评论,这些评论根本没有回答这个问题。welp谢谢,我将回顾这些代码,并尝试以一种更面向对象的方式编写它。到目前为止,当我只需要运行一次类时,我并不认为有必要建立类。这就是为什么我只使用静态方法和对象,我不需要特定的实例。问题:我不明白为什么只写add而不写topPanel.add有效。您是否应该指定要添加面板的位置?