Jeu d'interface graphique de swing de couleur
J'ai créé ce programme ici (~ 240 lignes) dans lequel l'utilisateur doit faire correspondre son panneau RVB (à droite) avec une couleur aléatoire à gauche. C'est un programme assez amusant, et je vous suggère de l'essayer! Il est entièrement exécutable tel quel.
Mais une grande partie du code semble répétitive et je me demandais comment il pourrait être condensé et rendu plus efficace si possible. Tous les autres conseils seraient grandement appréciés. C'est mon premier programme java depuis quelques années donc j'ai peut-être enfreint certaines règles non écrites.
Ma plus grande préoccupation avec ce programme est la répétitivité du JButtonset des fonctions qu'il exécute. Il y a 6 boutons, un qui ajoute du rouge, un qui soustrait du rouge, un qui ajoute du vert, un qui soustrait du vert, un qui ajoute du bleu et un qui soustrait du bleu. La fonctionnalité est très similaire car elles augmentent ou diminuent la couleur de 15, donc je me demandais s'il y avait un moyen de les condenser toutes en une seule fonction. Merci!
J'ai ajouté quelques commentaires pour expliquer ce qui se passe
package guessColor;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
public class GuessColor extends JFrame {
private static final long serialVersionUID = 1L;
Font font = new Font("Times New Roman", Font.BOLD, 30);
static Random rand = new Random();
static int randRed = (rand.nextInt(17)+1)*15; //randomized red green and blue values, multiples of 15
static int randGrn = (rand.nextInt(17)+1)*15;
static int randBlu = (rand.nextInt(17)+1)*15;
static int userRed = 0;
static int userGrn = 0;
static int userBlu = 0;
Color randColor = new Color(randRed, randGrn, randBlu);
static Color userColor = new Color(userRed, userGrn, userBlu);
Dimension d = new Dimension(500, 500); //color panel size
Dimension b = new Dimension(50,50); //button size
public GuessColor() {
initGUI();
System.out.println("SOLUTION: " + randRed + " " + randGrn + " " + randBlu); // This is just to show what the RGB values are so you can easily solve
setTitle("Match the color!");
pack();
setLocationRelativeTo(null);
setVisible(true);
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
private void initGUI() { //sets up the frame and functionality of UI
JLabel title = new JLabel("Match The Color!", JLabel.CENTER);
title.setFont(font);
title.setBackground(Color.BLACK);
title.setForeground(Color.WHITE);
title.setOpaque(true);
add(title, BorderLayout.NORTH);
JPanel center = new JPanel();
center.setBackground(Color.CYAN);
add(center, BorderLayout.CENTER);
JPanel randPan = new JPanel(); //random color panel
randPan.setBackground(randColor);
randPan.setPreferredSize(d);
center.add(randPan, BorderLayout.EAST);
JPanel userPan = new JPanel(); //adjustable color panel
userPan.setBackground(userColor);
userPan.setPreferredSize(d);
center.add(userPan, BorderLayout.WEST);
/**BUTTONS**/
JPanel butPan = new JPanel();
add(butPan, BorderLayout.SOUTH);
JButton addRed = new JButton("+");
addRed.setBackground(Color.RED);
addRed.setPreferredSize(b);
addRed.setFocusPainted(false);
addRed.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
increaseRed();
userPan.setBackground(userColor);
repaint();
check();
}
});
butPan.add(addRed);
JButton subRed = new JButton("-");
subRed.setBackground(Color.RED);
subRed.setPreferredSize(b);
subRed.setFocusPainted(false);
subRed.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
decreaseRed();
userPan.setBackground(userColor);
repaint();
check();
}
});
butPan.add(subRed);
JButton addGrn = new JButton("+");
addGrn.setBackground(Color.GREEN);
addGrn.setPreferredSize(b);
addGrn.setFocusPainted(false);
addGrn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
increaseGrn();
userPan.setBackground(userColor);
repaint();
check();
}
});
butPan.add(addGrn);
JButton subGrn = new JButton("-");
subGrn.setBackground(Color.GREEN);
subGrn.setPreferredSize(b);
subGrn.setFocusPainted(false);
subGrn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
decreaseGrn();
userPan.setBackground(userColor);
repaint();
check();
}
});
butPan.add(subGrn);
JButton addBlu = new JButton("+");
addBlu.setBackground(Color.BLUE);
addBlu.setPreferredSize(b);
addBlu.setFocusPainted(false);
addBlu.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
increaseBlu();
userPan.setBackground(userColor);
repaint();
check();
}
});
butPan.add(addBlu);
JButton subBlu = new JButton("-");
subBlu.setBackground(Color.BLUE);
subBlu.setPreferredSize(b);
subBlu.setFocusPainted(false);
subBlu.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
decreaseBlu();
userPan.setBackground(userColor);
repaint();
check();
}
});
butPan.add(subBlu);
}
//function names say it all...
private static void increaseRed() {
if (userRed < 255) {
userRed += 15;
userColor = new Color(userRed, userGrn, userBlu);
}
}
private static void increaseGrn() {
if (userGrn < 255) {
userGrn += 15;
userColor = new Color(userRed, userGrn, userBlu);
}
}
private static void increaseBlu() {
if (userBlu < 255) {
userBlu += 15;
userColor = new Color(userRed, userGrn, userBlu);
}
}
private static void decreaseRed() {
if (userRed > 0) {
userRed -= 15;
userColor = new Color(userRed, userGrn, userBlu);
}
}
private static void decreaseGrn() {
if (userGrn > 0) {
userGrn -= 15;
userColor = new Color(userRed, userGrn, userBlu);
}
}
private static void decreaseBlu() {
if (userBlu > 0) {
userBlu -= 15;
userColor = new Color(userRed, userGrn, userBlu);
}
}
//checks if the color panels are the same and displays winning message if they are
private static void check() {
if (userRed == randRed && userGrn == randGrn && userBlu == randBlu) {
int choose = JOptionPane.showConfirmDialog(null, "You win! Play again?");
if(choose == JOptionPane.YES_OPTION) {
reset();
} else if(choose == JOptionPane.NO_OPTION) {
System.exit(0);
}
}
}
//resets game for when user wins and wants to play again
private static void reset() {
randRed = (rand.nextInt(17)+1)*15;
randGrn = (rand.nextInt(17)+1)*15;
randBlu = (rand.nextInt(17)+1)*15;
userRed = 0;
userGrn = 0;
userBlu = 0;
userColor = new Color(userRed, userGrn, userBlu);
new GuessColor();
}
//main method
public static void main(String[] args) {
try {
String laf = UIManager.getCrossPlatformLookAndFeelClassName();
UIManager.setLookAndFeel(laf);
}
catch (Exception e) {}
SwingUtilities.invokeLater(new Runnable(){
public void run() {
new GuessColor();
}
});
}
}
Réponses
Ma version n'est pas plus courte, mais j'espère qu'elle est plus claire et fournit une base plus solide pour créer des jeux plus complexes.
Lors du développement d'un jeu Swing, cela aide à séparer le modèle, la vue et le contrôleur. C'est ce qu'on appelle le modèle modèle / vue / contrôleur .
Donc, je créé une classe de modèle, GameModel. Voici le code de la GameModelclasse.
public class GameModel {
private Color randomColor;
private Color userColor;
private final Random random;
public GameModel() {
this.random = new Random();
}
public void createColors() {
setRandomColor();
setUserColor();
}
public Color getUserColor() {
return userColor;
}
public void setUserColor() {
int userRed = 0;
int userGrn = 0;
int userBlu = 0;
this.userColor = new Color(userRed, userGrn, userBlu);
}
public void setUserColor(int red, int green, int blue) {
this.userColor = new Color(red, green, blue);
}
public Color getRandomColor() {
return randomColor;
}
public void setRandomColor() {
int randRed = (random.nextInt(17) + 1) * 15;
int randGrn = (random.nextInt(17) + 1) * 15;
int randBlu = (random.nextInt(17) + 1) * 15;
this.randomColor = new Color(randRed, randGrn, randBlu);
}
}
GameModelest une classe Java simple qui contient les données du jeu. Dans ce jeu simple, nous avons deux champs de couleur, un pour la couleur aléatoire et un pour l'utilisateur à ajuster à l'aide des boutons de l'interface graphique.
Nous avons déplacé le code d'initiation de la couleur dans cette classe.
Nous avons deux setRandomColorméthodes, une pour initialiser la couleur de l'utilisateur et une pour définir la couleur de l'utilisateur en fonction des actions du bouton GUI.
Maintenant que nous avons créé un modèle de jeu fonctionnel, nous pouvons nous concentrer sur la vue. Voici le code de vue.
public class GuessColor {
private GameModel model;
private JFrame frame;
private JPanel userPanel;
public GuessColor() {
this.model = new GameModel();
this.model.createColors();
frame = new JFrame("Match the color!");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createMainPanel(), BorderLayout.CENTER);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setResizable(false);
frame.setVisible(true);
printSolution();
}
// sets up the frame and functionality of UI
private JPanel createMainPanel() {
JPanel panel = new JPanel(new BorderLayout());
JLabel title = new JLabel("Match The Color!", JLabel.CENTER);
Font font = new Font("Times New Roman", Font.BOLD, 30);
title.setFont(font);
title.setBackground(Color.BLACK);
title.setForeground(Color.WHITE);
title.setOpaque(true);
panel.add(title, BorderLayout.NORTH);
JPanel center = new JPanel(new BorderLayout());
center.setBackground(Color.CYAN);
panel.add(center, BorderLayout.CENTER);
Dimension d = new Dimension(500, 500); // color panel size
JPanel randPan = new JPanel(); // random color panel
randPan.setBackground(model.getRandomColor());
randPan.setPreferredSize(d);
center.add(randPan, BorderLayout.WEST);
userPanel = new JPanel(); // adjustable color panel
userPanel.setBackground(model.getUserColor());
userPanel.setPreferredSize(d);
center.add(userPanel, BorderLayout.EAST);
/** BUTTONS **/
JPanel buttonPanel = new JPanel();
panel.add(buttonPanel, BorderLayout.SOUTH);
// This Object array makes it possible to create the JButtons in a loop
// buttonObject[0] - JButton labels
// buttonObject[1] - JButton action commands
// buttonObject[2] - JButton background colors
// buttonObject[3] - JButton foreground colors
Object[][] buttonObject = new Object[][] { { "+", "-", "+", "-", "+", "-" },
{ "red", "red", "green", "green", "blue", "blue" },
{ Color.RED, Color.RED, Color.GREEN,
Color.GREEN, Color.BLUE, Color.BLUE },
{ Color.WHITE, Color.WHITE, Color.BLACK,
Color.BLACK, Color.WHITE, Color.WHITE } };
Dimension b = new Dimension(50, 50); // button size
ButtonListener listener = new ButtonListener();
for (int i = 0; i < buttonObject[0].length; i++) {
JButton button = new JButton((String) buttonObject[0][i]);
button.setActionCommand((String) buttonObject[1][i]);
button.setBackground((Color) buttonObject[2][i]);
button.setForeground((Color) buttonObject[3][i]);
button.setPreferredSize(b);
button.setFocusPainted(false);
button.addActionListener(listener);
buttonPanel.add(button);
}
return panel;
}
public void setUserPanelColor() {
userPanel.setBackground(model.getUserColor());
}
public void printSolution() {
// This is just to show what the RGB
// values are so you can easily solve
System.out.println("SOLUTION: " + model.getRandomColor());
}
// main method
public static void main(String[] args) {
try {
String laf = UIManager.getCrossPlatformLookAndFeelClassName();
UIManager.setLookAndFeel(laf);
} catch (Exception e) {
e.printStackTrace();
}
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new GuessColor();
}
});
}
}
J'ai apporté pas mal de changements à votre code. Voici les changements majeurs que je souhaite souligner.
Dans la
mainméthode, j'ai ajouté une.printStackTrace();aucatchbloc. Vous devez toujours imprimer ou enregistrer les erreurs.J'ai séparé le code pour construire le
JFramedu code pour construire le mainJPanel. Cela me permet de me concentrer sur une partie de l'interface graphique à la fois.J'ai utilisé un
JFrame. Le seul moment où vous devez étendre un composant Swing, ou une classe Java, est lorsque vous souhaitez remplacer une ou plusieurs méthodes de classe.J'ai déplacé presque toutes les
GuessColorvariables de classe vers leurs méthodes respectives. Les seules variables de classe qui restent en tant que variables de classe sont les variables utilisées dans plus d'une méthode.J'ai créé un
Objecttableau certes complexe afin de pouvoir créer leJButtonsdans une boucle.
Enfin, j'ai créé le fichier ActionListener. J'ai pu déplacer la checkméthode dans le ActionListener.
public class ButtonListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent event) {
JButton button = (JButton) event.getSource();
String text = button.getText();
String action = event.getActionCommand();
Color color = model.getUserColor();
int red = color.getRed();
int green = color.getGreen();
int blue = color.getBlue();
if (action.equals("red")) {
if (text.equals("+")) {
red += 15;
red = Math.min(255, red);
model.setUserColor(red, green, blue);
} else {
red -= 15;
red = Math.max(0, red);
model.setUserColor(red, green, blue);
}
} else if (action.equals("green")) {
if (text.equals("+")) {
green += 15;
green = Math.min(255, green);
model.setUserColor(red, green, blue);
} else {
green -= 15;
green = Math.max(0, green);
model.setUserColor(red, green, blue);
}
} else if (action.equals("blue")) {
if (text.equals("+")) {
blue += 15;
blue = Math.min(255, blue);
model.setUserColor(red, green, blue);
} else {
blue -= 15;
blue = Math.max(0, blue);
model.setUserColor(red, green, blue);
}
}
setUserPanelColor();
System.out.println(model.getUserColor());
check();
}
// checks if the color panels are the same and displays
// winning message if they are the same
private void check() {
if (model.getRandomColor().equals(model.getUserColor())) {
int choose = JOptionPane.showConfirmDialog(frame,
"You win! Play again?");
if (choose == JOptionPane.YES_OPTION) {
model.createColors();
setUserPanelColor();
printSolution();
} else if (choose == JOptionPane.NO_OPTION) {
System.exit(0);
}
}
}
}
Voici le code exécutable complet. J'espère que cette explication vous aidera.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
public class GuessColor {
private GameModel model;
private JFrame frame;
private JPanel userPanel;
public GuessColor() {
this.model = new GameModel();
this.model.createColors();
frame = new JFrame("Match the color!");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createMainPanel(), BorderLayout.CENTER);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setResizable(false);
frame.setVisible(true);
printSolution();
}
// sets up the frame and functionality of UI
private JPanel createMainPanel() {
JPanel panel = new JPanel(new BorderLayout());
JLabel title = new JLabel("Match The Color!", JLabel.CENTER);
Font font = new Font("Times New Roman", Font.BOLD, 30);
title.setFont(font);
title.setBackground(Color.BLACK);
title.setForeground(Color.WHITE);
title.setOpaque(true);
panel.add(title, BorderLayout.NORTH);
JPanel center = new JPanel(new BorderLayout());
center.setBackground(Color.CYAN);
panel.add(center, BorderLayout.CENTER);
Dimension d = new Dimension(500, 500); // color panel size
JPanel randPan = new JPanel(); // random color panel
randPan.setBackground(model.getRandomColor());
randPan.setPreferredSize(d);
center.add(randPan, BorderLayout.WEST);
userPanel = new JPanel(); // adjustable color panel
userPanel.setBackground(model.getUserColor());
userPanel.setPreferredSize(d);
center.add(userPanel, BorderLayout.EAST);
/** BUTTONS **/
JPanel buttonPanel = new JPanel();
panel.add(buttonPanel, BorderLayout.SOUTH);
// This Object array makes it possible to create the JButtons in a loop
// buttonObject[0] - JButton labels
// buttonObject[1] - JButton action commands
// buttonObject[2] - JButton background colors
// buttonObject[3] - JButton foreground colors
Object[][] buttonObject = new Object[][] { { "+", "-", "+", "-", "+", "-" },
{ "red", "red", "green", "green", "blue", "blue" },
{ Color.RED, Color.RED, Color.GREEN,
Color.GREEN, Color.BLUE, Color.BLUE },
{ Color.WHITE, Color.WHITE, Color.BLACK,
Color.BLACK, Color.WHITE, Color.WHITE } };
Dimension b = new Dimension(50, 50); // button size
ButtonListener listener = new ButtonListener();
for (int i = 0; i < buttonObject[0].length; i++) {
JButton button = new JButton((String) buttonObject[0][i]);
button.setActionCommand((String) buttonObject[1][i]);
button.setBackground((Color) buttonObject[2][i]);
button.setForeground((Color) buttonObject[3][i]);
button.setPreferredSize(b);
button.setFocusPainted(false);
button.addActionListener(listener);
buttonPanel.add(button);
}
return panel;
}
public void setUserPanelColor() {
userPanel.setBackground(model.getUserColor());
}
public void printSolution() {
// This is just to show what the RGB
// values are so you can easily solve
System.out.println("SOLUTION: " + model.getRandomColor());
}
// main method
public static void main(String[] args) {
try {
String laf = UIManager.getCrossPlatformLookAndFeelClassName();
UIManager.setLookAndFeel(laf);
} catch (Exception e) {
e.printStackTrace();
}
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new GuessColor();
}
});
}
public class ButtonListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent event) {
JButton button = (JButton) event.getSource();
String text = button.getText();
String action = event.getActionCommand();
Color color = model.getUserColor();
int red = color.getRed();
int green = color.getGreen();
int blue = color.getBlue();
if (action.equals("red")) {
if (text.equals("+")) {
red += 15;
red = Math.min(255, red);
model.setUserColor(red, green, blue);
} else {
red -= 15;
red = Math.max(0, red);
model.setUserColor(red, green, blue);
}
} else if (action.equals("green")) {
if (text.equals("+")) {
green += 15;
green = Math.min(255, green);
model.setUserColor(red, green, blue);
} else {
green -= 15;
green = Math.max(0, green);
model.setUserColor(red, green, blue);
}
} else if (action.equals("blue")) {
if (text.equals("+")) {
blue += 15;
blue = Math.min(255, blue);
model.setUserColor(red, green, blue);
} else {
blue -= 15;
blue = Math.max(0, blue);
model.setUserColor(red, green, blue);
}
}
setUserPanelColor();
System.out.println(model.getUserColor());
check();
}
// checks if the color panels are the same and displays
// winning message if they are the same
private void check() {
if (model.getRandomColor().equals(model.getUserColor())) {
int choose = JOptionPane.showConfirmDialog(frame,
"You win! Play again?");
if (choose == JOptionPane.YES_OPTION) {
model.createColors();
setUserPanelColor();
printSolution();
} else if (choose == JOptionPane.NO_OPTION) {
System.exit(0);
}
}
}
}
public class GameModel {
private Color randomColor;
private Color userColor;
private final Random random;
public GameModel() {
this.random = new Random();
}
public void createColors() {
setRandomColor();
setUserColor();
}
public Color getUserColor() {
return userColor;
}
public void setUserColor() {
int userRed = 0;
int userGrn = 0;
int userBlu = 0;
this.userColor = new Color(userRed, userGrn, userBlu);
}
public void setUserColor(int red, int green, int blue) {
this.userColor = new Color(red, green, blue);
}
public Color getRandomColor() {
return randomColor;
}
public void setRandomColor() {
int randRed = (random.nextInt(17) + 1) * 15;
int randGrn = (random.nextInt(17) + 1) * 15;
int randBlu = (random.nextInt(17) + 1) * 15;
this.randomColor = new Color(randRed, randGrn, randBlu);
}
}
}
Modifié pour ajouter: j'ai rendu le jeu plus accessible aux jeunes joueurs en ajoutant un écran RVB pour chaque couleur.
Voici l'interface graphique.
Voici le code exécutable complet révisé.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
public class GuessColor {
private DisplayPanel randomDisplayPanel;
private DisplayPanel userDisplayPanel;
private GameModel model;
private JFrame frame;
private JPanel randomPanel;
private JPanel userPanel;
public GuessColor() {
this.model = new GameModel();
this.model.createColors();
frame = new JFrame("Match the color!");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createMainPanel(), BorderLayout.CENTER);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setResizable(false);
frame.setVisible(true);
}
// sets up the frame and functionality of UI
private JPanel createMainPanel() {
JPanel panel = new JPanel(new BorderLayout());
JLabel title = new JLabel("Match The Color!", JLabel.CENTER);
Font font = new Font("Times New Roman", Font.BOLD, 30);
title.setFont(font);
title.setBackground(Color.BLACK);
title.setForeground(Color.WHITE);
title.setOpaque(true);
panel.add(title, BorderLayout.NORTH);
JPanel center = new JPanel(new BorderLayout());
center.setBackground(Color.CYAN);
panel.add(center, BorderLayout.CENTER);
Dimension d = new Dimension(500, 500); // color panel size
randomPanel = new JPanel(new BorderLayout()); // random color panel
randomPanel.setBackground(model.getRandomColor());
randomPanel.setPreferredSize(d);
randomDisplayPanel = new DisplayPanel(model.getRandomColor());
randomPanel.add(randomDisplayPanel.getPanel(), BorderLayout.NORTH);
center.add(randomPanel, BorderLayout.WEST);
userPanel = new JPanel(new BorderLayout()); // adjustable color panel
userPanel.setBackground(model.getUserColor());
userPanel.setPreferredSize(d);
userDisplayPanel = new DisplayPanel(model.getUserColor());
userPanel.add(userDisplayPanel.getPanel(), BorderLayout.NORTH);
center.add(userPanel, BorderLayout.EAST);
/** BUTTONS **/
JPanel buttonPanel = new JPanel();
panel.add(buttonPanel, BorderLayout.SOUTH);
// This Object array makes it possible to create the JButtons in a loop
// buttonObject[0] - JButton labels
// buttonObject[1] - JButton action commands
// buttonObject[2] - JButton background colors
// buttonObject[3] - JButton foreground colors
Object[][] buttonObject = new Object[][] { { "+", "-", "+", "-", "+", "-" },
{ "red", "red", "green", "green", "blue", "blue" },
{ Color.RED, Color.RED, Color.GREEN,
Color.GREEN, Color.BLUE, Color.BLUE },
{ Color.WHITE, Color.WHITE, Color.BLACK,
Color.BLACK, Color.WHITE, Color.WHITE } };
Dimension b = new Dimension(50, 50); // button size
ButtonListener listener = new ButtonListener();
for (int i = 0; i < buttonObject[0].length; i++) {
JButton button = new JButton((String) buttonObject[0][i]);
button.setActionCommand((String) buttonObject[1][i]);
button.setBackground((Color) buttonObject[2][i]);
button.setForeground((Color) buttonObject[3][i]);
button.setPreferredSize(b);
button.setFocusPainted(false);
button.addActionListener(listener);
buttonPanel.add(button);
}
return panel;
}
public void setRandomPanelColor() {
randomPanel.setBackground(model.getRandomColor());
randomDisplayPanel.setColor(model.getRandomColor());
}
public void setUserPanelColor() {
userPanel.setBackground(model.getUserColor());
userDisplayPanel.setColor(model.getUserColor());
}
// main method
public static void main(String[] args) {
try {
String laf = UIManager.getCrossPlatformLookAndFeelClassName();
UIManager.setLookAndFeel(laf);
} catch (Exception e) {
e.printStackTrace();
}
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new GuessColor();
}
});
}
public class DisplayPanel {
private JPanel panel;
private JTextField redField;
private JTextField greenField;
private JTextField blueField;
public DisplayPanel(Color color) {
createJPanel();
setColor(color);
}
private void createJPanel() {
panel = new JPanel(new GridBagLayout());
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.LINE_START;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.insets = new Insets(5, 5, 5, 5);
gbc.gridx = 0;
gbc.gridy = 0;
JLabel redLabel = new JLabel("Red:");
redLabel.setForeground(Color.WHITE);
panel.add(redLabel, gbc);
gbc.gridx++;
redField = new JTextField(3);
redField.setEditable(false);
redField.setHorizontalAlignment(JTextField.TRAILING);
panel.add(redField, gbc);
gbc.gridx = 0;
gbc.gridy++;
JLabel greenLabel = new JLabel("Green:");
greenLabel.setForeground(Color.WHITE);
panel.add(greenLabel, gbc);
gbc.gridx++;
greenField = new JTextField(3);
greenField.setEditable(false);
greenField.setHorizontalAlignment(JTextField.TRAILING);
panel.add(greenField, gbc);
gbc.gridx = 0;
gbc.gridy++;
JLabel blueLabel = new JLabel("Blue:");
blueLabel.setForeground(Color.WHITE);
panel.add(blueLabel, gbc);
gbc.gridx++;
blueField = new JTextField(3);
blueField.setEditable(false);
blueField.setHorizontalAlignment(JTextField.TRAILING);
panel.add(blueField, gbc);
}
public JPanel getPanel() {
return panel;
}
public void setColor(Color color) {
panel.setBackground(color);
redField.setText(Integer.toString(color.getRed()));
greenField.setText(Integer.toString(color.getGreen()));
blueField.setText(Integer.toString(color.getBlue()));
}
}
public class ButtonListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent event) {
JButton button = (JButton) event.getSource();
String text = button.getText();
String action = event.getActionCommand();
Color color = model.getUserColor();
int red = color.getRed();
int green = color.getGreen();
int blue = color.getBlue();
if (action.equals("red")) {
if (text.equals("+")) {
red += 15;
red = Math.min(255, red);
} else {
red -= 15;
red = Math.max(0, red);
}
} else if (action.equals("green")) {
if (text.equals("+")) {
green += 15;
green = Math.min(255, green);
} else {
green -= 15;
green = Math.max(0, green);
}
} else if (action.equals("blue")) {
if (text.equals("+")) {
blue += 15;
blue = Math.min(255, blue);
} else {
blue -= 15;
blue = Math.max(0, blue);
}
}
model.setUserColor(red, green, blue);
setUserPanelColor();
check();
}
// checks if the color panels are the same and displays
// winning message if they are the same
private void check() {
if (model.getRandomColor().equals(model.getUserColor())) {
int choose = JOptionPane.showConfirmDialog(frame,
"You win! Play again?");
if (choose == JOptionPane.YES_OPTION) {
model.createColors();
setRandomPanelColor();
setUserPanelColor();
} else if (choose == JOptionPane.NO_OPTION) {
frame.dispose();
System.exit(0);
}
}
}
}
public class GameModel {
private Color randomColor;
private Color userColor;
private final Random random;
public GameModel() {
this.random = new Random();
}
public void createColors() {
setRandomColor();
setUserColor();
}
public Color getUserColor() {
return userColor;
}
public void setUserColor() {
int userRed = 135;
int userGrn = 135;
int userBlu = 135;
this.userColor = new Color(userRed, userGrn, userBlu);
}
public void setUserColor(int red, int green, int blue) {
this.userColor = new Color(red, green, blue);
}
public Color getRandomColor() {
return randomColor;
}
public void setRandomColor() {
int randRed = (random.nextInt(17) + 1) * 15;
int randGrn = (random.nextInt(17) + 1) * 15;
int randBlu = (random.nextInt(17) + 1) * 15;
this.randomColor = new Color(randRed, randGrn, randBlu);
}
}
}
La plupart de ce que je changerais au premier passage est de définir correctement et de limiter la portée de vos objets pour faciliter la lecture et la réflexion sur le code. (Je changerais plus aussi, mais je voulais juste vous faire part de vos commentaires dans ce domaine pour l'instant)
Vous pouvez sauter toute initGui()chose et de définir simplement les éléments de niveau supérieur ( title, center, butPan) en tant que membres de la classe, puis en utilisant initialiseur les blocs afin qu'ils sont créés et mis en place la façon dont vous voulez, y compris leurs enfants. Les blocs d'initialisation et le constructeur sont appelés dans l'ordre des fichiers. (voir ma version ci-dessous)
Lorsque vous avez une méthode longue, ce n'est pas toujours le signe d'un problème. Mais lorsque vous le faites, il peut être utile d'utiliser des blocs de portée pour limiter les endroits où les choses sont visibles. Il est simplement plus facile de dire en un coup d'œil que des sections entières du code ne définissent pas les variables qui auront une importance plus tard dans la méthode longue. (J'ai donc utilisé ceci dans le bloc d'initialisation butPanci-dessous).
En dehors de cela, vous avez staticbeaucoup de choses qui ne semblent pas statiques car elles appartiennent au jeu en cours. C'est pourquoi vous avez une resetméthode qui ne fait que tout réinitialiser - mais c'est normalement plus facile et moins sujet aux erreurs si vous ne faites qu'une toute nouvelle instance pour un nouveau jeu.
Voici où je suis arrivé jusqu'ici. J'espère que cela aide, même si je suppose que je n'ai pas vraiment répondu à votre question sur la façon de mieux gérer la création des boutons.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class GuessColor extends JFrame {
private static final long serialVersionUID = 1L;
private static final Font font = new Font("Times New Roman", Font.BOLD, 30);
private static final Dimension d = new Dimension(500, 500); // color panel size
private static final Dimension b = new Dimension(50, 50); // button size
private static final Random rand = new Random();
private Color userColor = new Color(0, 0, 0);
private Color goalColor = randomColor();
private JLabel title = new JLabel("Match The Color!", JLabel.CENTER);
{
this.add(title, BorderLayout.NORTH);
title.setFont(font);
title.setBackground(Color.BLACK);
title.setForeground(Color.WHITE);
title.setOpaque(true);
}
private JPanel center = new JPanel();
{
this.add(center, BorderLayout.CENTER);
center.setBackground(Color.CYAN);
}
private JPanel randPan = new JPanel(); // random color panel
{
center.add(randPan, BorderLayout.EAST);
randPan.setBackground(goalColor);
randPan.setPreferredSize(d);
}
private JPanel userPan = new JPanel(); // adjustable color panel
{
center.add(userPan, BorderLayout.WEST);
userPan.setBackground(userColor);
userPan.setPreferredSize(d);
}
private JPanel butPan = new JPanel();
{
this.add(butPan, BorderLayout.SOUTH);
{
JButton addRed = new JButton("+");
addRed.setBackground(Color.RED);
addRed.setPreferredSize(b);
addRed.setFocusPainted(false);
addRed.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
increaseRed();
userPan.setBackground(userColor);
repaint();
check();
}
});
butPan.add(addRed);
}
{
JButton subRed = new JButton("-");
subRed.setBackground(Color.RED);
subRed.setPreferredSize(b);
subRed.setFocusPainted(false);
subRed.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
decreaseRed();
userPan.setBackground(userColor);
repaint();
check();
}
});
butPan.add(subRed);
}
{
JButton addGrn = new JButton("+");
addGrn.setBackground(Color.GREEN);
addGrn.setPreferredSize(b);
addGrn.setFocusPainted(false);
addGrn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
increaseGrn();
userPan.setBackground(userColor);
repaint();
check();
}
});
butPan.add(addGrn);
}
{
JButton subGrn = new JButton("-");
subGrn.setBackground(Color.GREEN);
subGrn.setPreferredSize(b);
subGrn.setFocusPainted(false);
subGrn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
decreaseGrn();
userPan.setBackground(userColor);
repaint();
check();
}
});
butPan.add(subGrn);
}
{
JButton addBlu = new JButton("+");
addBlu.setBackground(Color.BLUE);
addBlu.setPreferredSize(b);
addBlu.setFocusPainted(false);
addBlu.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
increaseBlu();
userPan.setBackground(userColor);
repaint();
check();
}
});
butPan.add(addBlu);
}
{
JButton subBlu = new JButton("-");
subBlu.setBackground(Color.BLUE);
subBlu.setPreferredSize(b);
subBlu.setFocusPainted(false);
subBlu.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
decreaseBlu();
userPan.setBackground(userColor);
repaint();
check();
}
});
butPan.add(subBlu);
}
}
public GuessColor() {
System.out.println("SOLUTION: " + goalColor);
this.setTitle("Match the color!");
this.pack();
this.setLocationRelativeTo(null);
this.setVisible(true);
this.setResizable(false);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
}
private Color randomColor() {
return new Color((rand.nextInt(17) + 1) * 15, (rand.nextInt(17) + 1) * 15,
(rand.nextInt(17) + 1) * 15);
}
private void increaseRed() {
if (userColor.getRed() < 255) {
userColor = new Color(userColor.getRed() + 15, userColor.getGreen(),
userColor.getBlue());
}
}
private void increaseGrn() {
if (userColor.getGreen() < 255) {
userColor = new Color(userColor.getRed(), userColor.getGreen() + 15,
userColor.getBlue());
}
}
private void increaseBlu() {
if (userColor.getBlue() < 255) {
userColor = new Color(userColor.getRed(), userColor.getGreen() + 15,
userColor.getBlue() + 15);
}
}
private void decreaseRed() {
if (userColor.getRed() > 0) {
userColor = new Color(userColor.getRed() - 15, userColor.getGreen() + 15,
userColor.getBlue());
}
}
private void decreaseGrn() {
if (userColor.getGreen() > 0) {
userColor = new Color(userColor.getRed(), userColor.getGreen() - 15,
userColor.getBlue());
}
}
private void decreaseBlu() {
if (userColor.getBlue() > 0) {
userColor = new Color(userColor.getRed(), userColor.getGreen(),
userColor.getBlue() - 15);
}
}
private void check() {
if (userColor.equals(goalColor)) {
int choose = JOptionPane.showConfirmDialog(null, "You win! Play again?");
if (choose == JOptionPane.YES_OPTION) {
this.dispose();
new GuessColor();
} else if (choose == JOptionPane.NO_OPTION) {
System.exit(0);
}
}
}
public static void main(String[] args)
throws ClassNotFoundException, InstantiationException, IllegalAccessException,
UnsupportedLookAndFeelException {
UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new GuessColor();
}
});
}
}
En m'appuyant sur ma réponse précédente , je vais maintenant aborder la simplification de la création des boutons.
L'essentiel ici est que vous ayez du code qui se répète, nous pouvons donc extraire cette logique d'une fonction et paramétrer les parties qui changent. ( createGameButton)
Les ActionListeners que vous créez appellent simplement leurs méthodes respectives - c'est un peu inutile car nous pouvons simplement placer ces instructions pour l'ActionListener directement là où nous les définissons. Cela permet également de ne pas avoir besoin de nommer les boutons lorsque nous n'y faisons référence qu'une seule fois. ( butPanbloc d'initialisation)
Enfin, les bits qui sont appelés à chaque fois par la suite peuvent entrer dans une méthode, et simplement appeler cette méthode. ( update)
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class GuessColor extends JFrame {
private static final long serialVersionUID = 1L;
private static final Font font = new Font("Times New Roman", Font.BOLD, 30);
private static final Dimension d = new Dimension(500, 500); // color panel size
private static final Dimension b = new Dimension(50, 50); // button size
private static final Random rand = new Random();
private Color userColor = new Color(0, 0, 0);
private Color goalColor = randomColor();
private JLabel title = new JLabel("Match The Color!", JLabel.CENTER);
{
this.add(title, BorderLayout.NORTH);
title.setFont(font);
title.setBackground(Color.BLACK);
title.setForeground(Color.WHITE);
title.setOpaque(true);
}
private JPanel center = new JPanel();
{
this.add(center, BorderLayout.CENTER);
center.setBackground(Color.CYAN);
}
private JPanel randPan = new JPanel(); // random color panel
{
center.add(randPan, BorderLayout.EAST);
randPan.setBackground(goalColor);
randPan.setPreferredSize(d);
}
private JPanel userPan = new JPanel(); // adjustable color panel
{
center.add(userPan, BorderLayout.WEST);
userPan.setBackground(userColor);
userPan.setPreferredSize(d);
}
private JPanel butPan = new JPanel();
{
this.add(butPan, BorderLayout.SOUTH);
butPan.add(createGameButton(Color.RED, "+", new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (userColor.getRed() < 255) {
userColor = new Color(userColor.getRed() + 15, userColor.getGreen(),
userColor.getBlue());
}
update();
}
}));
butPan.add(createGameButton(Color.RED, "-", new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (userColor.getRed() > 0) {
userColor = new Color(userColor.getRed() - 15, userColor.getGreen(),
userColor.getBlue());
}
update();
}
}));
butPan.add(createGameButton(Color.GREEN, "+", new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (userColor.getGreen() < 255) {
userColor = new Color(userColor.getRed(), userColor.getGreen() + 15,
userColor.getBlue());
}
update();
}
}));
butPan.add(createGameButton(Color.GREEN, "-", new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (userColor.getGreen() > 0) {
userColor = new Color(userColor.getRed(), userColor.getGreen() - 15,
userColor.getBlue());
}
update();
}
}));
butPan.add(createGameButton(Color.BLUE, "+", new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (userColor.getBlue() < 255) {
userColor = new Color(userColor.getRed(), userColor.getGreen(),
userColor.getBlue() + 15);
}
update();
}
}));
butPan.add(createGameButton(Color.BLUE, "-", new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (userColor.getBlue() > 0) {
userColor = new Color(userColor.getRed(), userColor.getGreen(),
userColor.getBlue() - 15);
}
}
}));
}
public GuessColor() {
System.out.println("SOLUTION: " + goalColor);
this.setTitle("Match the color!");
this.pack();
this.setLocationRelativeTo(null);
this.setVisible(true);
this.setResizable(false);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
}
private Color randomColor() {
return new Color((rand.nextInt(17) + 1) * 15, (rand.nextInt(17) + 1) * 15,
(rand.nextInt(17) + 1) * 15);
}
private JButton createGameButton(Color color, String label, ActionListener listener) {
JButton button = new JButton(label);
button.setBackground(color);
button.setPreferredSize(b);
button.setFocusPainted(false);
button.addActionListener(listener);
return button;
}
private void update() {
userPan.setBackground(userColor);
repaint();
check();
}
private void check() {
if (userColor.equals(goalColor)) {
int choose = JOptionPane.showConfirmDialog(null, "You win! Play again?");
if (choose == JOptionPane.YES_OPTION) {
this.dispose();
new GuessColor();
} else if (choose == JOptionPane.NO_OPTION) {
System.exit(0);
}
}
}
public static void main(String[] args)
throws ClassNotFoundException, InstantiationException, IllegalAccessException,
UnsupportedLookAndFeelException {
UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new GuessColor();
}
});
}
}