JPanel does not appear correctly while extending JFrame - java

This is my homework.
My directions:
Class GuessGame: This class contains the main function which creates a JFrame object, sets up the JFrame’s size, visibility and exit.
Class GuessGameFrame: GuessGameFrame class extends JFrame. So the GuessGameFrame class has all variables and methods defined in class JFrame.
I am not 100% sure what my problem is but I believe the JPanel is not working correctly
Any help would greatly be appreciated, if I left out anything important please let me know and I can add more detail.
main class:
public class GuessGame {
public static void main(String[] args){
GuessGameFrame localGuessGameFrame = new GuessGameFrame();
localGuessGameFrame.setVisible(true); //set visible
localGuessGameFrame.setSize(380,175); // set size 380 width 175 height
localGuessGameFrame.setDefaultCloseOperation(localGuessGameFrame.EXIT_ON_CLOSE); // needed to enable the red X button to close the program
}
}
extended class:
import javax.swing.*;
import java.awt.*;
public class GuessGameFrame extends JFrame
{
private int lastDistance; // distance between last guess and number
private Color background; // background color of application
private JFrame f;
static JPanel p;
private JButton b1;
private JLabel l1;
private JLabel l2;
JTextField t1 = new JTextField(8);
private JLabel l3;
//declare constructor
public GuessGameFrame()
{
//create our JFrame
f = new JFrame("Guessing game");
//create our panel
p = new JPanel();
p.setBackground(Color.MAGENTA); // background color is magenta
//create our labels
l1 = new JLabel("I have a number between 1 and 1000.");
l2 = new JLabel("Can you guess my number? Enter your first Guess:.");
l3 = new JLabel("Guess result appears here.");
//create our button
b1 = new JButton("New Game");
//add button and label to panel
p.add(l1); // Adds label 1
p.add(l2); // adds label 2
p.add(t1); // adds textfield 1
p.add(l3); // adds label 3
p.add(b1); // adds button 1
//add panel to JFrame
f.add(p);
}
}
Screenshot of the output window when executed:
I expect it to look like this:

You need remove JFrame f in GuessGameFrame class because GuessGameFrame is already a JFrame:
And update your code:
f = new JFrame("Guessing game"); to this.setTitle("Guessing game");
f.add(p); to this.getContentPane().add(p);

Related

Blank panel - When loading panel from another class (frame created in the base class)

