I currently have multiples of a JPanel (ItemPanel) within a JPanel (FlipPanel) within my JFrame. An ItemPanel is added to FlipPanel when a JButton in a separate panel (FlipFormPanel) is pressed. I have a JButton on ItemPanel labelled "Cancel" and I would like to remove the specific ItemPanel whose Cancel JButton was pressed. What I currently have only removes the ItemPanel whose button was selected, but after that no other buttons will remove any more ItemPanels.
How can I fix my code to do what I'm trying to accomplish?
My code for each class is below. I tried to remove as much of the extraneous material as possible to avoid cluttering the task at hand. I believe the issue is located in FlipPanel under the methods addItemPanel(, setItemListener(, and in the ItemPanelListener and ItemPanelEvent classes. Thanks for any help provided.
FlipPanel:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridBagLayout;
import java.util.ArrayList;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import net.miginfocom.swing.MigLayout;
public class FlipPanel extends JPanel {
private JPanel mainPanel;
private JScrollPane scrollPane;
private ItemPanel itemPanel;
private JPanel titlePanel;
private JLabel titleLabel;
private List<ItemPanel> itmPnls = new ArrayList<ItemPanel>();
private int count;
public FlipPanel() {
setLayout(new BorderLayout());
mainPanel = new JPanel();
scrollPane = new JScrollPane(mainPanel);
add(scrollPane, BorderLayout.CENTER);
mainPanel.setLayout(new MigLayout("align center, fillx", "fill", ""));
titlePanel = new JPanel();
mainPanel.add(titlePanel, "wrap, gapbottom 13, gaptop 7");
titlePanel.setLayout(new GridBagLayout());
titleLabel = new JLabel("CURRENT FLIPS");
Font labelFont = titleLabel.getFont();
titleLabel.setFont(new Font(labelFont.getName(), Font.BOLD, 25));
titlePanel.setBorder(BorderFactory.createMatteBorder(0, 0, 3, 0, Color.BLACK));
titlePanel.add(titleLabel);
count = 0;
}
public void addItemPanel(String item, String buyPrice, String sellPrice,
String quantity, String pcBuyPrice, String pcSellPrice) {
this.itemPanel = new ItemPanel(count, item, buyPrice, sellPrice, quantity,
pcBuyPrice, pcSellPrice);
mainPanel.add(itemPanel, "wrap");
itmPnls.add(itemPanel);
count++;
setItemListener(this.itemPanel);
}
public void setItemListener(ItemPanel iP) {
iP.setItemPanelListener(new ItemPanelListener() {
public void itemPanelEventOccurred(ItemPanelEvent e) {;
System.out.println("Remove");
System.out.println("Current Position: " + e.getPosition());
mainPanel.remove(itmPnls.get(e.getPosition()));
System.out.println("Positions:");
for (int i = 0; i < count; i++) {
System.out.println(itmPnls.get(i).getPosition());
}
if(e.getPosition() < count - 1) {
for (int i = e.getPosition() + 1; i < count; i++) {
itmPnls.get(i).setPosition(i);
}
}
count--;
revalidate();
repaint();
System.out.println("Positions:");
for (int i = 0; i < count; i++) {
System.out.println(itmPnls.get(i).getPosition());
}
setItemListener(itmPnls.get(0));
}
});
}
ItemPanel:
import javax.swing.JPanel;
public class ItemPanel extends JPanel {
private int position;
private String item;
private String buyPrice;
private String sellPrice;
private String quantity;
private String pcBuyPrice;
private String pcSellPrice;
private JButton logBtn;
private JButton editBtn;
private JButton cancelBtn;
private ItemPanelListener itemPanelListener;
public ItemPanel(int position, String item, String buyPrice, String sellPrice,
String quantity, String pcBuyPrice, String pcSellPrice) {
this.position = position;
this.item = item;
this.buyPrice = buyPrice;
this.sellPrice = sellPrice;
this.quantity = quantity;
this.pcBuyPrice = pcBuyPrice;
this.pcSellPrice = pcSellPrice;
Dimension dim = getPreferredSize();
dim.height = 100;
setPreferredSize(dim);
setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY));
logBtn = new JButton("Log Item");
editBtn = new JButton("Edit Item");
cancelBtn = new JButton("Cancel Item");
setupLabels();
setupCancelItemButton();
layoutComponents();
}
public int getPosition() {
return position;
}
public void setPosition(int pos) {
position = pos;
}
public void setupCancelItemButton() {
cancelBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
ItemPanelEvent ev = new ItemPanelEvent(this);
if (itemPanelListener != null) {
itemPanelListener.itemPanelEventOccurred(ev);
}
}
});
}
public void setItemPanelListener(ItemPanelListener listener) {
this.itemPanelListener = listener;
}
ItemPanelListener:
import java.util.EventListener;
public interface ItemPanelListener extends EventListener {
public void itemPanelEventOccurred(ItemPanelEvent e);
}
ItemPanelEvent:
import java.util.EventObject;
public class ItemPanelEvent extends EventObject {
private int position;
public ItemPanelEvent(Object source) {
super(source);
}
public ItemPanelEvent(Object source, int position) {
super(source);
this.position = position;
}
public int getPosition() {
return position;
}
}
Related
I'm writing a simple Trivia game and I ran into a problem where the question string won't display
In my frame I'm using border layout with "new game" and "end game" on the bottom (South) and my Trivia panel in the center.
The Trivia panel is made of grid layout with 2 rows and 1 column with the 4 answers on the bottom half and on the upper half I used another panel with border layout with the question string in the center and the score in the east.
It should look like this:
However all of the components display except for the question string.
My paintComponent is:
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setFont(font);
g.drawString(tf,0,0);
}
where tf is my string and my Trivia panel code is:
public TriviaPanel(){
score = 0;
scoreString = new JTextField();
scoreString.setFont(font);
questionPanel = new JPanel();
questionPanel.setLayout(new BorderLayout());
questionPanel.add(scoreString,BorderLayout.EAST);
this.setLayout(new GridLayout(2,1));
pool = null;
try {
pool = new Pool();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
question = pool.getQuestion();
String[] answers = question.shuffle();
tf = question.getQuestion();
this.add(questionPanel);
answersPanel = new JPanel();
answersPanel.setLayout(new GridLayout(2,2));
buttons = new JButton[NUM_OF_ANSWERS];
for (int i = 0; i < NUM_OF_ANSWERS; i++) {
buttons[i] = new JButton(answers[i]);
answersPanel.add(buttons[i]);
buttons[i].addActionListener(lis);
}
this.add(answersPanel);
scoreString.setText("Score: "+score+"/"+pool.getIterator()*CORRECT);
}
where pool is used to hold my pool of questions.
When I debugged the code I see the tf string being updated to the question string but it won't display.
Is it because of the coordinates?
Any insights would be greatly appreciated.
[Edit] Although not finished but full code below:
import java.util.Arrays;
import java.util.Collections;
public class Question {
private final int NUM_OF_ANSWERS = 4;
private String question;
private String[] answers = new String[NUM_OF_ANSWERS];
private final int CORRECT_ANSWER = 0;
public Question(String qu, String an, String dm1, String dm2, String
dm3){
question = qu;
answers[0] = an;
answers[1] = dm1;
answers[2] = dm2;
answers[3] = dm3;
}
public String getCorrectAnswer() {
return answers[CORRECT_ANSWER];
}
public String getQuestion(){
return question;
}
public String[] getAnswers(){
return answers;
}
public String toString(){
String str = question;
for (int i = 0; i<4; i++)
str+=" "+answers[i];
str+="\n";
return str;
}
public String[] shuffle(){
String[] shuffled = new String[NUM_OF_ANSWERS];
for (int i=0;i<NUM_OF_ANSWERS;i++)
shuffled[i]=answers[i];
Collections.shuffle(Arrays.asList(shuffled));
return shuffled;
}
}
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Scanner;
public class Pool {
private ArrayList<Question> questions = new ArrayList<>();
private Scanner input = new Scanner(new File("src/trivia.txt"));
private static int iterator = 0;
public Pool() throws FileNotFoundException {
while (input.hasNext()){
String q = input.nextLine();
String a = input.nextLine();
String d1 = input.nextLine();
String d2 = input.nextLine();
String d3 = input.nextLine();
Question question = new Question(q,a,d1,d2,d3);
questions.add(question);
}
Collections.shuffle(questions);
//System.out.println(questions);
}
public Question getQuestion(){
Question q = questions.get(iterator);
iterator++;
return q;
}
public int getSize(){
return questions.size();
}
public static int getIterator() {
return iterator;
}
}
import javax.swing.*;
import java.awt.*;
public class GameFrame extends JFrame {
private JButton restart, finish;
private JPanel buttons;
public GameFrame(){
super("Trivia");
TriviaPanel tp = new TriviaPanel();
this.setLayout(new BorderLayout());
this.add(tp,BorderLayout.CENTER);
restart = new JButton("New game");
finish = new JButton("End game");
buttons = new JPanel();
buttons.add(restart);
buttons.add(finish);
this.add(buttons,BorderLayout.SOUTH);
this.setSize(1000,600);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
public static void main(String[] args) {
GameFrame gf = new GameFrame();
}
}
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.FileNotFoundException;
import java.util.concurrent.TimeUnit;
public class TriviaPanel extends JPanel {
private TimerListener tl = new TimerListener();
private Timer timer = new Timer(10000,tl);
private static int score;
private JTextField scoreString;
private final int CORRECT = 10, INCORRECT = 5;
private JButton[] buttons;
private Pool pool;
private Question question;
private JButton pressed;
private final int NUM_OF_ANSWERS = 4;
private Listener lis = new Listener();
//private JPanel questionPanel;
private JPanel answersPanel;
private String tf;
private Font font = new Font("Serif",Font.BOLD,24);
private JTextField tf2 = new JTextField();
private QuestionPanel questionPanel;
public TriviaPanel(){
score = 0;
scoreString = new JTextField();
scoreString.setFont(font);
questionPanel = new QuestionPanel();
//questionPanel.setLayout(new BorderLayout());
//questionPanel.add(scoreString,BorderLayout.EAST);
this.setLayout(new GridLayout(2,1));
pool = null;
try {
pool = new Pool();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
question = pool.getQuestion();
String[] answers = question.shuffle();
tf = question.getQuestion();
//tf2.setText(question.getQuestion());
//questionPanel.add(tf2,BorderLayout.CENTER);
this.add(questionPanel);
answersPanel = new JPanel();
answersPanel.setLayout(new GridLayout(2,2));
buttons = new JButton[NUM_OF_ANSWERS];
for (int i = 0; i < NUM_OF_ANSWERS; i++) {
buttons[i] = new JButton(answers[i]);
answersPanel.add(buttons[i]);
buttons[i].addActionListener(lis);
}
this.add(answersPanel);
timer.start();
scoreString.setText("Score: "+score+"/"+pool.getIterator()*CORRECT);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
questionPanel.repaint();
}
private void next(){
Question q = pool.getQuestion();
question=q;
tf = q.getQuestion();
String[] answers = q.shuffle();
for (int i = 0; i < NUM_OF_ANSWERS; i++)
buttons[i].setText(answers[i]);
}
private void gameOver(){
JOptionPane.showConfirmDialog(null,
"Score: "+score, "Select an Option...", JOptionPane.YES_NO_CANCEL_OPTION);
}
private void check(String guess) {
timer.stop();
String answer = question.getCorrectAnswer();
if (guess.equals(answer)) {
score += CORRECT;
tf = "Correct!!!";
} else {
score -= INCORRECT;
tf = "Wrong answer";
}
scoreString.setText("Score: "+score+"/"+pool.getIterator()*CORRECT);
repaint();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private class QuestionPanel extends JPanel{
public QuestionPanel(){
this.setLayout(new BorderLayout());
this.add(scoreString,BorderLayout.EAST);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setFont(font);
g.drawString(tf,0,200);
}
}
private class Listener implements ActionListener{
#Override
public void actionPerformed(ActionEvent e) {
pressed = (JButton) e.getSource();
String guess = pressed.getText();
check(guess);
if (pool.getIterator() < pool.getSize()) {
timer.restart();
next();
}
else
gameOver();
}
}
private class TimerListener implements ActionListener{
#Override
public void actionPerformed(ActionEvent e) {
timer.stop();
score-=INCORRECT;
scoreString.setText("Score: "+score+"/"+pool.getIterator()*CORRECT);
repaint();
timer.restart();
next();
}
}
}
Start by getting rid of
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
questionPanel.repaint();
}
Seriously this is just dangerous and could set you for a endless loop which will consume your CPU cycles
Next, I modified your QuestionPanel so the text is actually rendered somewhere within the realms of probability ...
private class QuestionPanel extends JPanel {
public QuestionPanel() {
this.setLayout(new BorderLayout());
this.add(scoreString, BorderLayout.EAST);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setFont(font);
FontMetrics fm = g.getFontMetrics();
int y = ((getHeight() - fm.getHeight()) / 2) + fm.getAscent();
g.drawString(tf, 10, y);
}
}
But seriously, why aren't you just using a JLabel?
Now, any time tf changes, you need to call QuestionPanel's repaint method.
So, that's in the next and check(String) methods.
And finally (for now), you should never, ever do...
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
inside the context of the event dispatching thread. This is stopping the repaints from been processed, so, for one whole second, nothing will change.
If you want to stop the user for a second, disable the buttons and/or other controls and use another Swing Timer (for simplicity)
This is demonstrated in this self contained, compilable and runnable example...
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.Timer;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
GameFrame frame = new GameFrame();
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class GameFrame extends JFrame {
private JButton restart, finish;
private JPanel buttons;
public GameFrame() {
super("Trivia");
TriviaPanel tp = new TriviaPanel();
this.setLayout(new BorderLayout());
this.add(tp, BorderLayout.CENTER);
restart = new JButton("New game");
finish = new JButton("End game");
buttons = new JPanel();
buttons.add(restart);
buttons.add(finish);
this.add(buttons, BorderLayout.SOUTH);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
public static class TriviaPanel extends JPanel {
// private TimerListener tl = new TimerListener();
// private Timer timer = new Timer(10000, tl);
private static int score;
private JTextField scoreString;
private final int CORRECT = 10, INCORRECT = 5;
private JButton[] buttons;
private Pool pool;
private Question question;
private JButton pressed;
private final int NUM_OF_ANSWERS = 4;
private Listener lis = new Listener();
//private JPanel questionPanel;
private JPanel answersPanel;
private String tf;
private Font font = new Font("Serif", Font.BOLD, 24);
private JTextField tf2 = new JTextField();
private QuestionPanel questionPanel;
public TriviaPanel() {
score = 0;
scoreString = new JTextField();
scoreString.setFont(font);
questionPanel = new QuestionPanel();
//questionPanel.setLayout(new BorderLayout());
//questionPanel.add(scoreString,BorderLayout.EAST);
this.setLayout(new GridLayout(2, 1));
pool = null;
try {
pool = new Pool();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
question = pool.getQuestion();
String[] answers = question.shuffle();
tf = question.getQuestion();
//tf2.setText(question.getQuestion());
//questionPanel.add(tf2,BorderLayout.CENTER);
this.add(questionPanel);
answersPanel = new JPanel();
answersPanel.setLayout(new GridLayout(2, 2));
buttons = new JButton[NUM_OF_ANSWERS];
for (int i = 0; i < NUM_OF_ANSWERS; i++) {
buttons[i] = new JButton(answers[i]);
answersPanel.add(buttons[i]);
buttons[i].addActionListener(lis);
}
this.add(answersPanel);
// timer.start();
scoreString.setText("Score: " + score + "/" + pool.getIterator() * CORRECT);
}
// #Override
// protected void paintComponent(Graphics g) {
// super.paintComponent(g);
// questionPanel.repaint();
// }
private void next() {
Question q = pool.getQuestion();
question = q;
tf = q.getQuestion();
String[] answers = q.shuffle();
for (int i = 0; i < NUM_OF_ANSWERS; i++) {
buttons[i].setText(answers[i]);
}
questionPanel.repaint();
}
private void gameOver() {
JOptionPane.showConfirmDialog(null,
"Score: " + score, "Select an Option...", JOptionPane.YES_NO_CANCEL_OPTION);
}
private void check(String guess) {
// timer.stop();
String answer = question.getCorrectAnswer();
if (guess.equals(answer)) {
score += CORRECT;
tf = "Correct!!!";
} else {
score -= INCORRECT;
tf = "Wrong answer";
}
questionPanel.repaint();
scoreString.setText("Score: " + score + "/" + pool.getIterator() * CORRECT);
// OH GOD THIS IS A BAD IDEA!
// try {
// TimeUnit.SECONDS.sleep(1);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
Timer timer = new Timer(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Timer timer = (Timer) e.getSource();
timer.stop();
// Personally, I'd use a listener, but this will do
afterCheckDelay();
}
});
timer.start();
}
protected void afterCheckDelay() {
if (pool.getIterator() < pool.getSize()) {
//timer.restart();
next();
} else {
gameOver();
}
}
private class QuestionPanel extends JPanel {
public QuestionPanel() {
this.setLayout(new BorderLayout());
this.add(scoreString, BorderLayout.EAST);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setFont(font);
FontMetrics fm = g.getFontMetrics();
int y = ((getHeight() - fm.getHeight()) / 2) + fm.getAscent();
g.drawString(tf, 10, y);
}
}
private class Listener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
pressed = (JButton) e.getSource();
String guess = pressed.getText();
check(guess);
}
}
private class TimerListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
// timer.stop();
// score -= INCORRECT;
// scoreString.setText("Score: " + score + "/" + pool.getIterator() * CORRECT);
// repaint();
// timer.restart();
// next();
}
}
}
public static class Pool {
private ArrayList<Question> questions = new ArrayList<>();
// private Scanner input = new Scanner(new File("src/trivia.txt"));
private static int iterator = 0;
public Pool() throws FileNotFoundException {
Question question = new Question("Why am I doing this", "Because I'm awesome", "You feel for the trick", "You have no idea", "To much caffine");
questions.add(question);
// while (input.hasNext()) {
// String q = input.nextLine();
// String a = input.nextLine();
// String d1 = input.nextLine();
// String d2 = input.nextLine();
// String d3 = input.nextLine();
// Question question = new Question(q, a, d1, d2, d3);
// questions.add(question);
// }
Collections.shuffle(questions);
//System.out.println(questions);
}
public Question getQuestion() {
Question q = questions.get(iterator);
iterator++;
return q;
}
public int getSize() {
return questions.size();
}
public static int getIterator() {
return iterator;
}
}
public static class Question {
private final int NUM_OF_ANSWERS = 4;
private String question;
private String[] answers = new String[NUM_OF_ANSWERS];
private final int CORRECT_ANSWER = 0;
public Question(String qu, String an, String dm1, String dm2, String dm3) {
question = qu;
answers[0] = an;
answers[1] = dm1;
answers[2] = dm2;
answers[3] = dm3;
}
public String getCorrectAnswer() {
return answers[CORRECT_ANSWER];
}
public String getQuestion() {
return question;
}
public String[] getAnswers() {
return answers;
}
public String toString() {
String str = question;
for (int i = 0; i < 4; i++) {
str += " " + answers[i];
}
str += "\n";
return str;
}
public String[] shuffle() {
String[] shuffled = new String[NUM_OF_ANSWERS];
for (int i = 0; i < NUM_OF_ANSWERS; i++) {
shuffled[i] = answers[i];
}
Collections.shuffle(Arrays.asList(shuffled));
return shuffled;
}
}
}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
Stuck on a problem that requires grabbing a boolean variable from another class.
I have the following for-loop, boolean 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?
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.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I'm developing a java component for my sudoku project. This component represents a sudoku box that can have two states: a digit or candidates (I use a CardLayout). So far, all works. I am now trying to add some MouseListener on my Labels. When I click on a candidate, I would like to change the value of the state with a simple number, then change the display (cardlayout.show (...)). The problem here is that the source of the event seems to be detected, but the change is not done ... Here is my code (Problem in CaseComponent > createController > candidate[i].addMouseListener():
package sudoku;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class CaseComponent extends JPanel {
private static final long serialVersionUID = 1L;
private static final String CANDIDATES = "candidate";
private static final String DIGIT = "digit";
private GridBagConstraints gridBagConstraint;
private JLabel[] candidates;
private JLabel digit;
public CaseComponent(Color caseColor){
super();
setLayout(new CardLayout());
setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY));
setPreferredSize(new Dimension(60, 60));
setBackground(caseColor);
createView();
placeComponents();
createController();
}
private void createView() {
gridBagConstraint = new GridBagConstraints();
candidates = new JLabel[9];
for (int i = 0; i < 9; i++) {
candidates[i] = new JLabel(""+(i + 1));
}
digit = new JLabel();
}
private void placeComponents() {
JPanel p = new JPanel(new GridLayout(3, 3)); {
for (int i = 0; i < 9; i++) {
JPanel q = new JPanel(); {
q.add(candidates[i]);
}
q.setOpaque(false);
p.add(q);
}
}
p.setOpaque(false);
add(p, DIGIT);
p = new JPanel(new GridBagLayout()); {
p.add(digit, gridBagConstraint);
p.setOpaque(false);
}
add(p, CANDIDATES);
}
private void createController() {
digit.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
if (SwingUtilities.isRightMouseButton(e)) {
candidateDisplay();
}
}
});
for (int i = 0; i < 9; i++) {
candidates[i].addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
JLabel source = (JLabel) e.getSource();
if (SwingUtilities.isLeftMouseButton(e)) {
System.out.println("IN");
digitDisplay();
digit.setText(source.getText());
}
}
});
}
}
private void digitDisplay() {
CardLayout cl = (CardLayout) getLayout();
cl.show(this, DIGIT);
}
private void candidateDisplay() {
CardLayout cl = (CardLayout) getLayout();
cl.show(this, CANDIDATES);
}
}
package sudoku;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.border.Border;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class Sudoku {
// ATTRIBUTS
private JFrame mainFrame;
private Timer timer;
private JButton pauseButton;
private JButton resumeButton;
private JButton penaltyButton;
private JLabel chronoInfo;
private Chronometer chrono;
public Sudoku() {
createModel();
createView();
placeComponents();
createController();
}
// COMMANDES
/**
* Rend l'application visible au centre de l'écran.
*/
public void display() {
mainFrame.pack();
mainFrame.setLocationRelativeTo(null);
mainFrame.setVisible(true);
}
// OUTILS
private void createModel() {
chrono = new Chronometer();
}
private void createView() {
mainFrame = new JFrame("Sudoku");
resumeButton = new JButton("Reprendre");
resumeButton.setEnabled(false);
pauseButton = new JButton("Pause");
penaltyButton = new JButton("Penalité");
chronoInfo = new JLabel("00:00");
}
private void placeComponents() {
JPanel p = new JPanel(); {
p.add(resumeButton);
p.add(pauseButton);
p.add(penaltyButton);
}
mainFrame.add(p, BorderLayout.NORTH);
p = new JPanel(); {
p.add(chronoInfo);
}
mainFrame.add(p, BorderLayout.SOUTH);
p = new JPanel(); {
JPanel q = new JPanel(new GridLayout(3,3)); {
for (int i = 0; i < 9; i++) {
Color caseColor = i % 2 == 0 ? Color.WHITE : Color.GRAY;
JPanel r = new JPanel(new GridLayout(3,3)); {
for (int j = 0; j < 9; j++) {
r.add(new CaseComponent(caseColor));
}
}
r.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY, 1));
q.add(r);
}
}
q.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY, 1));
p.add(q);
}
mainFrame.add(p);
}
private void createController() {
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final int delay = 1000;
timer = new Timer(delay, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
chrono.increment();
chronoInfo.setText(chrono.toString());
}
});
timer.start();
resumeButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
timer.start();
chrono.setPaused(false);
}
});
pauseButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
timer.stop();
chrono.setPaused(true);
}
});
penaltyButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
chrono.penalty();
chronoInfo.setText(chrono.toString());
}
});
chrono.addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent e) {
resumeButton.setEnabled(chrono.isPaused());
pauseButton.setEnabled(!chrono.isPaused());
}
});
}
// POINT D'ENTREE
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Sudoku().display();
}
});
}
}
package sudoku;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.EventListenerList;
public class Chronometer {
// ATTRIBUTS
private static final int MAX_SECONDS = 60;
private final EventListenerList listeners;
private final ChangeEvent changeEvent;
private int seconds;
private int minutes;
private boolean paused;
// CONSTRUCTEUR
public Chronometer() {
listeners = new EventListenerList();
changeEvent = new ChangeEvent(this);
seconds = 0;
minutes = 0;
paused = false;
}
// REQUETES
public int getSeconds() {
return seconds;
}
public int getMinutes() {
return minutes;
}
public boolean isPaused() {
return paused;
}
public ChangeListener[] getChangeListeners() {
return listeners.getListeners(ChangeListener.class);
}
// COMMANDES
public void setSeconds(int s) {
seconds = s;
}
public void setMinutes(int m) {
minutes = m;
}
public void setPaused(boolean b) {
paused = b;
fireStateChanged();
}
public void increment() {
seconds++;
if (seconds == MAX_SECONDS) {
seconds = 0;
minutes++;
}
}
public void penalty() {
seconds += 10;
if (seconds >= MAX_SECONDS) {
minutes++;
seconds -= MAX_SECONDS;
}
}
public void reset() {
seconds = 0;
minutes = 0;
fireStateChanged();
}
public void addChangeListener(ChangeListener listener) {
if (listener == null) {
return;
}
listeners.add(ChangeListener.class, listener);
}
public void removeChangeListener(ChangeListener listener) {
if (listener == null) {
return;
}
listeners.remove(ChangeListener.class, listener);
}
public String toString() {
return String.format("%02d:%02d", minutes, seconds);
}
// OUTILS
protected void fireStateChanged() {
ChangeListener[] listnrs = getChangeListeners();
for (ChangeListener lst : listnrs) {
lst.stateChanged(changeEvent);
}
}
}
I thank you in advance !
Now that looks like a nice program! I took a quick look and I believe I found the problem. In your placeComponents method you swapped the candidates and digit keys of your layout. I also remove unnecessary brackets.
private void placeComponents() {
JPanel p = new JPanel(new GridLayout(3, 3));
for (int i = 0; i < 9; i++) {
JPanel q = new JPanel(); {
q.add(candidates[i]);
}
q.setOpaque(false);
p.add(q);
}
p.setOpaque(false);
add(p, CANDIDATES); // was DIGIT
p = new JPanel(new GridBagLayout()); {
p.add(digit, gridBagConstraint);
p.setOpaque(false);
}
add(p, DIGIT); // was CANDIDATES
}
I have been trying to get my code to reset after hitting the okay button with slider, however, I have had no such luck. Does anyone have an idea on how I can incorporate this into my code?
P.S. The reset must be in Class Field.
package GUI;
import java.awt.GridLayout;
import javax.swing.JPanel;
public class GameDisplay extends JPanel {
private static final long serialVersionUID = 1L;
private boolean activated;
public GameDisplay(Model.Field field) {
setLayout(new GridLayout(GUI.SizeDialog.currentRows, GUI.SizeDialog.currentColumns));
for (int i = 0; i < GUI.SizeDialog.currentRows; ++i) {
for (int j = 0; j < GUI.SizeDialog.currentColumns; ++j) {
add(field.Cells[i][j]);
}
}
}
public boolean isActive() {
return activated;
}
public void setActive(boolean activated) {
this.activated = activated;
}
}
Field
package Model;
import java.awt.Dimension;
import java.util.ArrayList;
import GUI.SizeDialog;
public class Field {
private int difficultyFactor;
public static final int EASY = 1;
public static final int NORMAL = 2;
public static final int HARD = 3;
public Cell[][] Cells;
public Field() {
Cells = new Cell[GUI.SizeDialog.currentRows][GUI.SizeDialog.currentColumns];
for (int i = 0; i < GUI.SizeDialog.currentRows; ++i) {
for (int j = 0; j < GUI.SizeDialog.currentColumns; ++j) {
Cells[i][j]= new Cell();
}
}
}
public void reset(){
Cells = new Cell[GUI.SizeDialog.currentRows][GUI.SizeDialog.currentColumns];
for (int i = 0; i < GUI.SizeDialog.currentRows; ++i) {
for (int j = 0; j < GUI.SizeDialog.currentColumns; ++j) {
Cells[i][j]= new Cell();
}
}
}
public void setDifficultyFactor(int level) {
switch (level) {
case EASY:
difficultyFactor = EASY;
break;
case NORMAL:
difficultyFactor = NORMAL;
break;
case HARD:
difficultyFactor = HARD;
break;
default:
difficultyFactor = NORMAL;
}
}
}
SizeDialog
package GUI;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Hashtable;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import Model.Field;
public class SizeDialog extends JDialog {
private static final long serialVersionUID = 1L;
private Model.Field field;
private GUI.GameDisplay GameDisplay;
public static Integer currentRows = 4;
public static Integer currentColumns = 4;
public SizeDialog() {
JPanel dialogBoxPanel = new JPanel();
BorderLayout dialogLayout = new BorderLayout();
dialogBoxPanel.setLayout(dialogLayout);
JSlider rowCount = new JSlider(4, 10, 4);
JSlider columnCount = new JSlider(4, 10, 4);
Hashtable<Integer, JLabel> labelTable = new Hashtable<Integer, JLabel>();
labelTable.put(new Integer(4), new JLabel("4"));
labelTable.put(new Integer(10), new JLabel("10"));
rowCount.setLabelTable(labelTable);
rowCount.setPaintLabels(true);
columnCount.setLabelTable(labelTable);
columnCount.setPaintLabels(true);
JLabel row = new JLabel();
JLabel column = new JLabel();
JPanel rowPanel = new JPanel();
JPanel columnPanel = new JPanel();
JLabel rowPosition = new JLabel();
rowPosition.setText("Rows: 4");
JLabel columnPosition = new JLabel();
columnPosition.setText("Columns: 4");
rowCount.addChangeListener(getCurrentRows(rowCount, "row", rowPosition));
columnCount.addChangeListener(getCurrentColumns(columnCount, "column", columnPosition));
JButton okButton = new JButton("OK");
okButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
field.reset();
SizeDialog.this.dispose();
}
});
rowPanel.add(rowPosition, BorderLayout.WEST);
rowPanel.add(row, BorderLayout.CENTER);
rowPanel.add(rowCount, BorderLayout.EAST);
columnPanel.add(columnPosition, BorderLayout.WEST);
columnPanel.add(column, BorderLayout.CENTER);
columnPanel.add(columnCount, BorderLayout.EAST);
dialogBoxPanel.add(rowPanel, BorderLayout.NORTH);
dialogBoxPanel.add(columnPanel, BorderLayout.CENTER);
dialogBoxPanel.add(okButton, BorderLayout.SOUTH);
setContentPane(dialogBoxPanel);
setMinimumSize(new Dimension(300, 150));
setLocationRelativeTo(null);
}
private ChangeListener getCurrentColumns(final JSlider columnCount, final String string, final JLabel columnPosition) {
ChangeListener changeListener = new ChangeListener() {
public void stateChanged(ChangeEvent changeEvent) {
JSlider theSlider = (JSlider) changeEvent.getSource();
if (!theSlider.getValueIsAdjusting()) {
int sliderValue = theSlider.getValue();
columnPosition.setText("columns:" + sliderValue);
SizeDialog.currentColumns = sliderValue;
}
}
};
return changeListener;
}
private ChangeListener getCurrentRows(final JSlider rowCount, final String string, final JLabel rowPosition) {
ChangeListener changeListener = new ChangeListener() {
public void stateChanged(ChangeEvent changeEvent) {
JSlider theSlider = (JSlider) changeEvent.getSource();
if (!theSlider.getValueIsAdjusting()) {
int sliderValue = theSlider.getValue();
rowPosition.setText("Rows:" + sliderValue);
SizeDialog.currentRows = sliderValue;
}
}
};
return changeListener;
}
}
MainFrame
package GUI;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.ButtonGroup;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
public class MainFrame extends JFrame {
private static final long serialVersionUID = 1L;
private static JPanel centerPanel;
public static final String EASY = "Easy";
public static final String NORMAL = "Normal";
public static final String HARD = "Hard";
public MainFrame(JPanel centerPanel) {
// Setup of Main
super("The True/False Game");
this.centerPanel = centerPanel;
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setup();
}
private void setup() {
// Setup of centerPanel
add(centerPanel);
pack();
}
public JMenuBar setUpMenuBar(ActionListener listener) {
// create the necessary menu items and menus
JMenuBar menuBar = new JMenuBar();
JMenu settingsMenu = new JMenu("Settings");
JMenuItem size = new JMenuItem("Size");
size.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Object valueBox = new SizeDialog();
((Window) valueBox).setVisible(true);
}
});
JMenu difficultyMenu = new JMenu("Difficulty Level");
ButtonGroup levelGroup = new ButtonGroup();
JCheckBoxMenuItem easyDifficultyItem = new JCheckBoxMenuItem(EASY);
JCheckBoxMenuItem normalDifficultyItem = new JCheckBoxMenuItem(NORMAL);
JCheckBoxMenuItem hardDifficultyItem = new JCheckBoxMenuItem(HARD);
easyDifficultyItem.setSelected(true); // Default difficulty setting
// this button group ensures that only one check box is selected
levelGroup.add(easyDifficultyItem);
levelGroup.add(normalDifficultyItem);
levelGroup.add(hardDifficultyItem);
difficultyMenu.add(easyDifficultyItem);
difficultyMenu.add(normalDifficultyItem);
difficultyMenu.add(hardDifficultyItem);
settingsMenu.add(size);
settingsMenu.add(difficultyMenu);
menuBar.add(settingsMenu);
// use a single listener to handle all menu item selections
for (int i = 0; i < menuBar.getMenuCount(); ++i) {
for (JMenuItem item : getMenuItems(menuBar.getMenu(i))) {
item.addActionListener(listener);
}
}
return menuBar;
}
// this recursion works because JMenu is a subclass of JMenuItem!
private static List<JMenuItem> getMenuItems(JMenuItem item) {
List<JMenuItem> items = new ArrayList<>();
if (item instanceof JMenu) {
JMenu menu = (JMenu) item;
for (int i = 0; i < menu.getItemCount(); ++i) {
items.addAll(getMenuItems(menu.getItem(i)));
}
} else {
items.add(item);
}
return items;
}
}
App
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JMenuBar;
import Model.Cell;
import Model.Field;
import GUI.MainFrame;
import GUI.SizeDialog;
public class App {
// Main Objects
private static GUI.MainFrame MainFrame;
private static GUI.GameDisplay GameDisplay;
private static Model.Field field;
public static GUI.SizeDialog SizeDialog;
public static void main(String[] args) {
// Setup of the Main Objects
field = new Model.Field();
GameDisplay = new GUI.GameDisplay(field);
MainFrame = new MainFrame(GameDisplay);
MainFrame.setMinimumSize(new Dimension(500, 500));
MainFrame.getContentPane().add(GameDisplay);
// Setup of the Menu Bar
JMenuBar menuBar = MainFrame.setUpMenuBar(menuListener);
MainFrame.setJMenuBar(menuBar);
// Show the Mainframe in the center of the desktop screen
MainFrame.setLocationRelativeTo(null);
MainFrame.setVisible(true);
}
// listener for the menu items in MainFrame
private static ActionListener menuListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
switch (e.getActionCommand()) {
case GUI.MainFrame.EASY:
field.setDifficultyFactor(Field.EASY);
GameDisplay.setActive(true);
break;
case GUI.MainFrame.NORMAL:
field.setDifficultyFactor(Field.NORMAL);
GameDisplay.setActive(true);
break;
case GUI.MainFrame.HARD:
field.setDifficultyFactor(Field.HARD);
GameDisplay.setActive(true);
break;
}
}
};
};
An instance of your Field class is currently being created in the App class. Your private field field in the SizeDialog class is currently not being set to the instance known to the App class. A solution for this problem is to provide the Field instance as a parameter.
A possible solution is as follows:
App:
public class App {
// Main Objects
private static GUI.MainFrame MainFrame;
private static GUI.GameDisplay GameDisplay;
private static Model.Field field;
public static GUI.SizeDialog SizeDialog;
public static void main(String[] args) {
// Setup of the Main Objects
field = new Model.Field();
GameDisplay = new GUI.GameDisplay(field);
MainFrame = new MainFrame(GameDisplay, field);
/* the rest of your code */
}
/* more App code */
}
MainFrame:
public class MainFrame extends JFrame {
private static final long serialVersionUID = 1L;
private static JPanel centerPanel;
public static final String EASY = "Easy";
public static final String NORMAL = "Normal";
public static final String HARD = "Hard";
private Model.Field field;
public MainFrame(JPanel centerPanel, Model.Field field) {
this.field = field;
/* the rest of your code */
}
public JMenuBar setUpMenuBar(ActionListener listener) {
// create the necessary menu items and menus
JMenuBar menuBar = new JMenuBar();
JMenu settingsMenu = new JMenu("Settings");
JMenuItem size = new JMenuItem("Size");
size.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Object valueBox = new SizeDialog(field);
((Window) valueBox).setVisible(true);
}
});
/* the rest of your code */
}
/* more MainFrame code */
}
SizeDialog:
public class SizeDialog extends JDialog {
private static final long serialVersionUID = 1L;
private final Model.Field field;
private GUI.GameDisplay GameDisplay;
public static Integer currentRows = 4;
public static Integer currentColumns = 4;
public SizeDialog(final Model.Field field) {
this.field = field;
/* the rest of your code */
}
/* more SizeDialog code */
}
EDIT: As mentioned in this answer, objects that are referenced in anonymous classes must be final.
In my GUI, after importing an Excel file, I need to create a variable amount of panels/tabs. The amount depends on the number of rows imported from the Excel file. I need to show the information contained in row in a different panel, with a couple of buttons to move between all the tabs. For example, if the Excel file contains 6 rows:
Field1: user1
Field2: user1Age
< [1/6] >
So, I can move through the different panels, by clicking on the arrows:
Field1: user2
Field2: user2Age
< [2/6] >
One more consideration: Excel file import is not the only way to get information, it must be possible to manually add information. Therefore, after starting the GUI there must be at least one panel, and if the user decides to import an Excel file, then multiple panels must be created.
I need just a hint to start coding. And of course I am open to other possibilities.
Here is a sample code that should get you started (you will need to reorganize a bit the code). Although there are 1000 dummy users, it only uses a single panel to display the information:
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class TestMultiplePanels {
private final UserList userList;
private User currentUser;
private JTextField name;
private JTextField age;
private JTextField index;
private JButton prev;
private JButton next;
public TestMultiplePanels(UserList userList) {
this.userList = userList;
}
protected void initUI() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel userPanel = new JPanel(new BorderLayout());
JPanel userInfoPanel = new JPanel(new GridBagLayout());
JPanel buttonPanel = new JPanel(new FlowLayout());
JLabel nameLabel = new JLabel("Name");
JLabel ageLabel = new JLabel("Age");
name = new JTextField(30);
age = new JTextField(5);
index = new JTextField(5);
index.setEditable(false);
prev = new JButton("<");
prev.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
setCurrentUser(userList.previous(currentUser));
}
});
next = new JButton(">");
next.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
setCurrentUser(userList.next(currentUser));
}
});
GridBagConstraints gbcLabel = new GridBagConstraints();
gbcLabel.anchor = GridBagConstraints.EAST;
GridBagConstraints gbcField = new GridBagConstraints();
gbcField.anchor = GridBagConstraints.WEST;
gbcField.gridwidth = GridBagConstraints.REMAINDER;
userInfoPanel.add(nameLabel, gbcLabel);
userInfoPanel.add(name, gbcField);
userInfoPanel.add(ageLabel, gbcLabel);
userInfoPanel.add(age, gbcField);
buttonPanel.add(prev);
buttonPanel.add(index);
buttonPanel.add(next);
userPanel.add(userInfoPanel);
userPanel.add(buttonPanel, BorderLayout.SOUTH);
setCurrentUser(userList.getUsers().get(0));
frame.add(userPanel);
frame.pack();
frame.setMinimumSize(frame.getPreferredSize());
frame.setVisible(true);
}
private void setCurrentUser(User user) {
currentUser = user;
name.setText(user.getUserName());
age.setText(String.valueOf(user.getAge()));
index.setText(user.getIndex() + "/" + userList.getCount());
next.setEnabled(userList.hasNext(user));
prev.setEnabled(userList.hasPrevious(user));
}
public static class UserList {
private List<User> users;
private List<User> unmodifiableUsers;
public UserList() {
super();
this.users = load();
unmodifiableUsers = Collections.unmodifiableList(users);
}
public int getCount() {
return users.size();
}
public List<User> getUsers() {
return unmodifiableUsers;
}
private List<User> load() {
List<User> users = new ArrayList<TestMultiplePanels.User>();
for (int i = 0; i < 1000; i++) {
User user = new User();
user.setUserName("User " + (i + 1));
user.setAge((int) (Math.random() * 80));
user.setIndex(i + 1);
users.add(user);
}
return users;
}
public boolean hasNext(User user) {
return user.getIndex() - 1 < users.size();
}
public boolean hasPrevious(User user) {
return user.getIndex() > 1;
}
public User next(User user) {
if (hasNext(user)) {
return users.get(user.getIndex());
} else {
return null;
}
}
public User previous(User user) {
if (hasPrevious(user)) {
return users.get(user.getIndex() - 2);
} else {
return null;
}
}
}
public static class User {
private String userName;
private int age;
private int index;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
}
public static void main(String[] args) {
final UserList userList = new UserList();
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
TestMultiplePanels testMultiplePanels = new TestMultiplePanels(userList);
testMultiplePanels.initUI();
}
});
}
}
You can create the panels dynamically using an ArrayList, which I think is flexible enough for that and easily manageable. To handle panels display, you can use a CardLayout. Hope it helps
ArrayList<JPanel> panelGroup = new ArrayList<JPanel>();
for (int i=0;i<numberOfPanelsToCreate;i++){
panelGroup.add(new JPanel());
}