I am pretty new to Java(about 2 weeks in), and I am trying to set the text of a JLabel. The only problem is I am doing calculations in another class and I don't know how to reference the Jlabel I have already created. Here are the two classes in question.
package fightsim;
import javax.swing.JPanel;
import net.miginfocom.swing.MigLayout;
import javax.swing.JLabel;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class FightSimPane extends JPanel {
FightManager FightManager = new FightManager();
/**
* Create the panel.
*/
public FightSimPane() {
setLayout(new MigLayout("", "[][][][][][][][][][]", "[][][][]"));
JLabel lblChampionleft = new JLabel("ChampionLeft");
add(lblChampionleft, "cell 1 3");
JButton btnGo = new JButton("Go");
btnGo.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
FightManager.startFight();
FightManager.runTheFight();
}
});
add(btnGo, "cell 5 3");
JLabel lblChampionright = new JLabel("ChampionRight");
add(lblChampionright, "cell 9 3");
}
public void setLeftChampionLabel(String s){
//not able to reference Jlabel lblChampionLeft here???
System.out.println("Setting Left Champion text to"+s);
}
public void setRightChampionLabel(String s){
//not able to reference Jlabel lblChampionRight here???
System.out.println("Setting Right Champion text to"+s);
}
}
And the class that is trying to set the Label.
package fightsim;
public class FightManager {
Champion LeftChamp = new Champion();
Champion RightChamp = new Champion();
public FightManager() {
}
Thread LeftChampThread = new Thread(LeftChamp);
Thread RightChampThread = new Thread(RightChamp);
;
public void startFight() {
LeftChamp.setHealth(200);
RightChamp.setHealth(300);
LeftChamp.setATKsp(1000);
RightChamp.setATKsp(1000);
LeftChamp.setAD(20);
RightChamp.setAD(20);
}
public void runTheFight() {
System.out.println("Starting Threads");
LeftChampThread.start();
RightChampThread.start();
while ((LeftChamp.getHealth() > 0) && (RightChamp.getHealth() > 0)) {
if (RightChamp.isReadyToAttack()) {
LeftChamp.setHealth(LeftChamp.getHealth() - RightChamp.getAD());
RightChamp.setNotReady();
System.out.println("Setting Left Champion test to"
+ Integer.toString(LeftChamp.getHealth()));
// This is where I'd like to update the left Jlabel in
// FightSimPane
}
if (LeftChamp.isReadyToAttack()) {
RightChamp
.setHealth(RightChamp.getHealth() - LeftChamp.getAD());
LeftChamp.setNotReady();
System.out.println("Setting Right Champion test to"
+ Integer.toString(RightChamp.getHealth()));
// This is where I'd like to update the right Jlabel in
// FightSimPane
}
}
}
}
So, the question...How do I let my FightManager Class access and change the JLabel in my FightSimPane Class/Gui. Thanks in advance, and sorry if this is a stupid question. I am terribly new to programming and I'm still trying to take it all in. With that said, any other advice would be great. Thanks!
Pass references around so that classes can communicate with each other, and not only that but with the correct active instance of the class of the other type. For instance, you could give FlightManager a FlightSimPane field:
class FightManager {
private FightSimPane fightSimPane;
// and fill it in the constructor:
public FightManager(FightSimPane fightSimPane) {
this.fightSimPane = fightSimPane;
}
Then you'll be dealing with the actual visualized FightSimPane GUI object.
Note that you'll have to take care to pass in the correct instance:
public class FightSimPane extends JPanel {
FightManager FightManager = new FightManager(this);
Then you can call the public methods of FightSimPane in the FightManager class:
public void runTheFight() {
System.out.println("Starting Threads");
LeftChampThread.start();
RightChampThread.start();
while ((LeftChamp.getHealth() > 0) && (RightChamp.getHealth() > 0)) {
if (RightChamp.isReadyToAttack()) {
LeftChamp.setHealth(LeftChamp.getHealth() - RightChamp.getAD());
RightChamp.setNotReady();
System.out.println("Setting Left Champion test to"
+ Integer.toString(LeftChamp.getHealth()));
// !!! **** added this *************
fightSimPane.setRightChampionLabel("Setting Left Champion test to"
+ Integer.toString(LeftChamp.getHealth()));
}
EDIT 1
I see another potentially serious and unrelated problem here:
while ((LeftChamp.getHealth() > 0) && (RightChamp.getHealth() > 0)) {
//.........
}
This code appears to be called on the main Swing thread, the EDT and it's nature (while (true)) suggests that it has a very good chance of locking up the EDT bringing your Swing GUI's graphics processing and updating and all user interactions to a screeching halt. You may need to use a Swing Timer for this or a background thread so as to leave the EDT free to do its necessary work.
Declare the reference variable of FightSimPane class in FightManager class and pass the reference of FightSimPane object via the constructor of FightManager.
In FightManager class,
public class FightManager {
Champion LeftChamp = new Champion();
Champion RightChamp = new Champion();
private FightSimPane pane;
public FightManager(FightSimPane pane) { this.pane=pane;}
public FightManager() {
}
....
Using "pane" reference variable you can access accessible elements of FightSimPane class.
Modify the FightSimPane code,
public class FightSimPane extends JPanel {
FightManager fightManager;
public FightSimPane() {
fightManager= new FightManager(this);
...
}
Related
I've encountered a problem while trying to call a method within a class that implements actionListener. The method being called, DataCompiler, needs to use the integer wordCountWhole, which is returned in the wordCount class. The problem is that I can't pass the required parameter to the actionListener method.
import javax.swing.*;
import java.awt.*;
import java.awt.List;
import java.awt.event.*;
import java.beans.PropertyChangeListener;
import java.text.BreakIterator;
import java.util.*;
import java.util.stream.IntStream;
public class GUI extends JFrame {
public JTextArea textInput;
public JButton dataButton;
public String str;
public GUI() {
super("Text Miner");
pack();
setLayout(null);
dataButton = new JButton("View Data"); //Button to take user to data table
dataButton.setSize(new Dimension(120, 50));
dataButton.setLocation(5, 5);
Handler event = new Handler(); //Adds an action listener to each button
dataButton.addActionListener(event);
add(dataButton);
public class wordCount {
public int miner() {
//This returns an integer called wordCountWhole
}
}
public class Handler implements Action { //All the possible actions for when an action is observed
public void action(ActionEvent event, int wordCountWhole) {
if (event.getSource() == graphButton) {
Graphs g = new Graphs();
g.Graphs();
} else if (event.getSource() == dataButton) {
DataCompiler dc = new DataCompiler();
dc.Data(wordCountWhole);
} else if (event.getSource() == enterButton) {
wordCount wc = new wordCount();
sentenceCount sc = new sentenceCount();
wc.miner();
sc.miner();
}
}
}
}
And here's the code for the DataCompiler class:
public class DataCompiler{
public void Data(int wordCountWhole){
int m = wordCountWhole;
System.out.println(m);
}
}
You don't add the parameter there because you've invalidated the contract of the interface.
Use a constructor* (see note below, first)
public class Handler implements Action{ //All the possible actions for when an action is observed
private int wordCountWhole;
public Handler(int number) { this.wordCountWhole = number; }
#Override
public void actionPerformed(ActionEvent event) {
Although, it isn't entirely clear why you need that number. Your DataCompiler.Data method just prints the number passed into it, and that variable seemingly comes from nowhere in your code because it is not passed to the ActionListener.
* You should instead use Integer.parseInt(textInput.getText().trim()) inside Handler class / the listener code and not use a constructor. Otherwise, you'd always get the number value when you add the Handler, which would be an empty string and throw an error because the text area has no number in it.
Additionally, wc.miner(); returns a value, but calling it on its own without assigning it to a number just throws away that return value.
I'm going off of what I saw in a textbook to make an action listener for a button. To do it, I made an inner class. When I try to call the inner class, the error comes up: cannot find symbol.
Here's the code:
package GUI;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ATMGUI extends GUI
{
public ATMGUI()
{
this.makePane();
this.makeButton("Withdraw");
button.addActionListener(new WithdrawListener());
pane.add(button);
this.makeText("Enter amount to withdraw: ");
pane.add(text);
this.makeTextField("Enter amount here");
pane.add(field);
this.makeFrame();
frame.add(pane);
class WithdrawListener implements ActionListener
{
public void actionPerformed(ActionEvent click)
{
System.out.println("This is a test.");
}
}
}
//------------------------------------------------------------------
public void makeFrame()
{
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 500);
frame.setVisible(true);
}
public void makePane()
{
pane = new JPanel();
pane.setLayout(new GridLayout(3,3));
pane.setVisible(true);
}
public void makeButton(String buttonName)
{
button = new JButton(buttonName);
}
public void makeText(String addText)
{
text = new JLabel(addText);
}
public void makeTextField(String addText)
{
field = new JTextField(addText);
}
}
This is the particular bit that is giving me trouble
button.addActionListener(new WithdrawListener());
I saw somewhere else that it had to be instantiated in a certain way.
I tried something like:
ATMGUI a = new ATMGUI();
ATMGUI.WithdrawListener w = a.new WithdrawListener();
and then put w in for the argument, but that didn't really work for me either.
Not sure if it is because I'm working in a subclass. Also not really sure if things need to be done differently because I'm working with an interface.
Place the WithdrawListener outside of the constructor context
public class ATMGUI extends GUI {
public ATMGUI() {
//...
button.addActionListener(new WithdrawListener());
//...
}
class WithdrawListener implements ActionListener {
public void actionPerformed(ActionEvent click) {
System.out.println("This is a test.");
}
}
Add listener to button after local class declaration.
public void abc(){
PQR pqr = new PQR(); // incorrect
class PQR {
}
}
Correct way is
public void abc(){
class PQR {
}
PQR pqr = new PQR(); //correct
}
It seems like you must declare the local class before you use it. The follwing code snippets I tested:
This one showed no errors:
public void testFunc() {
class Test {
}
Test test = new Test();
}
But this one does:
public void testFunc() {
Test test = new Test();
class Test {
}
}
Edit: Sorry for posting nearly at the same time, next time I will check three times if someone already posted.
Use of anonymous type is recommended when you are not reusing a class.
Have a look at it (frequently used with listeners) - It's a great answer!!
quoted from above link
Using this method makes coding a little bit quicker, as I don't need
to make an extra class that implements ActionListener -- I can just
instantiate an anonymous inner class without actually making a
separate class.
I only use this technique for "quick and dirty" tasks where making an
entire class feels unnecessary. Having multiple anonymous inner
classes that do exactly the same thing should be refactored to an
actual class, be it an inner class or a separate class.
this.makePane();
this.makeButton("Withdraw");
button.addActionListener(new ActionListener() { //starts here
public void actionPerformed(ActionEvent click)
{
System.out.println("This is a test.");
}
});//ends
pane.add(button);
this.makeText("Enter amount to withdraw: ");
pane.add(text);
this.makeTextField("Enter amount here");
pane.add(field);
this.makeFrame();
frame.add(pane);
So, I want to access one class's data member's field from a whole other class through reflection. I have been unable to figure out, how, after I get the data member through reflection, I can change the field's value. I don't really know how to express it better, so I will let the code speak for me.
Here follows the handler class that calls the buttons. Following are the rest of the classes, whose functionality I will explain on the go.
import java.awt.*;
import java.awt.event.*;
public class SimHandler extends Frame{
public myValveButton but0,but1,but2,but3,but4,but5,but6,but7;
public SimHandler(){
super("Liquer Plant Control Panel");
this.setLayout(null);
this.setFont(new Font("Helvetica", Font.PLAIN, 14));
this.setBackground(Color.black);
but0 = new myValveButton("S1a",100,40,this);
but1 = new myValveButton("S1b",100,140,this);
but2 = new myValveButton("S2a",200,40,this);
but3 = new myValveButton("S2b",200,140,this);
but4 = new myValveButton("S3a",100,240,this);
but5 = new myValveButton("S3b",100,340,this);
but6 = new myValveButton("S4a",200,240,this);
but7 = new myValveButton("S4b",200,340,this);
this.setSize(335,410);
this.setLocation(100,100);
this.setVisible(true);
this.toFront();
this.setResizable(false);
this.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
}
This is actually where I try to use reflection to change the value of Silo's instance state. Below this one follow LiqPlantSim and Silo classes. As you can see, the state variable cannot be resolved that way, and after quite some googling, I can't figure out how I can make it work.
import java.awt.Button;
import java.awt.Frame;
import java.awt.event.*;
import java.lang.reflect.Field;
public class myValveButton extends Button{
String label;
public myValveButton(String label,int x,int y,Frame f){
super(label);
this.label = label;
this.addActionListener(new myValveButtonHandler(label));
f.add(this);
this.setBounds(x, y, 35, 30);
}
}
class myValveButtonHandler implements ActionListener{
Field f;
String label;
public myValveButtonHandler(String label){
this.label = label;
}
public void actionPerformed(ActionEvent pushButton){
try {
f = LiqPlantSim.class.getDeclaredField("silo"+label.split("")[1]);
System.out.println(f);
//f.state = "full" //Eclipse says 'state cannot be resolved to a type or is not a field'
} catch (NoSuchFieldException e) {
} catch (SecurityException e) {
}
System.out.println(label.split("")[2]);
}
}
Here is the LiqPlantSim class.
import java.util.HashMap;
import java.util.Map;
public class LiqPlantSim{
public Silo silo1,silo2,silo3,silo4;
public Pipe pipe;
public LiqPlantSim(){
silo1 = new Silo(false,false);
silo2 = new Silo(false,true);
silo3 = new Silo(true,false);
silo4 = new Silo(true,true);
pipe = new Pipe();
}
}
Here is the Silo Class.
public class Silo {
public boolean mixer,resistance;
public String state,mixerState,resState;
public Silo(boolean mix,boolean res){
mixer = mix;
resistance = res;
state = "empty";
}
}
Apart from finding out how I can access the silo's state variables, I would really appreciate any feedback and/or advice on how I could structure my work better, and on any mistakes I might have made.
First off, Class#getDeclaredField(String) returns a Field object, not the actual value of that field. To get the value, you must use Field#get(Object), where the argument is an instance of the class for which you are trying to access a field. In your code, this would be:
LiqPlantSim sim = doSomethingToGetInstance();
f = LiqPlantSim.class.getDeclaredField("siloX");
Silo silo = (Silo) f.get(sim);
Which brings me to my next point: Why use reflection at all? Your answer probably has to do with getting the correct Silo using the label. You should* restructure LiqPlantSim to use an array or a List to solve this:
import java.util.HashMap;
import java.util.Map;
import java.util.List;
import java.util.ArrayList;
public class LiqPlantSim{
private List<Silo> silos;
public Pipe pipe;
public LiqPlantSim(){
silos = new ArrayList<>();
silos.add(new Silo(false,false));
silos.add(new Silo(false,true));
silos.add(new Silo(true,false));
silos.add(new Silo(true,true));
pipe = new Pipe();
}
public Silo getSilo(int index) {
return silos.get(index);
}
//Possibly other methods to access silos
}
(EDIT: You should do the same with the buttons in SimHandler)
Then, in the handler, you can access a Silo like this:
public void actionPerformed(ActionEvent pushButton){
try {
int labelLength = label.length();
int index = Integer.parseInt(label.substring(labelLength - 1, labelLength));
Silo silo = doSomethingToGetLiqPlantSimInstance().getSilo(index);
silo.state = "full" //Note that it is good practice to use private fields and public getters and setters
} catch (NoSuchFieldException e) {
} catch (SecurityException e) {
}
System.out.println(label.split("")[2]);
}
Better yet, get the index in the constructor and store it so you don't have to recalculate it every time.
*Of course, this is only a suggestion
Why do you implement your action-listeners in the button class? The ValveButton should not be aware of what to do when it is clicked.
Instead you should implement your action-listener in your SimHandler class. After instantiating your 8 ValveButtons you can add the action-listeners in a loop.
Anyways - if you really need to go for a solution using reflection I would recomment using the tiny PrivilegedAccessor framework. Though recommended to be used only in unit-tests it might be useful in your case.
This: "silo"+label.split("")[1] will create the String siloS.
To get the number from the label variable try: label.substring(1,2)
Also you don't need to pass the Frame f to the myValveButton constructor, you can add the buttons to the frame directly in the SimHandler using this.add(but0).
Whatever I try to modify there's always a problem and the program won't run.
The thing is that my program works fine, when it's launched in the console, everything is ok, but when I try to make a GUI, and get text from console in the window, variables doesn't seem to work as they were.
The program is very simple, it has three packages like this:
//class SklepZoologiczny in package sklepzoologiczny
package sklepzoologiczny;
import javax.swing.JFrame;
import zwierzeta.*;
import magazyn.*;
public class SklepZoologiczny {
public static void main(String[] args) {
GUI GUI = new GUI();
GUI.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
GUI.pack();
GUI.setSize(300, 500);
GUI.setVisible(true);
GUI.setTitle("Appka Zaliczeniowa - Sklep Zoologiczny");
GUI.setResizable(false);
GUI.setLocationRelativeTo(null);
}
}
//class GUI in package sklepzoologiczny
package sklepzoologiczny;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import magazyn.*;
import zwierzeta.*;
public class GUI extends JFrame {
public JLabel l_imie, l_gatunek, l_rasa;
public JButton b_dodaj, b_usun, b_lista;
public JTextField tf_imie, tf_gatunek, tf_rasa;
public String imie, gatunek, rasa;
public ArrayList lista_psow, lista_kotow;
public String pies, kot, gatunek_zwierza;
public String imie_psa, rasa_psa;
public String imie_kota, rasa_kota;
public GUI() {
setLayout(new FlowLayout());
b_dodaj = new JButton("Uruchom Program");
add(b_dodaj);
l_imie = new JLabel("Text from console to GUI should go here");
add(l_imie);
event dodanie = new event();
b_dodaj.addActionListener(dodanie);
}
public class event implements ActionListener {
public void actionPerformed(ActionEvent dodanie) {
magazyn magazyn1 = new magazyn();
magazyn1.kasa = 0;
pies pies1 = new pies();
kot kot1 = new kot();
krolik krolik1 = new krolik();
pies1.ustawImie("Max");
kot1.ustawImie("Nuta");
krolik1.ustawImie("Filip");
pies1.ustawCene(200);
kot1.ustawCene(100);
krolik1.ustawCene(50);
pies1.ustawRase("Jamnik");
kot1.ustawRase("Perski");
krolik1.ustawRase("Mini_Lop");
pies1.ustawGatunek("pies");
kot1.ustawGatunek("kot");
krolik1.ustawGatunek("krolik");
System.out.println("Operacje Zakupu Zwierzat");
System.out.println("---");
magazyn1.dodajZwierza(pies1);
magazyn1.dodajZwierza(kot1);
magazyn1.dodajZwierza(krolik1);
magazyn1.StanSklepu();
System.out.println("Transkacje");
System.out.println("---");
magazyn1.sprzedajZwierza("Nuta");
magazyn1.StanSklepu();
}
}
}
//class magazyn in package magazyn
package magazyn;
import java.util.ArrayList;
import zwierzeta.*;
public class magazyn {
public float kasa;
ArrayList <zwierzeta> lista = new ArrayList(20);
public void dodajZwierza(zwierzeta i){
lista.add(i);
sklepzoologiczny.GUI.l_rasa.setText("Do sklepu dodano zwierza o imieniu: " + i.wezImie());
}
public void sprzedajZwierza(String i){
for(int j=0; j<lista.size(); j++){
if(lista.get(j).wezImie() == i){
kasa = kasa + lista.get(j).wezCene();
lista.remove(j);
System.out.println("Sprzedano: " + i);
}
}
}
public void StanSklepu(){
System.out.println("Aktualny stan sklepu:");
for(int i=0; i<lista.size(); i++){
System.out.println(lista.get(i).wezImie()+", " +lista.get(i).wezGatunek()+", " + lista.get(i).wezRase() + ", cena: " + lista.get(i).wezCene());
}
System.out.println("Stan kasy \t\t\t" + kasa);
}
}
//class zwierzeta in package zwierzeta
package zwierzeta;
public abstract class zwierzeta {
String imie, gatunek, rasa;
float cena;
/* public void checkProduct() throws ProductException{
if(isDamaged == true){
ProductException damaged = new ProductException();
damaged.setErrorMessage("Product is damaged:");
throw damaged;
}
}*/
public void ustawImie(String i){
imie = i;
}
public String wezImie(){
return imie;
}
public void ustawGatunek(String i){
gatunek = i;
}
public String wezGatunek(){
return gatunek;
}
public void ustawRase(String i){
rasa = i;
}
public String wezRase(){
return rasa;
}
public void ustawCene(float i){
cena = i;
}
public float wezCene(){
return cena;
}
}
There are also three classes in package zwierzeta which only extends zwierzeta with no code in it.
So the thing is, whatever I try to put in the dodajZwierza in magazyn.java, there's always an error which says that I can't use non-static variable l_rasa to reference in a static context. I don't know how to fix this, I tried to make class as static in GUI but it just gets worse with more errors.
How can I get the text to appear in the window instead of a console?
First of all - you better avoid using members with names identical to type names:
GUI GUI = new GUI();
You - and the JVM - are more than likely to get confused by this, not knowing whether you are trying to access the class type or the class instance when you later run something like:
GUI.setVisible(true);
Second, if you want to let one class access a member of another class, it is much better to provide a getter that returns (a reference to ) that member, instead of defining the member as static and let the other classes access it directly.
You seem to conflate classes and instances: you want to create an instance of class GUI and then pass this instance around to be able to use the instance rather than the class.
In your main method, you create an instance of class GUI:
GUI GUI = new GUI();
The variable which refers to this instance you call GUI, the same as the class. This is a very bad idea. Java naming conventions dictate that variable names start with a non-capital letter, so you should write:
GUI gui = new GUI();
and change the rest of the main method accordingly.
Now, this instance gui is what you want to use. You have to pass it to the methods where you use it, and then write for example
gui.l_rasa.setText(...);
By the way, your code becomes more maintainable if you make the member variables of a class private, and add getter and setter methods to access them.
You are trying to access non static variable defined in GUI class as:
public JLabel l_imie, l_gatunek, l_rasa;
Here:
sklepzoologiczny.GUI.l_rasa.setText
I dont see its being initialised, but you could define it as static in GUI class like:
public static JLabel l_rasa;//initialize it may be and that would resolve your issue.
I'm having trouble putting multiple classes into a single file. For example, when my file looks like:
public class FirstClass() {}
public class SecondClass() {}
public class ThirdClass() {}
I get an error during compilation. I'm not quite sure what's causing this. Any ideas?
One Java file can consist of multiple classes with the restriction that only one of them can be public. As soon as you remove public keyword from your classes, you can combine them into a single Java file.
At the risk of spoon-feeding
Please read http://docs.oracle.com/javase/tutorial/java/javaOO/innerclasses.html
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.DecimalFormat;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class TheaterWindow extends JFrame
{
private JPanel pnlAdultTicketPrice, pnlAdultTicketsSold, pnlChildTicketPrice, pnlChildTicketsSold,
pnlCalculate, pnlMain;
private JLabel lblAdultTicketPrice, lblAdultTicketsSold, lblChildTicketPrice, lblChildTicketsSold;
private JTextField txtAdultTicketPrice, txtAdultTicketsSold, txtChildTicketPrice, txtChildTicketsSold;
private JButton btnCalculate;
public TheaterWindow()
{
// Sets window title
setTitle("Theater");
// Sets layout to BorderLayout
setLayout(new GridLayout(5,1));
// Specifies what happens when close button is clicked
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Builds the panels
buildPanels();
// Add the panels to the frame's content pane
add(pnlAdultTicketPrice);
add(pnlChildTicketPrice);
add(pnlAdultTicketsSold);
add(pnlChildTicketsSold);
add(pnlCalculate);
// Size the frame to fit all of the panels
pack();
// Display the window
setVisible(true);
}
private void buildPanels()
{
// Creates labels to display instructions
lblAdultTicketPrice = new JLabel("Adult ticket price");
lblChildTicketPrice = new JLabel("Child ticket price");
lblAdultTicketsSold = new JLabel("Adult tickets sold");
lblChildTicketsSold = new JLabel("Child tickets sold");
// Creates text fields that are 10 characters wide
txtAdultTicketPrice = new JTextField(10);
txtChildTicketPrice = new JTextField(10);
txtAdultTicketsSold = new JTextField(10);
txtChildTicketsSold = new JTextField(10);
// Creates button with caption
btnCalculate = new JButton("Calculate");
// Adds action listener to button
btnCalculate.addActionListener(new CalcButtonListener());
// Creates panels
pnlAdultTicketPrice = new JPanel();
pnlChildTicketPrice = new JPanel();
pnlAdultTicketsSold = new JPanel();
pnlChildTicketsSold = new JPanel();
pnlCalculate = new JPanel();
pnlMain = new JPanel();
// Adds elements to their proper panels
pnlAdultTicketPrice.add(lblAdultTicketPrice);
pnlAdultTicketPrice.add(txtAdultTicketPrice);
pnlChildTicketPrice.add(lblChildTicketPrice);
pnlChildTicketPrice.add(txtChildTicketPrice);
pnlAdultTicketsSold.add(lblAdultTicketsSold);
pnlAdultTicketsSold.add(txtAdultTicketsSold);
pnlChildTicketsSold.add(lblChildTicketsSold);
pnlChildTicketsSold.add(txtChildTicketsSold);
pnlCalculate.add(btnCalculate);
// Adds all of the above panels to a main panel
pnlMain.add(pnlAdultTicketPrice);
pnlMain.add(pnlChildTicketPrice);
pnlMain.add(pnlAdultTicketsSold);
pnlMain.add(pnlChildTicketsSold);
pnlMain.add(pnlCalculate);
}
private class CalcButtonListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
// Creates object of Theater
Theater theater = new Theater();
// Sets the member variables of Theater to the user's input
theater.setAdultTicketPrice(Double.parseDouble(txtAdultTicketPrice.getText()));
theater.setChildTicketPrice(Double.parseDouble(txtChildTicketPrice.getText()));
theater.setAdultTicketsSold(Integer.parseInt(txtAdultTicketsSold.getText()));
theater.setChildTicketsSold(Integer.parseInt(txtChildTicketsSold.getText()));
// Creates DecimalFormat object for rounding
DecimalFormat dollar = new DecimalFormat("#.##");
// Display the charges.
JOptionPane.showMessageDialog(null, "Adult ticket gross: $" +
Double.valueOf(dollar.format(theater.getAdultGross())) + "\n" +
"Child ticket gross: $" + Double.valueOf(dollar.format(theater.getChildGross())) + "\n" +
"Adult ticket net: $" + Double.valueOf(dollar.format(theater.getAdultNet())) + "\n" +
"Child ticket net: $" + Double.valueOf(dollar.format(theater.getChildNet())) + "\n" +
"Total gross: $" + Double.valueOf(dollar.format(theater.getChildGross())) + "\n" +
"Total net: $" + Double.valueOf(dollar.format(theater.getTotalNet())));
}
}
public class Theater
{
private double PERCENTAGE_KEPT = 0.20;
private double adultTicketPrice, childTicketPrice;
private int adultTicketsSold, childTicketsSold;
public double getAdultGross()
{
return getAdultTicketPrice() * getAdultTicketsSold();
}
public double getAdultNet()
{
return PERCENTAGE_KEPT * getAdultGross();
}
public double getAdultTicketPrice()
{
return adultTicketPrice;
}
public int getAdultTicketsSold()
{
return adultTicketsSold;
}
public double getChildGross()
{
return getChildTicketPrice() * getChildTicketsSold();
}
public double getChildNet()
{
return PERCENTAGE_KEPT * getChildGross();
}
public double getChildTicketPrice()
{
return childTicketPrice;
}
public int getChildTicketsSold()
{
return childTicketsSold;
}
public double getTotalGross()
{
return getChildGross() + getAdultGross();
}
public double getTotalNet()
{
return getChildGross() + getChildNet();
}
public void setAdultTicketPrice(double adultTicketPrice)
{
this.adultTicketPrice = adultTicketPrice;
}
public void setAdultTicketsSold(int adultTicketsSold)
{
this.adultTicketsSold = adultTicketsSold;
}
public void setChildTicketPrice(double childTicketPrice)
{
this.childTicketPrice = childTicketPrice;
}
public void setChildTicketsSold(int childTicketsSold)
{
this.childTicketsSold = childTicketsSold;
}
}
}
Yes You can write your all classes in a single .java file, But you must have only one class public(if file name and class name same)
Example:
class A
{
}
class B
{
}
class C
{
}
I am assuming you are very beginner! Just copy paste all these contents in a single file TheaterDemo.java. And dont forget to remove all the public keyword in the beginning of class declaration.
One Java file can contain at most one top-level public class. That public top-level class can contain any number of public nested classes.
You can eliminate your compiler errors by any of the following approaches:
Moving the other classes into their own files. For example: FirstClass.java, SecondClass.java, and ThirdClass.java.
Nesting the classes whose name is not the file basename. For example:
public class FirstClass() {
public class SecondClass() {}
public class ThirdClass() {}
}
Removing the public qualifier from all but the one class whose name is the file basename. This approach has become less common after the introduction of nested classes in Java v1.1. For example, in file FirstClass.java, you could have:
public class FirstClass() {}
class SecondClass() {}
class ThirdClass() {}
From the Java Language Specification, section 7.6: Top Level Type Declarations:
If and only if packages are stored in a file system (§7.2), the host system may choose to enforce the restriction that it is a compile-time error if a type is not found in a file under a name composed of the type name plus an extension (such as .java or .jav) if either of the following is true:
The type is referred to by code in other compilation units of the package in which the type is declared.
The type is declared public (and therefore is potentially accessible from code in other packages).
Just remove public from all other class definition and paste the code into TheaterDemo.java file
public class TheaterDemo
{
public static void main(String[] args)
{
TheaterWindow theaterWindow = new TheaterWindow();
}
}
//Here class code after removing public
// Here another class code
I see you have already done that kind of implementation. Please refer
private class CalcButtonListener implements ActionListener
in your TheaterWindow class.
By doing this, you are creating inner classes i.e. CalcButtonListener is an inner class of TheaterWindow class. Some concept you can extend to other classes.
There is no restriction on the number of class files in a java file.
But we can’t have more than one public class per source code file. Also the name of the file must match the name of the public class. Like, a class declared as public class Dog { } must be in a source code file named Dog.java.
And files with no public classes can have a name that does not match any of the classes in the file.