I have created 3 classes (code given below).
BasicDetails - base class - frame created here along with a panel
GradeSubjectList - derived class - another panel created here and loaded in the frame created in the base class
SubjectList - derived class - another panel created here and loaded in the frame created in the base class
Base class has a panel of its own and on click of the button loads the panel created in GradeSubjectList. A button created in this panel calls a function in base class which inturn loads the panel created in SubjectList in the frame created in the base class.
The panel created in BasicDetails and GradeSubjectList load with any issues, and when the panel created in SubjectList is being loaded in the frame created in the base class displays only in a blank frame
public class BasicDetails{
static int lec_no;
static int sub_no;
JFrame frame = new JFrame("Time Table");
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
JPanel panel_bd = new JPanel();
public static void main(String[] args) {
BasicDetails bd = new BasicDetails();
bd.main_method_bd();
}
public void main_method_bd() {
panel_bd.setBackground(Color.white);
frame.setExtendedState(java.awt.Frame.MAXIMIZED_BOTH);
panel_bd.setLayout(null);
JLabel lec_no_lbl = new JLabel("Enter the number of lectures required per day:");
JTextField lec_no_txt = new JTextField(5);
lec_no_txt.setText("5");
JButton next_btn_1 = new JButton("Next");
panel_bd.add(lec_no_lbl);
panel_bd.add(lec_no_txt);
panel_bd.add(next_btn_1);
lec_no_lbl.setBounds(5,100,300,20);
lec_no_txt.setBounds(320,100,50,20);
next_btn_1.setBounds(520,350,100,20);
next_btn_1.addActionListener(e->
{
lec_no=Integer.parseInt(lec_no_txt.getText());
panel_bd.setVisible(false);
gsl(); //calls function to load the next panel
});
frame.setSize(screenSize.width,screenSize.height);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.add(panel_bd);
}
//----this function loads the panel from GradeSubjectList.java
public void gsl() {
GradeSubjectList GSL = new GradeSubjectList();
JPanel gsl_panel = GSL.main_method_gsl();
frame.add(gsl_panel);
}
//-----this function loads the panel from SubjectList.java (this function gets called from GradeSubjectList.java but the panel does not load)
public void sl() {
SubjectList sl = new SubjectList();
JPanel sl_panel = sl.main_mehod_sl();
frame.add(sl_panel);
}
}
public class GradeSubjectList extends BasicDetails{
JComboBox grd_cb = new JComboBox();
JComboBox sub_cb_1 = new JComboBox();
public JPanel main_method_gsl() {
//-------Panel creation and loading components------------
JPanel panel_gsl = new JPanel();
panel_gsl.setBackground(Color.blue);
panel_gsl.setLayout(null);
JLabel tec_details_txt = new JLabel("Select the Grades and Subjects");
JButton next_btn_5 = new JButton("Next");
next_btn_5.setBounds(600,500,150,20);
tec_details_txt.setBounds(100,50,250,20);
grd_cb.setBounds(10,100,100,20);
sub_cb_1.setBounds(130,100,100,20);
panel_gsl.add(tec_details_txt);
panel_gsl.add(next_btn_5);
panel_gsl.add(grd_cb);
panel_gsl.add(sub_cb_1);
//On click perform actions
next_btn_5.addActionListener(e->
{
panel_gsl.setVisible(false);
sl(); //---------calls function in BasicDetails.java to load the next panel
});
return(panel_gsl); ////------returns panel to BasicDetails.java to load it in the frame
}
}
public class SubjectList extends BasicDetails{
public JPanel main_mehod_sl() {
//-------Panel creation and loading components------------
JPanel panel_sl = new JPanel();
panel_sl.setBackground(Color.white);
panel_sl.setLayout(null);
JLabel sub_list_lbl = new JLabel("Enter Subject Name");
JLabel max_day_lbl = new JLabel("Max Lectures Per Day");
JLabel max_week_lbl = new JLabel("Max Lectures Per Week");
sub_list_lbl.setBounds(25,50,150,20);
max_day_lbl.setBounds(200,50,150,20);
max_week_lbl.setBounds(375,50,150,20);
JButton next_btn_2 = new JButton("Next");
next_btn_2.setBounds(600,500,150,20);
JTextField sub_name_txt = new JTextField();
JTextField max_day_txt = new JTextField();
JTextField max_week_txt = new JTextField();
sub_name_txt.setBounds(25,100,150,20);
max_day_txt.setBounds(200,100,105,20);
max_week_txt.setBounds(375,100,150,20);
panel_sl.add(sub_list_lbl);
panel_sl.add(max_day_lbl);
panel_sl.add(max_week_lbl);
panel_sl.add(next_btn_2);
panel_sl.add(sub_name_txt);
panel_sl.add(max_day_txt);
panel_sl.add(max_week_txt);
//On click action
next_btn_2.addActionListener(e->
{
panel_sl.setVisible(false);
});
return(panel_sl); //------returns panel to BasicDetails.java to load it in the frame
}
}
I have changed the order in which the panels are loaded from other classes. I noticed that the panel which is being loaded first (from the other class) does load without any problem while the other panel does not.
for e.g. if the order is
GradeSubjectList - panel loads properly
SubjectList - panel does not show
and is the order is changed
SubjectList - panel loads properly
GradeSubjectList - panel does not show
So my guess is the most of the code is working fine...cannot just figure out where it is going wrong...
The main problem that the third panel in the sequence is not visible, is because it is added to a new instance of JFrame each time. Because SubjectList inherits from BasicDetails (same for GradeSubjectList) and because frame reference is not static, each new BasicDetails object (including any new instance of GradeSubjectList and SubjectList) gets a new instance of JFrame where the next panel in the sequence (when pressing the respective Next button) is added to that new JFrame.
A solution would be to make the frame a static reference and/or revisit your class diagram.
Other than that, always try to use a LayoutManager (instead of setLayout(null);). In your case a CardLayout would handle the job of setting [in]visible each panel in the sequence when needed, so that you wouldn't have to do it manually. You can also use a LayoutManager for each panel you add to the frame (such as a GridBagLayout for example).

