问题
Stuck on a problem that requires grabbing a boolean
variable from another class.
I have the following for-loop
, boolea
n and if-else
statements
import java.awt.*;
import javax.swing.*;
import java.awt.Color.*;
import java.awt.event.MouseListener;
import java.awt.event.MouseEvent;
import java.util.Random;
public class Checkers extends JFrame
{
Random random = new Random();
private final int ROWS = 2;
private final int COLS = 5;
private final int GAP = 2;
private final int NUM = ROWS * COLS;
private int i;
private int score;
private JPanel pane = new JPanel(new GridLayout(ROWS,COLS, GAP,GAP));
private JPanel pane2 = new JPanel();
private JPanel pane3 = new JPanel();
private JButton btn1 = new JButton("Play A Game");
private JButton btn2 = new JButton("Exit");
private JButton btn3 = new JButton("Easy");
private JButton btn4 = new JButton("Intermediate");
private JButton btn5 = new JButton("Difficult");
private JLabel lbl1 = new JLabel ("score: " + score);
private JLabel gameLost = new JLabel("You lose! You got: " + score + " points");
private JButton btnRestart = new JButton("Restart");
private MyPanel [] panel = new MyPanel[NUM];
private Color col1 = Color.RED;
private Color col2 = Color.WHITE;
private Color col3 = Color.GREEN;
private Color tempColor;
private boolean isPanelDisabled;
//Starts the checkers GUI, calling the constructor below this.
public static void main(String[] args){
new Checkers();
}
//Sets the dimensions of the GUI, visibility, background color and
//contents via the setBoard();
public Checkers()
{
super("Checkers");
setSize(600,600);
setVisible(true);
setBackground(Color.BLACK);
setBoard();
}
//Makes the grid, contains a conditional boolean, adds the panels to grid based on i value.
//sets Colours accordingly
public void setBoard()
{
boolean isPanelDisabled = false;
for (int i = 0; i < panel.length; i++) {
panel[i] = new MyPanel(this);
pane.add(panel[i]);
if (i % COLS == 0) {
tempColor = col1;
}
if (i == 9 || i <8) {
panel[i].setBackground(col1);
}
if(i == 8){
isPanelDisabled = true;
panel[i].setBackground(col3);
}
}
//pane background colour and the size of this pane.
pane.setBackground(Color.BLACK);
pane.setPreferredSize(new Dimension(300,300));
//pane background colour and size of this pane.
pane2.setBackground(Color.white);
pane2.setPreferredSize(new Dimension(300,300));
//directions on the board where these panes appear.
add(pane, BorderLayout.WEST);
add(pane2, BorderLayout.EAST);
pane2.add(lbl1);
pane2.add(btnRestart);
btnRestart.addActionListener( e -> restartBoard());
pane2.setLayout(new BoxLayout(pane2, BoxLayout.PAGE_AXIS));
}
//increments the score for the user based on current points.
public void incrementScore(){
if (score != 5){
score++;
lbl1.setText("Score: " + Integer.toString(score));
}
else if(score == 5){
lbl1.setText("Congratulations!, you've won!, your score is:" + score);
}
}
}
and this mouseClicked
Event
import java.awt.Color;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.*;
import java.awt.event.*;
import javax.swing.JPanel;
public class MyPanel extends JPanel implements MouseListener, ActionListener {
private final Checkers checkers;
private boolean isPanelDisabled;
//MyPanel Constructor that initiates a instance of checkers.
public MyPanel(Checkers checkers) {
this.checkers = checkers;
addMouseListener(this);
}
@Override
public void actionPerformed(ActionEvent e){
}
// Sets the panel colours according to their int number and the boolean condiiton.
@Override
public void mouseClicked(MouseEvent e) {
if (isPanelDisabled == true){
setBackground(Color.CYAN);
}
else{
setBackground(Color.BLACK);
checkers.incrementScore();
}
}
My Expected result of this should be that if the user clicks the 8th panel in that grid, then the color of that panel will be cyan when pressed and not black, but it cant access the boolean variable? where am i going wrong here?
回答1:
Your question involves communication between objects of different classes, and there are several ways to do this, but most basic is to call a method of an object in one class to the other.
First lets set up the problem,... I've created classes called MyPanel2 and Checkers2, to distinguish them from yours.
Say in MyPanel2 we have a Checkers2 field and a boolean field called selected that is set to false:
private Checkers2 checkers;
private boolean selected = false;
along with appropriate boolean getter and setter:
public void setSelected(boolean selected) {
this.selected = selected;
}
public boolean isSelected() {
return selected;
}
And say within the Checkers2 class you have a 10 instances of MyPanel2 held within an array, and you want the user to be able to "select" instances of the class, but only allow 7 of them to be selected, and assume that you want to user the set up that you're currently using, you could give the main class, a method, public boolean isPanelDisabled()
, and have the MyPanel2 class call this method to determine if selection is allowed. So within MyPanel2 you could have a MouseListener with something like:
@Override
public void mousePressed(MouseEvent e) {
if (selected) {
return;
}
// call the Checkers2 boolean method to check
if (checkers.isPanelDisabled()) {
setBackground(DISABLED_COLOR);
} else {
setBackground(SELECTED_COLOR);
setSelected(true);
}
}
Within Checkers2 .isPanelDisabled()
method you'd iterate through the array of MyPanel2 instances to see how many have been selected, something like this could work:
public boolean isPanelDisabled() {
int count = 0;
for (MyPanel2 panel2 : myPanels) {
if (panel2.isSelected()) {
count++;
}
}
return count >= MAX_COUNT;
}
The whole MCVE testable code could look like:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Checkers2 extends JFrame {
private static final int MAX_COUNT = 7;
private final int ROWS = 2;
private final int COLS = 5;
private final int GAP = 2;
private final int NUM = ROWS * COLS;
private MyPanel2[] myPanels = new MyPanel2[NUM];
public Checkers2() {
super("Checkers");
setDefaultCloseOperation(EXIT_ON_CLOSE);
JPanel gridPanel = new JPanel(new GridLayout(ROWS, COLS, 1, 1));
gridPanel.setBackground(Color.BLACK);
gridPanel.setBorder(BorderFactory.createLineBorder(Color.BLACK));
for (int i = 0; i < myPanels.length; i++) {
MyPanel2 myPanel = new MyPanel2(this);
gridPanel.add(myPanel);
myPanels[i] = myPanel;
}
JButton resetButton = new JButton("Reset");
resetButton.setMnemonic(KeyEvent.VK_R);
resetButton.addActionListener(evt -> {
for (MyPanel2 myPanel2 : myPanels) {
myPanel2.reset();
}
});
JButton exitButton = new JButton("Exit");
exitButton.setMnemonic(KeyEvent.VK_X);
exitButton.addActionListener(evt -> System.exit(0));
JPanel buttonPanel = new JPanel();
buttonPanel.add(resetButton);
add(gridPanel);
add(buttonPanel, BorderLayout.PAGE_END);
pack();
setLocationRelativeTo(null);
}
public boolean isPanelDisabled() {
int count = 0;
for (MyPanel2 panel2 : myPanels) {
if (panel2.isSelected()) {
count++;
}
}
return count >= MAX_COUNT;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
new Checkers2().setVisible(true);
});
}
}
class MyPanel2 extends JPanel {
private static final int PREF_W = 200;
private static final int PREF_H = PREF_W;
private static final int GR = 240;
public static final Color BASE_COLOR = new Color(GR, GR, GR);
public static final Color DISABLED_COLOR = Color.CYAN;
public static final Color SELECTED_COLOR = Color.BLACK;
private Checkers2 checkers;
private boolean selected = false;
public MyPanel2(Checkers2 checkers) {
setBackground(BASE_COLOR);
this.checkers = checkers;
setPreferredSize(new Dimension(PREF_W, PREF_H));
addMouseListener(new MyMouse());
}
public void setSelected(boolean selected) {
this.selected = selected;
}
public boolean isSelected() {
return selected;
}
public void reset() {
setBackground(BASE_COLOR);
setSelected(false);
}
private class MyMouse extends MouseAdapter {
@Override
public void mousePressed(MouseEvent e) {
if (selected) {
return;
}
if (checkers.isPanelDisabled()) {
setBackground(DISABLED_COLOR);
} else {
setBackground(SELECTED_COLOR);
setSelected(true);
}
}
}
}
Another Option is to take all the logic out of MyPanel and put it into the main program, something like:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
@SuppressWarnings("serial")
public class Checkers3 extends JPanel {
private static final int MAX_COUNT = 7;
private final int ROWS = 2;
private final int COLS = 5;
private final int GAP = 2;
private final int NUM = ROWS * COLS;
private MyPanel3[] myPanels = new MyPanel3[NUM];
public Checkers3() {
JPanel gridPanel = new JPanel(new GridLayout(ROWS, COLS, 1, 1));
gridPanel.setBackground(Color.BLACK);
gridPanel.setBorder(BorderFactory.createLineBorder(Color.BLACK));
MyMouse myMouse = new MyMouse();
for (int i = 0; i < myPanels.length; i++) {
MyPanel3 myPanel = new MyPanel3();
myPanel.addMouseListener(myMouse);
gridPanel.add(myPanel);
myPanels[i] = myPanel;
}
JButton resetButton = new JButton("Reset");
resetButton.setMnemonic(KeyEvent.VK_R);
resetButton.addActionListener(evt -> {
for (MyPanel3 myPanel : myPanels) {
myPanel.reset();
}
});
JButton exitButton = new JButton("Exit");
exitButton.setMnemonic(KeyEvent.VK_X);
exitButton.addActionListener(evt -> System.exit(0));
JPanel buttonPanel = new JPanel();
buttonPanel.add(resetButton);
setLayout(new BorderLayout());
add(gridPanel);
add(buttonPanel, BorderLayout.PAGE_END);
}
public boolean isPanelDisabled() {
int count = 0;
for (MyPanel3 panel : myPanels) {
if (panel.isSelected()) {
count++;
}
}
return count >= MAX_COUNT;
}
private class MyMouse extends MouseAdapter {
@Override
public void mousePressed(MouseEvent e) {
MyPanel3 myPanel = (MyPanel3) e.getSource();
if (myPanel.isSelected()) {
return; // it's already selected
} else if (isPanelDisabled()) {
myPanel.setSelected(false);
} else {
myPanel.setSelected(true);
}
}
}
private static void createAndShowGui() {
Checkers3 mainPanel = new Checkers3();
JFrame frame = new JFrame("Checkers");
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());
}
}
@SuppressWarnings("serial")
class MyPanel3 extends JPanel {
private static final int PREF_W = 200;
private static final int PREF_H = PREF_W;
private static final int GR = 240;
public static final Color BASE_COLOR = new Color(GR, GR, GR);
public static final Color DISABLED_COLOR = Color.CYAN;
public static final Color SELECTED_COLOR = Color.BLACK;
private boolean selected = false;
public MyPanel3() {
setBackground(BASE_COLOR);
setPreferredSize(new Dimension(PREF_W, PREF_H));
}
public void setSelected(boolean selected) {
this.selected = selected;
Color background = selected ? SELECTED_COLOR : DISABLED_COLOR;
setBackground(background);
}
public boolean isSelected() {
return selected;
}
public void reset() {
setSelected(false);
setBackground(BASE_COLOR);
}
}
But the BEST option is to put all logic within a separate model class (or classes) and make the GUI's as dumb as possible.
来源:https://stackoverflow.com/questions/55188752/click-event-accessing-a-boolean-variable-from-another-class