I have this problem of using my method "changeStyle" to change the appearance of my JButtons. I made a method which will change the background, border, and Opacity of my JButton. I tried to make another method to shorten the first code but it return an error, "The method changeStyle() is undefined for the type JButton."
The code that I tried to shorten:
public void buttonChange(){
rock.setBackground(defaultColor);
rock.setBorder(defaultBorder);
rock.setOpaque(false);
paper.setBackground(defaultColor);
paper.setBorder(defaultBorder);
paper.setOpaque(false);
scissor.setBackground(defaultColor);
scissor.setBorder(defaultBorder);
scissor.setOpaque(false);
switch(main.playerChoice){
case 1:
rock.setBackground(Color.cyan);
rock.setBorder(BorderFactory.createLineBorder(Color.blue, 2, true));
rock.setOpaque(true);
break;
case 2:
paper.setBackground(Color.cyan);
paper.setBorder(BorderFactory.createLineBorder(Color.blue, 2, true));
paper.setOpaque(true);
break;
case 3:
scissor.setBackground(Color.cyan);
scissor.setBorder(BorderFactory.createLineBorder(Color.blue, 2, true));
scissor.setOpaque(true);
break;
default:
rock.setBackground(defaultColor);
rock.setBorder(defaultBorder);
rock.setOpaque(false);
paper.setBackground(defaultColor);
paper.setBorder(defaultBorder);
paper.setOpaque(false);
scissor.setBackground(defaultColor);
scissor.setBorder(defaultBorder);
scissor.setOpaque(false);
break;
}
}
This is the function I make to shorten buttonChange:
package RPS;
import java.awt.Color;
import javax.swing.JButton;
import javax.swing.border.Border;
public class changeStyle extends JButton{
public changeStyle(Color color, Border border, Boolean bol){
setBackground(color);
setBorder(border);
setOpaque(bol);
}
}
Whole Code:
package RPS;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.concurrent.ThreadLocalRandom;
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.JSplitPane;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import RPS.changeStyle;
public class main extends JFrame{
private static String version = "V. 0.02";
private JPanel contentPane;
JPanel titlePane = new JPanel();
JLabel title = new JLabel("Rock Paper Scissor " + version);
JSplitPane split1 = new JSplitPane();
JButton exit = new JButton("Exit");
JButton play = new JButton("Play");
JSplitPane split2 = new JSplitPane();
JSplitPane split3 = new JSplitPane();
JSplitPane split4 = new JSplitPane();
JButton rock = new JButton("Rock");
JButton paper = new JButton("Paper");
JButton scissor = new JButton("Scissor");
static int playerChoice;
static int computerChoice;
static int playerScore;
static int computerScore;
static String finalScore;
JLabel plScore = new JLabel("Player Score: " + playerScore);
JLabel compScore = new JLabel("Computer Score: " + computerScore);
JButton reset = new JButton("Reset");
Color defaultColor = new JButton().getBackground();
Border defaultBorder = new JButton().getBorder();
public static void main(String[] args) {
try {
main frame = new main();
frame.setVisible(true);
frame.setResizable(false);
} catch (Exception e) {
e.printStackTrace();
}
}
public main() {
setTitle("Rock Paper Scissor " + version);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
setContentPane(contentPane);
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setLayout(new BorderLayout());
add(titlePane, BorderLayout.PAGE_START);
titlePane.add(title);
titlePane.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
add(split2, BorderLayout.LINE_START);
split2.setOrientation(JSplitPane.VERTICAL_SPLIT);
split2.setEnabled(false);
split2.setTopComponent(plScore);
split2.setBottomComponent(rock);
split2.setDividerLocation(this.getHeight()/4);
split2.setDividerSize(0);
rock.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
main.playerChoice = 1;
//System.out.println(main.playerChoice);
buttonChange();
}
});
plScore.setFont(plScore.getFont().deriveFont(12F));
plScore.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
add(split3, BorderLayout.CENTER);
split3.setOrientation(JSplitPane.VERTICAL_SPLIT);
split3.setEnabled(false);
split3.setTopComponent(compScore);
split3.setBottomComponent(paper);
split3.setDividerLocation(this.getHeight()/4);
split3.setDividerSize(0);
paper.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
main.playerChoice = 2;
//System.out.println(main.playerChoice);
buttonChange();
}
});
compScore.setFont(compScore.getFont().deriveFont(12F));
compScore.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
add(split4, BorderLayout.LINE_END);
split4.setOrientation(JSplitPane.VERTICAL_SPLIT);
split4.setEnabled(false);
split4.setTopComponent(reset);
split4.setBottomComponent(scissor);
split4.setDividerLocation(this.getHeight()/4);
split4.setDividerSize(0);
reset.setSize(25, 75);
scissor.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
main.playerChoice = 3;
//System.out.println(main.playerChoice);
buttonChange();
}
});
reset.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
finalScore = "";
computerChoice = 0;
playerChoice = 0;
playerScore = 0;
computerScore = 0;
plScore.setText("Player Score: " + playerScore);
plScore.setForeground(Color.black);
compScore.setText("Computer Score: " + computerScore);
compScore.setForeground(Color.black);
buttonChange();
}
});
//add(rock, BorderLayout.LINE_START);
split2.setPreferredSize(new Dimension(this.getWidth()/3 -6,0));
//add(paper, BorderLayout.CENTER);
split3.setPreferredSize(new Dimension(this.getWidth()/3 -6,0));
//add(scissor, BorderLayout.LINE_END);
split4.setPreferredSize(new Dimension(this.getWidth()/3 -6,0));
add(split1, BorderLayout.PAGE_END);
split1.setOrientation(JSplitPane.HORIZONTAL_SPLIT);
split1.setEnabled(false);
split1.setDividerLocation(this.getWidth()/2);
split1.setDividerSize(0);
split1.setLeftComponent(play);
split1.setRightComponent(exit);
exit.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
System.exit(0);
}
});
play.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
int rand = ThreadLocalRandom.current().nextInt(1, 4);
main.computerChoice = rand;
//System.out.println(main.computerChoice);
plScore.setForeground(Color.black);
compScore.setForeground(Color.black);
if(main.playerChoice == main.computerChoice){
finalScore = "Tie!";
JOptionPane.showMessageDialog(null, finalScore, "Result", JOptionPane.INFORMATION_MESSAGE);
}else if(main.playerChoice == 1){
switch(main.computerChoice){
case 2:
finalScore = "Computer Wins!";
break;
case 3:
finalScore = "Player Wins!";
}
}else if(main.playerChoice == 2){
switch(main.computerChoice){
case 3:
finalScore = "Computer Wins!";
break;
case 1:
finalScore = "Player Wins!";
}
}else if(main.playerChoice == 3){
switch(main.computerChoice){
case 2:
finalScore = "Computer Wins!";
break;
case 1:
finalScore = "Player Wins!";
}
}else{
JOptionPane.showMessageDialog(contentPane, "You didn't choose!!!", "Error", JOptionPane.ERROR_MESSAGE);
}
while(finalScore == "Player Wins!"){
playerScore+=1;
plScore.setText("Player Score: " + playerScore);
//INSERT POP UP
JOptionPane.showMessageDialog(contentPane, finalScore, "Result", JOptionPane.INFORMATION_MESSAGE);
plScore.setForeground(Color.green);
finalScore = "";
}
while(finalScore == "Computer Wins!"){
computerScore+=1;
compScore.setText("Computer Score: " + computerScore);
//INSTERT POP UP
JOptionPane.showMessageDialog(contentPane, finalScore, "Result", JOptionPane.INFORMATION_MESSAGE);
compScore.setForeground(Color.red);
finalScore = "";
}
main.playerChoice = 0;
}
});
}
public void buttonChange(){
rock.setBackground(defaultColor);
rock.setBorder(defaultBorder);
rock.setOpaque(false);
paper.setBackground(defaultColor);
paper.setBorder(defaultBorder);
paper.setOpaque(false);
scissor.setBackground(defaultColor);
scissor.setBorder(defaultBorder);
scissor.setOpaque(false);
switch(main.playerChoice){
case 1:
rock.setBackground(Color.cyan);
rock.setBorder(BorderFactory.createLineBorder(Color.blue, 2, true));
rock.setOpaque(true);
break;
case 2:
paper.setBackground(Color.cyan);
paper.setBorder(BorderFactory.createLineBorder(Color.blue, 2, true));
paper.setOpaque(true);
break;
case 3:
scissor.setBackground(Color.cyan);
scissor.setBorder(BorderFactory.createLineBorder(Color.blue, 2, true));
scissor.setOpaque(true);
break;
default:
rock.setBackground(defaultColor);
rock.setBorder(defaultBorder);
rock.setOpaque(false);
paper.setBackground(defaultColor);
paper.setBorder(defaultBorder);
paper.setOpaque(false);
scissor.setBackground(defaultColor);
scissor.setBorder(defaultBorder);
scissor.setOpaque(false);
break;
}
}
}
Thanks for your time.
Extending a class and adding functionality to doesn't make that functionality available to parent classes, only instances of the new class and it's children will have access to it, so when you use JButton rock = new JButton("Rock");, rock will NOT have the functionality of changeStyle (it's not an instance of changeStyle, so how can it?)
We could get into semantics about polymorphism and object casting, but let's just say you should be using
changeStyle rock = new changeStyle();
This will now allow you to call the changeStyle method. Note, you will need to override the button's constructor if you wish to pass the text String to it when you create it
Java naming conventions would also suggest that class names should start with an uppercase character, so changeStyle should be ChangeStyle, while it might not seem like a big deal, it will make you code easier to read for others and for you to read other people's code, it's just a good habit to use
Related
I'm having trouble getting an output while using the switch-statement and IntBinaryOperator. I'm trying to build a simple calculator in Java, and I found that the IntBinaryOperator cut down on unnecessary boilerplate code. I hope that you can show me the best approach. Thank you.
The three classes that I wrote are below.
package gui_calc;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.function.IntBinaryOperator;
public class CalculatorJFrame extends JFrame implements ActionListener {
static protected JLabel lblOut;
private JButton btnEq;
private JButton btnClear;
public CalculatorJFrame() {
setTitle("CALCULATOR");
JPanel container = new JPanel(); //create a JPanel inside the JFrame as a container
container.setLayout(new BorderLayout());
//add your components in here
lblOut = new JLabel("");
btnEq = new JButton("=");
btnClear = new JButton("C");
btnEq.addActionListener(this);
btnClear.addActionListener(this);
NumButtonsJP numBtns = new NumButtonsJP(); //create an instance of NumButtonsJP
OpButtonsJP opBtns = new OpButtonsJP(); //create an instance of OpButtonsJP
container.add(btnClear, BorderLayout.WEST);
container.add(btnEq, BorderLayout.EAST);
container.add(lblOut, BorderLayout.NORTH);
container.add(numBtns, BorderLayout.CENTER); //add the numBtns JPanel to the container
container.add(opBtns, BorderLayout.SOUTH); //add the opBtns JPanel to the container
add(container); //add container to the JFrame
}
static protected void updateOutLabel(String suffix) {
String currLblContent = lblOut.getText().trim(); //get current content of lblOut
lblOut.setText(currLblContent + suffix); //update the output label on the main container
}
static protected void clearOutLabel() {
lblOut.setText("");
}
#Override
public void actionPerformed(ActionEvent e) {
String face = e.getActionCommand().trim();
switch (face) {
case "=":
//do math... get the values... and reset the label with the result
updateOutLabel("=" + getResultFromQuestion(lblOut.getText()));
break;
case "+":
IntBinaryOperator add = (a,b) -> a + b;
System.out.println("Your answer is" + (add));
break;
case "-":
IntBinaryOperator substract = (a, b) -> a - b;
System.out.println("Your answer is" + (substract.applyAsInt(lblOut.getText().charAt(0),lblOut.getText().charAt(1))));
break;
case "*":
IntBinaryOperator multiply = (a, b) -> a * b;
System.out.println("Your answer is" + (multiply));
break;
case "/":
IntBinaryOperator divide = (a, b) -> a / b;
System.out.println("Your answer is" + divide);
case "C":
clearOutLabel();
break;
}
}
private String getResultFromQuestion(String text) {
double resultStr = 10;
return "" + resultStr;
}
public static void main(String[] args) {
//create instance of calculator and run it
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
CalculatorJFrame calcGUI = new CalculatorJFrame();
calcGUI.setDefaultCloseOperation(calcGUI.EXIT_ON_CLOSE);
calcGUI.setSize(300, 300);
calcGUI.setVisible(true);
}
});
}
package gui_calc;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JPanel;
public class OpButtonsJP extends JPanel implements ActionListener{
JButton btnAdd = new JButton("+");
JButton btnSub = new JButton("-");
JButton btnMul = new JButton("*");
JButton btnDiv = new JButton("/");
JButton [] opsBtns = {btnAdd, btnSub, btnMul, btnDiv};//array of jbuttons
public OpButtonsJP(){
setLayout(new GridLayout(1,4));
for(int i=0; i<opsBtns.length; i++){
add(opsBtns[i]); //add the button to the JPanel
opsBtns[i].addActionListener(this); //add the ActionListener to make the button functional
}
}
#Override
public void actionPerformed(ActionEvent e) {
String face = e.getActionCommand();
System.out.println(face + " was clicked");
CalculatorJFrame.updateOutLabel(face);
//String currLblContent = CalculatorJFrame.lblOut.getText();
//CalculatorJFrame.lblOut.setText(currLblContent + face); //update the output label on the main container
}
}
package gui_calc;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class NumButtonsJP extends JPanel implements ActionListener {
JButton numButtons[];
public NumButtonsJP() {
setLayout(new GridLayout(4, 3));
numButtons = new JButton[10];
for (int i = 1; i < 10; i++) {
//create a JButton with the number on its face and add it to the array of JButtons
numButtons[i] = new JButton("" + i);
numButtons[i].addActionListener(this); //make the button trigger the event
//add the JButton to the JPanel
add(numButtons[i]);
}
JLabel spaceHolder = new JLabel(); //create the spaceHolder as a blank label
add(spaceHolder); //add the spaceHolder to the JPanel
numButtons[0] = new JButton("0"); //create the Zero button
numButtons[0].addActionListener(this);//make the Zero button trigger actioNPerformed
add(numButtons[0]); //add the Zero button to the JPanel
}
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
String face = e.getActionCommand();
System.out.println(face + " was clicked");
int num = Integer.parseInt(face.trim()); // parse to an int so we can use in math
CalculatorJFrame.updateOutLabel(face);
//String currLblContent = CalculatorJFrame.lblOut.getText();
//CalculatorJFrame.lblOut.setText(currLblContent + face); //update the output label on the main container
}
}
I change a little your code, basically I'm adding an evaluator of expressions.
The UI basically construct the expression and pass to your getResultFromQuestion() function which takes the input and then try to parse to a math function.
You must handle the exceptions properly, and it brokes your BinaryOperators since you could entry two of more operands.
#Override
public void actionPerformed(ActionEvent e) {
String face = e.getActionCommand().trim();
switch (face) {
case "=":
// do math... get the values... and reset the label with the result
updateOutLabel("=" + getResultFromQuestion(lblOut.getText()));
break;
case "C":
clearOutLabel();
break;
}
}
private String getResultFromQuestion(String text) {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("js");
Object result = null;
try {
result = engine.eval(text);
} catch (ScriptException e) {
//Do something with the exception
}
return result.toString();
}
I need to finish up this simon game for my beginner Java class. Basically the game needs to randomize 3 of the COLOR letters on the top label "R", "B", "Y" or "G" to begin playing the game. The player will press the colors in this sequence and if they are correct it will add another letter/color if they are wrong they will lose. I have the main part of the game set up including color ect... What I am having a hard time with is printing the letters of the buttons pushed on the bottom label and also getting the top label to randomize 3 to start with. I can get the game to print random letters on the top label when a button is pushed but it wont do this own its own to start and it wont add the letters on?
HERE IS MY CODE:
//10/30/16
package simongame1;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.FlowLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import java.security.SecureRandom;
public class SimonGame1 extends JFrame implements ActionListener
{
public SecureRandom rand;
public String randomLetters="";
JButton[] numberButtons = new JButton[4];
JPanel numberButtonPanel = new JPanel();
JLabel labelTop;
JLabel labelBottom;
String messageTop = "";
String messageBottom = "";
JButton red;
JButton green;
JButton yellow;
JButton blue;
public final String letters= "RGBY";
public JLabel labelDisplay;
//constructor?
public SimonGame1()
{
super("Simon Game!");
labelDisplay = new JLabel ("");
setLayout(new BorderLayout());
red = new JButton();
green = new JButton();
blue = new JButton();
yellow = new JButton();
labelTop = new JLabel("");
//getRandomLetter();
labelBottom = new JLabel("");
//System.out.print (randomLetters);
rand = new SecureRandom();
numberButtons = new JButton[4];
numberButtonPanel = new JPanel();
numberButtonPanel.setLayout(new GridLayout(3,3));
for(int i = 0; i < 0; i++)
{
numberButtons[i] = new JButton();
numberButtonPanel.add(numberButtons[i]);
numberButtons[i].addActionListener(this);
}
numberButtonPanel.add(red);
red.setBackground(Color.red);
red.addActionListener(this);
numberButtonPanel.add(blue);
blue.setBackground(Color.blue);
blue.addActionListener(this);
numberButtonPanel.add(yellow);
yellow.setBackground (Color.yellow);
yellow.addActionListener(this);
numberButtonPanel.add (green);
green.setBackground (Color.green);
green.addActionListener(this);
add(labelTop, BorderLayout.NORTH);
add(labelBottom, BorderLayout.SOUTH);
add(numberButtonPanel, BorderLayout.CENTER);
//if (messageTop = messageBottom)
}
// TODO code application logic here
#Override
public void actionPerformed(ActionEvent e)
{
rand = new SecureRandom();
randomLetters+= getRandomLetter();
labelTop.setText (randomLetters);
labelBottom.setText (letters);
System.out.println(e.getID());
if(e.getSource() == red)
{
System.out.println("R");
}
else if (e.getSource()==blue)
{
System.out.println ("B");
}
else if (e.getSource()==yellow)
{
System.out.println ("Y");
}
else if (e.getSource()==green)
{
System.out.println ("G");
}
}
public char getRandomLetter()
{
char randChar = letters.charAt(rand.nextInt (4));
return randChar;
}
}
AND HERE IS THE TEST
package simongame1;
import javax.swing.JFrame;
public class NewClass {
public static void main(String[] args) {
{
SimonGame1 simpleFrame = new SimonGame1();
simpleFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
simpleFrame.setSize(300, 300);
simpleFrame.setVisible(true);
}
}
}
WHY IS THIS ONE CLICK BEHIND? If i click the red button it doenst show anything but if i click the blue one after the red thats when it prints "R" finally...
labelBottom.setText (messageBottom);
**//WHY IS IT ONE LETTER BEHIND?**
System.out.println(e.getID());
if(e.getSource() == red)
{
messageBottom += "R";
//System.out.println("R");
}
else if (e.getSource()==blue)
{
messageBottom += "B";
//System.out.println ("B");
}
else if (e.getSource()==yellow)
{
messageBottom += "Y";
//System.out.println ("Y");
}
else if (e.getSource()==green)
{
messageBottom += "G";
//System.out.println ("G");
}
When you initialize your label, before you add it to the panel I would just generate the label with the letters you need and set the text of the label right there. That way when you add it you will for sure have the characters in there. Right now you are only setting the text of labelTop when the actionPerformed method is called, which is only called when a button is pressed.
So it should look something like:
public SimonGame1() {
//....
rand = new SecureRandom();
labelTop = new JLabel( "" );
//initialize with 3
for(int i = 0; i < 3; i++)
{
randomLetters += getRandomLetter();
}
labelTop.setText( randomLetters );
//...
add(labelTop, BorderLayout.NORTH);
}
also this block of code is not used at all because the condition is never met, since you initialize i to 0 and then say as long as it is less than 0:
for(int i = 0; i < 0; i++)
{
numberButtons[i] = new JButton();
numberButtonPanel.add(numberButtons[i]);
numberButtons[i].addActionListener(this);
}
EDIT:
since you added another part of the question, you asked why it is waiting an iteration before adding the character you just clicked in your actionPerformed method, and that is because you are setting the text before you add the next character to the string. So your actionPerformed method should look like:
public void actionPerformed(ActionEvent e)
{
if(e.getSource() == red)
{
messageBottom += "R";
//System.out.println("R");
}
else if (e.getSource()==blue)
{
messageBottom += "B";
//System.out.println ("B");
}
else if (e.getSource()==yellow)
{
messageBottom += "Y";
//System.out.println ("Y");
}
else if (e.getSource()==green)
{
messageBottom += "G";
//System.out.println ("G");
}
labelBottom.setText (messageBottom);
}
I'm writing a program that has a quiz element, and when the user gets an answer wrong, feedback is given. The question JFrame is made of a JLabel that has the actual question, and 4 JRadioButtons that have the different options (named rad1, rad2, rad3, rad4). What I'm trying to do is if the user gets an asnswer wrong, the radio button with the correct answer's background colour turns green and the radio button with the answer that the user gave's background turns red.
Here's the FOR loop that I'm using to figure out which of the answers is correct:
private void btnSubmitActionPerformed(java.awt.event.ActionEvent evt) {
System.out.println("Submit Clicked");
//figures out what choice the user selected
String correctAnswer = questions.get(current).getAnswer();
int numChoice = -1;
String choice = "";
boolean answered = false;
if (rad1.isSelected()) {
numChoice = 0;
answered = true;
choice = rad1.getText();
} else if (rad2.isSelected()) {
numChoice = 1;
answered = true;
choice = rad2.getText();
} else if (rad3.isSelected()) {
numChoice = 2;
answered = true;
choice = rad3.getText();
} else if (rad4.isSelected()) {
numChoice = 3;
answered = true;
choice = rad4.getText();
} else { //user didn't pick a choice
JOptionPane.showMessageDialog(null, "You didn't answer the question, try again!");
}
if (choice.equals(correctAnswer)) {
score++;
System.out.println("score++");
} else {
//figures out which of the answers was correct
rad1.setBackground(Color.RED);
for (int i = 0; i < 4; i++) {
if (questions.get(current).getChoices()[i].equals(correctAnswer)) {
System.out.println(correctAnswer);
System.out.println(i);
//me trying to see if it will change if I put it outside the switch
//confirmed that it will not.
rad1.setBackground(Color.RED);
switch (i) {
case 0:
rad1.setBackground(new Color(51, 204, 51));
break;
case 1:
rad2.setBackground(new Color(51, 204, 51));
break;
case 2:
rad3.setBackground(new Color(51, 204, 51));
break;
case 3:
rad4.setBackground(new Color(51, 204, 51));
break;
}
break;
}
}
switch (numChoice) {
case 0:
rad1.setBackground(new Color(153, 0, 0));
break;
case 1:
rad2.setBackground(new Color(153, 0, 0));
break;
case 2:
rad3.setBackground(new Color(153, 0, 0));
break;
case 3:
rad4.setBackground(new Color(153, 0, 0));
break;
}
}
//loads next question
//loads the next question
if (current < 10) {
updateFrame();
} else {
//ends the quiz
}
}
I've been playing around with the .setBackground() method for a while, and if I put print statements in the case blocks, they execute, but the colouring doesn't happen. Is there something dumb that I'm missing?
Thanks
EDIT: Added more code to see that the FOR loop is within the btnSubmitActionPerformed() method. When the user clicks the button, their answer is to be judged and the colour of the radio button is to be changed.
You look to have code that is overly and unnecessarily complex. Myself, I'd try to "OOP-ify" things to reduce cyclomatic complexity and have
A nonGUI Question class,
with a String field for questionText,
with a String field for correctAnswer,
with a List<String> for incorrectAnswers.
I'd give it a method, say public List<String> getShuffledAnswers() to return a List of Strings with all answers, both correct and incorrect, shuffled in their own list,
A boolean method to testAnswer(String test), and return true of the test equals the correctAnswer.
I'd then create a JPanel called QuestionPanel
that has a Question field
that displays the information of a single Question object, including the questionText in the JLabel and all the shuffled answers in JRadioButtons.
It would have methods for getting the selected JRadioButton and for getting the Question,
And a method for setting making a JRadioButtons background non-opaque when need be, by calling `setOpaque(false)
And a method that allows the calling code to set the background of select JRadioButtons with a correct answer color or incorrect answer color.
For example:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.ButtonModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.SwingUtilities;
#SuppressWarnings("serial")
public class TestQuestions extends JPanel {
private static final Question TEST_QUESTION = new Question("Select the Correct Answer", "This answer is correct",
"Incorrect Answer 1", "Incorrect Answer 2", "Incorrect Answer 3");
private QuestionPanel questionPanel = new QuestionPanel();
public TestQuestions() {
questionPanel.setQuestion(TEST_QUESTION);
JButton testAnswerBtn = new JButton(new AbstractAction("Test Answer") {
#Override
public void actionPerformed(ActionEvent e) {
boolean isCorrect = questionPanel.isCorrectAnswerSelected();
String message = "";
if (isCorrect) {
message = "Correct answer selected!";
} else {
message = "Incorrect answer selected!";
}
JOptionPane.showMessageDialog(TestQuestions.this, message);
questionPanel.displayCorrectWrongAnswers();
}
});
JButton clearAllBtn = new JButton(new AbstractAction("Clear All") {
#Override
public void actionPerformed(ActionEvent e) {
questionPanel.clearAll();
questionPanel.clearSelection();
}
});
JPanel btnPanel = new JPanel(new GridLayout(1, 0, 5, 5));
btnPanel.add(testAnswerBtn);
btnPanel.add(clearAllBtn);
setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
setLayout(new BorderLayout(5, 5));
add(questionPanel, BorderLayout.CENTER);
add(btnPanel, BorderLayout.PAGE_END);
}
private static void createAndShowGui() {
JFrame frame = new JFrame("TestQuestions");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new TestQuestions());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
#SuppressWarnings("serial")
class QuestionPanel extends JPanel {
private static final Color CORRECT_ANSWER_SELECTED_COLOR = new Color(151, 255, 151);
private static final Color CORRECT_ANSWER_NOT_SELECTED_COLOR = new Color(151,151, 255);
private static final Color INCORRECT_ANSWER_SELECTED_COLOR = new Color(255, 151, 151);
private Question question;
private JLabel questionTextLabel = new JLabel();
private List<JRadioButton> answerButtonList = new ArrayList<>();
private JPanel answerPanel = new JPanel(new GridLayout(0, 1));
private ButtonGroup buttonGroup = new ButtonGroup();
public QuestionPanel() {
setLayout(new BorderLayout());
add(questionTextLabel, BorderLayout.PAGE_START);
add(answerPanel, BorderLayout.CENTER);
}
public void setQuestion(Question question) {
this.question = question;
questionTextLabel.setText(question.getQuestionText());
answerPanel.removeAll();
answerButtonList.clear();
buttonGroup = new ButtonGroup();
for (String answer : question.getShuffledAnswers()) {
JRadioButton rBtn = new JRadioButton(answer);
rBtn.setActionCommand(answer);
answerButtonList.add(rBtn);
buttonGroup.add(rBtn);
answerPanel.add(rBtn);
}
}
public boolean isCorrectAnswerSelected() {
ButtonModel model = buttonGroup.getSelection();
if (model == null) {
return false; // nothing selected
} else {
return question.checkAnswer(model.getActionCommand());
}
}
public void clearAll() {
for (JRadioButton jRadioButton : answerButtonList) {
jRadioButton.setOpaque(false);
jRadioButton.setBackground(null);
}
}
public void clearSelection() {
buttonGroup.clearSelection();
}
public void displayCorrectWrongAnswers() {
clearAll();
for (JRadioButton jRadioButton : answerButtonList) {
if (jRadioButton.isSelected()) {
jRadioButton.setOpaque(true);
if (question.checkAnswer(jRadioButton.getActionCommand())) {
jRadioButton.setBackground(CORRECT_ANSWER_SELECTED_COLOR);
} else {
jRadioButton.setBackground(CORRECT_ANSWER_NOT_SELECTED_COLOR);
}
} else if (question.checkAnswer(jRadioButton.getActionCommand())) {
jRadioButton.setOpaque(true);
jRadioButton.setBackground(INCORRECT_ANSWER_SELECTED_COLOR);
}
}
}
}
class Question {
private String questionText;
private String correctAnswer;
private List<String> incorrectAnswerList = new ArrayList<>();
public Question(String questionText, String correctAnswer, String... incorrectAnswers) {
this.questionText = questionText;
this.correctAnswer = correctAnswer;
for (String incorrectAnswer : incorrectAnswers) {
incorrectAnswerList.add(incorrectAnswer);
}
}
public String getQuestionText() {
return questionText;
}
public String getCorrectAnswer() {
return correctAnswer;
}
public List<String> getShuffledAnswers() {
List<String> answers = new ArrayList<>(incorrectAnswerList);
answers.add(correctAnswer);
Collections.shuffle(answers);
return answers;
}
public boolean checkAnswer(String test) {
return correctAnswer.equalsIgnoreCase(test);
}
}
Two immediate things jump to mind:
Where is the code you posted being called from? Making UI changes outside of the Swing worker thread is sort of undefined. Sometimes the right thing will happen, other times not.
I've never tried to set colors on radio buttons, but it seems likely that they don't have a background.
Try setting some other property, like size, just to see if you get a result. If so, then the problem is that radio buttons don't have a background and you'll have to come up with another design. If nothing happens, then it's probably the first problem.
Ok, so I made a program and here's the GUI output...
GUI output
I tried resizing it,but no dice... doesn't work. the jlist 'box' is still somehow cut... Pls help?
Resized Output
By the way, here's the code if needed...
import java.awt.GridLayout;
import java.awt.BorderLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.event.ItemListener;
import java.awt.event.ItemEvent;
import javax.swing.DefaultListModel;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JRadioButton;
import javax.swing.JLabel;
import javax.swing.JButton;
import javax.swing.ButtonGroup;
import javax.swing.JCheckBox;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
public class Order extends JFrame{
JLabel title;
JLabel size;
JLabel top;
JRadioButton b1;
JRadioButton b2;
JRadioButton b3;
JCheckBox c1;
JCheckBox c2;
JCheckBox c3;
JButton process;
ButtonGroup group;
JPanel p1;
JPanel p2;
JPanel p3;
double total;
boolean cb1 = false;
boolean cb2 = false;
boolean cb3 = false;
boolean cheese = false;
boolean tomato = false;
boolean mushroom = false;
String toppings = "Add-on Toppings: ";
double length = 0;
boolean cf = false;
boolean tf = false;
boolean mf = false;
String sizeString;
String num;
String price = "Amount Due: ";
DefaultListModel tops;
double tprice;
String listData[] = new String [3];
JScrollPane pain;
public Order(){
super ("");
p1 = new JPanel();
title = new JLabel("WELCOME TO HAUZ DINNERS");
p1.add(title);
add(p1, BorderLayout.NORTH);
p2 = new JPanel();
p2.setLayout(new GridLayout(4,2));
size = new JLabel("Burger Size");
p2.add(size);
top = new JLabel("Each Add-on Toppings: $1.25");
p2.add(top);
b1 = new JRadioButton("Small: $3.50");
p2.add(b1);
b1.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
total = 3.50;
sizeString = "Burger Size: Small";
}
});
c1 = new JCheckBox("Extra Cheese");
p2.add(c1);
c1.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
if(c1.isSelected()){
cheese = true;
}
else{
cheese = false;
}
if(cheese == true){
length++;
}
else{
length--;
}
}
});
b2 = new JRadioButton("Medium: $4.50");
p2.add(b2);
b2.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
total = 4.50;
sizeString = "Burger Size: Medium";
}
});
c2 = new JCheckBox("Tomato");
p2.add(c2);
c2.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
if(c2.isSelected()){
tomato = true;
}
else{
tomato = false;
}
if(tomato == true){
length++;
}
else{
length--;
}
}
});
b3 = new JRadioButton("Large: $6.00");
p2.add(b3);
b3.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
total = 6.00;
sizeString = "Burger Size: Large";
}
});
c3 = new JCheckBox("Mushrooms");
p2.add(c3);
c3.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
if(c3.isSelected()){
mushroom = true;
}
else{
mushroom = false;
}
if(mushroom == true){
length++;
}
else{
length--;
}
}
});
group = new ButtonGroup();
group.add(b1);
group.add(b2);
group.add(b3);
add(p2, BorderLayout.CENTER);
p3 = new JPanel();
process = new JButton("Process Order");
p3.add(process);
process.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
if(cheese == true){
cf = true;
if((cf == true)&&(tf != true)&&(mf != true)){
toppings = toppings + "Extra Cheese";
}
else{
toppings = toppings + ", Extra Cheese";
}
}
if(tomato == true){
tf = true;
if((cf != true)&&(tf == true)&&(mf != true)){
toppings = toppings + "Tomato";
}
else{
toppings = toppings + ", Tomato";
}
}
if(mushroom == true){
mf = true;
if((cf != true)&&(tf != true)&&(mf == true)){
toppings = toppings + "Mushrooms";
}
else{
toppings = toppings + ", Mushrooms";
}
}
tprice = 1.25 * length;
total = total + tprice;
num = Double.toString(total);
price = price + "$" + num;
listData [0] = sizeString;
listData [1] = toppings;
listData [2] = price;
}
});
JList<String> list = new JList<>(listData);
list.setSelectedIndex(0);
pain = new JScrollPane(list);
p3.add(list);
add(p3, BorderLayout.SOUTH);
}
public static void main(String[]args){
Order frame = new Order();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(350,220);
frame.setVisible(true);
}
}
First, change the layout manager for p3 to something more pratical, rather then the default FlowLayout manager...
p3 = new JPanel();
p3.setLayout(new BorderLayout());
process = new JButton("Process Order");
p3.add(process, BorderLayout.NORTH);
Next, make sure you're adding the JScrollPane to the container and not just the JList
JList<String> list = new JList<>();
list.setSelectedIndex(0);
list.setVisibleRowCount(3);
pain = new JScrollPane(list);
p3.add(pain, BorderLayout.SOUTH);
add(p3, BorderLayout.SOUTH);
Now, things to note. I added list.setVisibleRowCount(3); which gives the JList some sizing hint. I also removed listData from the JList when its constructed, this because the list is array is empty and it JList was using it's contents to determine the "preferred" row size, which was resulting in a very small JList
Which ends up producing something like...
Now, when you click Process Order, you will need to create a ListModel and apply it to your JList, this will require to make the JList available to the ActionListener of the button, probably by making it a instance field
I am having a bit of trouble with the code before. It is doing what I want, but I can only call the method once, if I call it more than that it won't work, essentially it only works once. So right now this ballG is an object. It starts off as White, it sets it to green, has a delay, then sets it back to white, this is perfect. The problem is since I do timerG.start(); and I don't end it, when I call it again it doesn't work. If I do timerG.stop(); it ignores the action event and leaves it green without going back to white. How can I make it so I can call this method multiple times???
import java.awt.BorderLayout;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JTextField;
import javax.swing.JButton;
import javax.swing.JTextArea;
import javax.swing.Timer;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JTextPane;
import javax.swing.JLabel;
import java.awt.Color;
import java.awt.Font;
import java.util.concurrent.TimeUnit;
import javax.swing.JLayeredPane;
import javax.swing.JEditorPane;
public class frame extends JFrame {
private JPanel contentPane;
private JTextField textEntered;
private JTextArea displayT;
private JTextPane textPane;
private JLabel instructions;
private JLabel instructions3;
private JLabel instructions2;
private JLabel ballR;
private JLabel ballG;
private JLabel ballB;
private JPanel panel;
private JTextArea textArea;
private JLabel instructions4;
public String translator(String x)
{
String y = "";
for(int i = 0; i< x.length(); i++)
{
y = y + code(x.charAt(i)) + " ";
}
return y;
}
private String code(char a)
{
switch (a) {
case 'e' : return "R";
case 't' : return "B";
case 'a' : return "G";
case 'o' : return "RB";
case 'i' : return "RG";
case 'n': return "BG";
case 's' : return "R-R";
case 'h' : return "R-B";
case 'r' : return "R-G";
case 'd' : return "R-RB";
case 'l' : return "R-RG";
case 'c' : return "R-BG";
case 'u' : return "B-R";
case 'm' : return "B-B";
case 'w' : return "B-G";
case 'f' : return "B-RB";
case 'g' : return "B-RG";
case 'y' : return "B-BG";
case 'p' : return "G-R";
case 'b' : return "G-B";
case 'v': return "G-B";
case 'k' : return "G-RB";
case 'j' : return "G-RG";
case 'x' : return "G-BG";
case 'q' : return "RB-R";
case 'z' : return "RB-G";
case ' ' : return "RB-B";
case '0' : return "RB-RB";
case '1' : return "RB-RG";
case '2' : return"RB-BG";
case '3' : return "RG-R";
case '4' :return "RG-B";
case '5' : return "RG-G";
case '6' : return "RG-RB";
case '7' : return "RG-RG";
case '8' : return "RG-BG";
case '9' : return "BG-R";
}
return "Z";
}
//Trying to get 1/4 of these methods to work, colorRed, colrGreen, colorBlue,setWhite
private void colorRed()
{
Timer timerR = new Timer(750, new ActionListener(){
#Override
public void actionPerformed(ActionEvent e){
ballR.setForeground(Color.RED);//or RED, depending
}
});
//timer.setRepeats(false);//don't repeat if you don't want to
timerR.start();
ballR.setForeground(Color.WHITE);
}
private void colorGreen()
{
ballG.setForeground(Color.GREEN);
Timer timerG = new Timer(750, new ActionListener(){
#Override
public void actionPerformed(ActionEvent e){
ballG.setForeground(Color.WHITE);//or RED, depending
}
});
timerG.setRepeats(false);
timerG.start();
}
private void colorBlue()
{
Timer timerB = new Timer(750, new ActionListener(){
#Override
public void actionPerformed(ActionEvent e){
ballB.setForeground(Color.BLUE);//or RED, depending
}
});
//timer.setRepeats(false);
timerB.start();
ballR.setForeground(Color.WHITE);
}
private void setWhite()
{
Timer timer = new Timer(750, new ActionListener(){
#Override
public void actionPerformed(ActionEvent e){
ballB.setForeground(Color.WHITE);
ballR.setForeground(Color.WHITE);
ballG.setForeground(Color.WHITE);
}
});
//timer.setRepeats(false);
timer.start();
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
frame frame = new frame();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public frame() {
setTitle("RBG Translator");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 800, 529);
contentPane = new JPanel();
contentPane.setBackground(Color.GRAY);
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
textEntered = new JTextField();
textEntered.setText("Enter String...");
textEntered.setBounds(10, 124, 261, 50);
contentPane.add(textEntered);
textEntered.setColumns(10);
JButton submit = new JButton("Submit");
submit.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
ballR.setForeground(Color.WHITE);
ballB.setForeground(Color.WHITE);
ballG.setForeground(Color.WHITE);
String input = textEntered.getText().toLowerCase();
String output = translator(input);
displayT.setText(output);
//colorRed();
colorGreen();
//colorRed();
//colorBlue();
colorGreen();
colorGreen();
}
});
submit.setBounds(281, 125, 138, 50);
contentPane.add(submit);
displayT = new JTextArea();
displayT.setBounds(10, 246, 409, 234);
displayT.setLineWrap(true);
contentPane.add(displayT);
instructions = new JLabel("Please enter a word or a phrase that you would like to be transalted\r\n");
instructions.setBounds(10, 11, 396, 14);
contentPane.add(instructions);
instructions3 = new JLabel("Below is a translated text of the word or phrase submitted");
instructions3.setBounds(10, 205, 409, 34);
contentPane.add(instructions3);
instructions2 = new JLabel("into RBG code. Currently A-Z, 0-9, and space are permitted.");
instructions2.setBounds(10, 24, 396, 34);
contentPane.add(instructions2);
panel = new JPanel();
panel.setBounds(470, 25, 304, 169);
contentPane.add(panel);
ballR = new JLabel("\u2022");
panel.add(ballR);
ballR.setForeground(Color.RED);
ballR.setFont(new Font("Tahoma", Font.PLAIN, 99));
ballB = new JLabel("\u2022");
panel.add(ballB);
ballB.setForeground(Color.BLUE);
ballB.setFont(new Font("Tahoma", Font.PLAIN, 99));
ballG = new JLabel("\u2022");
panel.add(ballG);
ballG.setForeground(Color.GREEN);
ballG.setFont(new Font("Tahoma", Font.PLAIN, 99));
textArea = new JTextArea();
textArea.setLineWrap(true);
textArea.setColumns(4);
textArea.setText("a:G k:G-RB u:B-R 4:RG-B "
+ "b:G-B l:R-RG v:G-G 5:RG-G "
+ "c:R-BG m:B-B w:B-G 6:RG-RB "
+ "d:R-RB n:BG x:G-BG 7:RG-RG "
+ "e:R o:RB y:B-BG 8:RG-BG "
+ "f:B-RB p:G-R z:RB-G 9:BG-R "
+ "g:B-RG q:RB-R 0:RB-RB :RB-B "
+ "h:R-B r:R-G 1:RB-RG "
+ "i:RG s:R-R 2:RB-BG "
+ "j:G-RG t:B 3:RG-R " );
textArea.setBounds(429, 246, 345, 234);
contentPane.add(textArea);
instructions4 = new JLabel("Key\r\n");
instructions4.setBounds(429, 205, 345, 34);
contentPane.add(instructions4);
}
}
(I really don't know what your "codes" are doing, as R-RB doesn't seem to make sense, how do you display R, G and B?)
Okay, you need to start by generating some kind of sequence that you want displayed. This will allow the Timer to act as a pseudo loop and update the UI according to the current sequence set
private String[] sequence;
private int index;
private Timer timer;
//...
public Test() {
//...
JButton submit = new JButton("Submit");
submit.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
ballR.setForeground(Color.WHITE);
ballB.setForeground(Color.WHITE);
ballG.setForeground(Color.WHITE);
String input = textEntered.getText().toLowerCase();
String output = translator(input);
displayT.setText(output);
timer.stop();
System.out.println(output);
List<String> firstPass = new ArrayList<>(Arrays.asList(output.split(" ")));
List<String> fullPass = new ArrayList<>(25);
for (String pass : firstPass) {
if (pass.contains("-")) {
String[] parts = pass.split("-");
fullPass.addAll(Arrays.asList(parts));
} else {
fullPass.add(pass);
}
}
sequence = fullPass.toArray(new String[fullPass.size()]);
index = 0;
timer.start();
}
});
Basically, this assumes that each space is a separate sequence to be displayed
Next, you need to setup a single Timer which can play through the sequences
timer = new Timer(750, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
ballR.setForeground(Color.WHITE);
ballG.setForeground(Color.WHITE);
ballB.setForeground(Color.WHITE);
if (index < sequence.length) {
String set = sequence[index];
System.out.println(index + " = " + set);
for (char c : set.toCharArray()) {
if ('R' == c) {
ballR.setForeground(Color.RED);
} else if ('G' == c) {
ballG.setForeground(Color.GREEN);
} else if ('B' == c) {
ballB.setForeground(Color.BLUE);
}
}
} else {
timer.stop();
}
index++;
}
});
Okay, so, this takes the next String sequence and breaks it down into invidual elements, by spiting the String on the - character (which is why you "codes" don't make sense to me). It then loops through this set and changes the state of the "balls" accordingly.
The Timercontinues` until there are no more sequences left...
Avoid using null layouts, pixel perfect layouts are an illusion within modern ui design. There are too many factors which affect the individual size of components, none of which you can control. Swing was designed to work with layout managers at the core, discarding these will lead to no end of issues and problems that you will spend more and more time trying to rectify