Trouble with java GUI. I can't get JRadioButtons to display in JLabel

I am new to Java; but I'm having a blast. I feel like I'm missing something really simple; but I can't figure it out.
I want the RadioButtons to be displayed inside the JFrame."
public class HelloWorldFrame extends JFrame
{
private TitledBorder title;
public HelloWorldFrame()
{
super("Hello World! ");
JFrame helloWorld = new JFrame();
JLabel label = new JLabel();
title = BorderFactory.createTitledBorder("Language");
title.setTitleJustification(TitledBorder.LEFT);
label.setBorder(title);
add(label);
setSize(300, 200);
JRadioButton button1 = new JRadioButton("English");
JRadioButton button2 = new JRadioButton("French");
JRadioButton button3 = new JRadioButton("Spanish");
ButtonGroup bG = new ButtonGroup();
bG.add(button1);
bG.add(button2);
bG.add(button3);
label.add(button1);
label.add(button2);
label.add(button3);
helloWorld.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
//The main class starts here
public class HelloWorldApp
{
public static void main(String[] args)
{
JFrame helloWorld = new HelloWorldFrame();
helloWorld.setVisible(true);
}
}
The first question is why? Why do you want to add the radio buttons to a JLabel?
Having said that, you can set the labels layout manager to something other then it's default value of null...
label.setLayout(new FlowLayout());
label.add(button1);
label.add(button2);
label.add(button3);
Next...your class extends from JFrame, but in your constructor, you are creating another JFrame, this means that when you do...
JFrame helloWorld = new HelloWorldFrame();
helloWorld.setVisible(true);
Nothing will be displayed, because nothing has been added to the frame.
Instead, make your class extend from something like JFrame and then add that to your JFrame in main
Updated
I just did some testing and doing this (adding buttons to a label) won't work well, as the JLabel calculates it's preferred size based on the text and icon, not it's contents (like something like JPanel would)...just saying...

ActionListener not recognizing variables from main class

I am trying to create a GUI payroll calculator for a Java class I am taking. The requirements were that it must take the user inputs (one using a JComboBox), calculate the weekly pay and add the results to a JTable. The user should be able to continue calculating for other employees and have an exit button. I created the GUI in the main class and need two ActionListeners, one to exit and one to calculate and add to the JTable.
My problem is that when I start working on the calculate ActionListener, it is not recognizing the variables I set in the main class. I have tried making them public, using the main class name DOT variable name (PayrollCalc.empName), initializing them and nothing seems to work. The code is not complete, as I have not even started to add to the JTable until I can get the actual calculations done first. Does anyone have any suggestions?
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class PayrollCalc {
public static void main(String[] args) {
//Declare variables used
String empName = null, entDept = null, calcdPay = null;
String[] empDept = {"Marketing","IT","Accounting","Development","Payroll","Facilities"};
String columnNames[] = {"Name","Department","Pay Check"};
String dataValues [][] = {
{empName,entDept,calcdPay}
};
double wrkHours = 0;
double empRate = 0;
double wklyPay = 0;
//Create JTable and scrollPane for output
JTable table;
JScrollPane scrollPane;
table = new JTable (dataValues,columnNames);
scrollPane = new JScrollPane(table);
//Create JFrame object with title
JFrame frame = new JFrame("Employee Payroll Calculator");
//Create combo box for department choices
JComboBox combo = new JComboBox(empDept);
JTextField nameField = new JTextField(15);
JTextField hourField = new JTextField(10);
JTextField rateField = new JTextField(10);
//Create JLables for input fields
JLabel nameLbl = new JLabel ("Name:");
JLabel hourLbl = new JLabel ("Hours:");
JLabel rateLbl = new JLabel ("Rate:");
JLabel deptLbl = new JLabel ("Department:");
//Create buttons for ActionListners
JButton exitButton= new JButton("Exit");
exitButton.addActionListener(new exitApp());
exitButton.setSize(5,5);
JButton calcButton= new JButton("Calculate");
calcButton.addActionListener(new calcApp());
calcButton.setSize(5,5);
//Create panels
Panel panel1 = new Panel();
panel1.add(nameLbl);
panel1.add(nameField);
panel1.add(deptLbl);
panel1.add(combo);
panel1.add(hourLbl);
panel1.add(hourField);
panel1.add(rateLbl);
panel1.add(rateField);
panel1.add(rateField);
Panel panel2 = new Panel();
panel2.add(calcButton);
Panel panel3 = new Panel();
panel3.add(calcButton);
panel3.add(exitButton);
Panel panel4 = new Panel();
panel4.add(scrollPane, BorderLayout.CENTER);
//creates the frame
frame.setSize(950,200);
frame.add(panel1,BorderLayout.NORTH);
frame.add(panel2);
frame.add(panel3, BorderLayout.SOUTH);
frame.add(panel4);
frame.setVisible(true);
}
//ActionListner for Exit button
static class exitApp implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
System.exit(0);
}
}
//ActionListner for Calculate button
static class calcApp implements ActionListener
{
public void actionPerformed(ActionEvent c)
{
empName = nameField.getText();
entDept = combo.getName();
wrkHours = Double.parseDouble(hourField.getText());
empRate = Double.parseDouble(rateField.getText());
wklyPay = wrkHours * empRate;
calcdPay = new Double(wklyPay).toString();
}
}
}
Look , every variable has its Scope ... and you have not defined anything as a member class variable so nothing will act as a global variable .
you have defined variable inside main method () so their scope is limited to only main method thats the reason behind your problem .
Since the variables you're trying to access in your ActionListener are local to your main() they are not visible to your static class. Also, initializing your GUI inside the static main() is forcing the use of statics every where which as you can tell from the comments below is a bad practice.
So, move the initialization out to a constructor and the local variables as instance level member fields. Along with this you would need to switch from static nested classes to using inner classes instead.
Instance members of your class would then be available to your inner ActionListener classes.
public class PayrollCalc {
//Declare variables used
private String empName = null, entDept = null, calcdPay = null;
private double wrkHours = 0;
private double empRate = 0;
private double wklyPay = 0;
private JComboBox combo;
private JTextField nameField;
private JTextField hourField;
private JTextField rateField;
public static void main(String[] args) {
new PayrollCalc();
}
public PayrollCalc() {
// ...
combo = new JComboBox(empDept);
nameField = new JTextField(15);
hourField = new JTextField(10);
rateField = new JTextField(10);
// ...
}
// non-static ActionListener inner classes
}

Java Displaying String on a JTextField after a JButton in a separate class is pressed

Currently working on a school project in which I am making a wheel of fortune replica in Java. I have a panel of JButtons within a class called buttonPanel, and a separate class, wheelGUI, which acts as the class that the program runs through. What I want to happen is when the JButton spin is pressed on the GUI, it assigns a random value from String[] wheelStuff to a String, spinValue,using the method spinWheel which acts as the parameter for the JTextField results, and then displays that random value on the Cyan box in the GUI. In non-technical terms, when the button spin is pressed, display a random value in the Cyan box which acts as the current players' spin value. Here is the code for the class buttonPanel
package wheelOfFortune;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class buttonPanels extends JPanel
implements ActionListener
{
private JButton spin, solve, buyVowel, guess, reset, end, cont;
Color yungMoney = new Color(0, 180, 100);
private static String[] wheelStuff = new String[]{"Bankrupt", "Lose a Turn", "$5000", "$600", "$500", "$300", "$800", "$550", "$400", "$900", "$350", "$450", "$700"};
public buttonPanels()
{
setBackground(yungMoney);
spin = new JButton("Spin!");
spin.addActionListener(this);
solve = new JButton("Solve the Puzzle");
solve.addActionListener(this);
buyVowel = new JButton("Buy a Vowel");
buyVowel.addActionListener(this);
guess = new JButton("Guess a Letter");
guess.addActionListener(this);
reset = new JButton("Reset");
reset.addActionListener(this);
cont = new JButton("Continue");
cont.addActionListener(this);
JPanel buttonPanel = new JPanel(new GridLayout(3, 1, 5, 5));
buttonPanel.setPreferredSize(new Dimension(300,380));
buttonPanel.setBackground(yungMoney);
buttonPanel.add(spin);
buttonPanel.add(guess);
buttonPanel.add(buyVowel);
buttonPanel.add(solve);
buttonPanel.add(cont);
buttonPanel.add(reset);
add(buttonPanel);
}
public void actionPerformed(ActionEvent e)
{
JButton b = (JButton)e.getSource();
b.addActionListener(this);
if(b==spin)
{
wheelGUI.spinWheel(wheelStuff);
}
repaint();
}
}
And here is the code for the main class, wheelGUI
package wheelOfFortune;
import java.awt.*;
import java.awt.event.*;
import java.io.IOException;
import java.util.Random;
import javax.swing.*;
public class wheelGUI extends JFrame implements ActionListener {
private playerPlate player1, player2, player3;
Color yungMoney = new Color(0, 180, 100);
private String fileName = "M:/wheelOfFortune/src/wheelOfFortune/img/wheel1.png";
private String cat;
private static String spinValue = "";
private static String[] wheelStuff = new String[]{"Bankrupt", "Lose a Turn", "$5000", "$600", "$500", "$300", "$800", "$550", "$400", "$900", "$350", "$450", "$700"};
private static JTextField results;
public wheelGUI() {
super("Butt Stuff!");
ImageIcon i = new ImageIcon(fileName);
JLabel picture = new JLabel(i);
player1 = new playerPlate("Garrett", Color.RED);
player2 = new playerPlate("Jonny", Color.YELLOW);
player3 = new playerPlate("Robert", Color.BLUE);
buttonPanels buttons = new buttonPanels();
letterBoard letters = new letterBoard();
catBox category = new catBox(cat);
inputField input = new inputField();
Box wall = Box.createHorizontalBox();
wall.add(player1);
wall.add(Box.createHorizontalStrut(5));
wall.add(player2);
wall.add(Box.createHorizontalStrut(5));
wall.add(player3);
JPanel result = new JPanel();
result.setBackground(yungMoney);
JTextField results = new JTextField(spinValue);
results.setBackground(Color.CYAN);
results.setHorizontalAlignment(JTextField.CENTER);
results.setBorder(BorderFactory.createLineBorder(Color.BLACK,2));
results.setPreferredSize(new Dimension(150,100));
results.setFont(new Font("Impact", Font.PLAIN, 28));
results.setEditable(false);
result.add(results);
Box catInput = Box.createVerticalBox();
catInput.add(category);
catInput.add(Box.createVerticalStrut(50));
catInput.add(result);
catInput.add(Box.createVerticalStrut(100));
catInput.add(input);
Container c = getContentPane();
c.setBackground(yungMoney);
c.add(buttons, BorderLayout.EAST);
c.add(wall, BorderLayout.SOUTH);
c.add(letters, BorderLayout.NORTH);
c.add(picture, BorderLayout.WEST);
c.add(catInput, BorderLayout.CENTER);
}
public static String spinWheel(String[] wheelStuff)
{
Random rnd = new Random();
wheelStuff[rnd.nextInt(wheelStuff.length)] = spinValue;
return spinValue;
}
public static void main(String[] args) {
wheelGUI window = new wheelGUI();
window.setBounds(50, 50, 1024, 768);
window.setDefaultCloseOperation(EXIT_ON_CLOSE);
window.setResizable(false);
window.setVisible(true);
}
public void actionPerformed(ActionEvent e)
{
// logic for any additional panels. other logics should be in individual
// classes.
}
}
Thanks for your help! Note: all of the code in wheelGUI that isn't related to something previously stated can be ignored, it's from various other classes.
The use of static fields in this manner is not recommended.
Instead, the buttonsPanel should be taking a reference of the wheelGUI. This will allow the buttonsPanel to call the required methods on the wheelGUI when it needs to.
A better solution would be to use a model which can sit between the two UIs and model the logic, firing events as parts of the model change
Your primary problem is your shadowing the results textfield. That is, you've declared and class level, static field and then redeclared it within your constructor
Change the following line in your wheelGUI constructor
JTextField results = new JTextField(spinValue);
To
results = new JTextField(spinValue);
This will mean when you set the text on the results field, you will be setting the value of the correct instance of the field.

Actionlistener java

For my class I need to use my ActionListener. I am having trouble adding my ActionListener to my buttons. I have to use the word "this" like this.buttons to add my ActionListener but Im having trouble doing that. I will get to my actionPerformed method later but my main problem is my ActionListener.
public class TextButtonsHW extends JFrame implements ActionListener {
private JButton[] buttons; //Do not change
private JTextArea textArea; //Do not change
//Assign values for these constants in the constructor
private final int ENTER; //Index of Enter button in buttons
private final int SPACE; //Index of Space button in buttons
private final int CLEAR; //Index of Clear button in buttons
/**
* Set up this frame and its contents.
* #param title Title to appear in JFrame title bar
*/
public TextButtonsHW(String title) {
super(title); //call parent JFrame constructor to set the title
buttons = new JButton[] { new JButton("A"), new JButton("B"), new JButton("C"),
new JButton("1"), new JButton("2"), new JButton("3"),
new JButton("X"), new JButton("Y"), new JButton("Z"),
new JButton("Enter"), new JButton("Space"), new JButton("Clear")};
ENTER = buttons.length-3;
SPACE = buttons.length-2;
CLEAR = buttons.length-1;
textArea = new JTextArea(15, 5);
textArea.setEditable(false);
this.buttons[0].addActionListener(I dont know what to put right here);
//TODO: instantiate all JButtons, add them to the buttons array,
// and register "this" as the ActionListener for each button.
//DONE
//TODO: assign values to ENTER, SPACE, and CLEAR constants to
// indicate the indexes of those buttons in the buttons array
//DONE
//TODO: create the JTextArea textArea
//TODO: set its "editable" property to false
//DONE
//Create a TextButtonsHWPanel to display the buttons and textArea
TextButtonsHWPanel mainPanel = new TextButtonsHWPanel(buttons, textArea);
this.getContentPane().add(mainPanel);
this.pack();
}
public void actionPerformed(ActionEvent e) {
//TODO: update the text of textArea according to which
// button generated the ActionEvent.
}
public static void main(String[] args) {
final TextButtonsHW f = new TextButtonsHW("Text Buttons");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setLocationRelativeTo(null); //centers frame on screen
f.setVisible(true);
}
}
buttons[0].addActionListener(this);
Since you have 12 buttons you could also go for a for-loop to add ActionListener to all your buttons i.e.
for(int i=0; i<12; i++)
{
buttons[i].addActionListener(this);
}
Instead of a long code i.e.
buttons[0].addActionListener(this);
buttons[1].addActionListener(this);
........................
Though buttons[0].addActionListener(this); will work well, From design perspective I will suggest to have separate class (may be inner class) which implements ActionListner and pass its object reference to the method.
the whole point of Object Oriented programming is to delegate different responsibilities to different Objects(classes), so code becomes more maintainable and reusable.

Categories