Inheriting classes in JButton - java

Hi guyz i have a prob in writing java code for my project as am unable to tackle that, i want my "Categories" button to perform action like it should show bread class in it but am unable to inherit it and put a pic on it so can anyone here just tell me whats the problem in it..
here is the code:
JButton b1 = new JButton("Categories");
b1.setSize(120,25);
b1.setLocation(130,650);
b1.setBackground(Color.LIGHT_GRAY) ;
b1.addActionListener(new AL());
f.add(b1);
public class AL implements ActionListener{
public void actionPerformed(ActionEvent ae){
JFrame f3 = new JFrame("Delicious Bakery");
f3.setVisible(true);
f3.setSize(400,200);
f3.add(Bread);
Now here is the Bread class:
public class Bread extends AL implements ActionListener
{
Bread()
{
ImageIcon BreadImage = new ImageIcon("C:\\Users\\Baba\\Downloads\\Documents\\Bread1.jpg");
JButton Bread = new JButton("Bread",BreadImage);
Bread.setSize(128,96);
}}

You appear to be making several basic mistakes including what looks to be trying to add a class that implements ActionListener to your GUI as if it were a button, but it's not. This suggests that you'd greatly benefit from first reading through the JButton Tutorial and the ActionListener Tutorial.
Note that if this were my project, I'd use AbstractActions a concept that is sort of like an "ActionListener on steroids". You would set your JButton with this Action and in doing so, gain the button its name text, its icon and its ActionListener behavior.
Some notes on your code:
JButton b1 = new JButton("Categories"); // (1)
b1.setSize(120,25); // (2)
b1.setLocation(130,650); // (3)
b1.setBackground(Color.LIGHT_GRAY) ;
b1.addActionListener(new AL()); // (4)
f.add(b1); // (5)
You here create a JButton with a String name text
Here you try to set absolute size, something that we don't recommend as doing this, and using null layouts leads to rigid hard to improve and debug programs
Same for setting locations
You appear to be adding an ActionListener OK
And then add your button to a container (the JFrame perhaps)?
public class AL implements ActionListener{ // (6)
public void actionPerformed(ActionEvent ae){
JFrame f3 = new JFrame("Delicious Bakery"); // (7)
f3.setVisible(true); // (8)
f3.setSize(400,200); // (9)
f3.add(Bread); // (10)
OK, so the AL class implements ActionListener and has an actionPerformed method, so far so good
OK, so inside it you create a new JFrame, a bit unusual since most GUI's have only one JFrame
You're calling setVisible(true) on the JFrame before adding components -- not code, since this may sometimes not allow the JFrame to fully render components added after this setVisible was called
Same notes as previous about setting sizes
Now you add Bread to the JFrame. But Bread looks to not be a component but rather only an ActionListener. This line should not compile.
public class Bread extends AL implements ActionListener { // (11)
Bread() {
// (12)
ImageIcon BreadImage = new ImageIcon("C:\\Users\\Baba\\Downloads\\Documents\\Bread1.jpg");
JButton Bread = new JButton("Bread",BreadImage); // (13)
Bread.setSize(128,96); // (14)
}
}
Your Bread class extends AL but also implements ActionListener which is redundant since AL already implements ActionListener.
You are creating an image icon using a file and an absolute path, a slight no-no. Better to use resources and absolute paths
OK you create a new JButton, but you give it the same name as the non-JButton class -- very confusing. Simply don't do this. Ever. Name your fields with unique names, and obey Java naming issues.
Same issue regarding setting sizes.
For example:
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;
public class TestBread extends JPanel {
// String to url for bread image
private static final String BREAD_IMG_PATH = "http://findicons.com/files/icons/339/"
+ "coffee_break/128/sliced_bread.png";
// preferred size of jpanel
private static final int PREF_W = 400;
private static final int PREF_H = 300;
private BreadAction breadAction; // our abstract action
private JButton breadButton; // our jbutton
public TestBread() {
Icon breadIcon = null;
try {
// get image and put into Icon
URL breadUrl = new URL(BREAD_IMG_PATH);
BufferedImage breadImg = ImageIO.read(breadUrl);
breadIcon = new ImageIcon(breadImg);
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
breadAction = new BreadAction("Bread", KeyEvent.VK_B, breadIcon); // create Action
breadButton = new JButton(breadAction); // create button with Action
breadButton.setVerticalTextPosition(AbstractButton.BOTTOM); // position text
breadButton.setHorizontalTextPosition(SwingConstants.CENTER);
add(breadButton);
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private static void createAndShowGui() {
TestBread mainPanel = new TestBread();
JFrame frame = new JFrame("TestBread");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
Our AbstractAction or "super" ActionListener
#SuppressWarnings("serial")
class BreadAction extends AbstractAction {
public BreadAction(String name, int mnemonic, Icon icon) {
super(name);
putValue(MNEMONIC_KEY, mnemonic);
putValue(LARGE_ICON_KEY, icon);
}
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("bread pressed");
}
}

Related

Can I change an unique MouseListener methods with several JButton in JAVA?

Goal
What I want to do is to set a MouseListener on a Panel when click on a Button1.
Then I want to click on another Button that changes the MouseListener code to do something else.
Example of application
Click on JButton1 -> add MouseListener that change a JLabel background color to red.
Click on JButton2 -> DOESNT ADD a new MouseListener, but change the first one to set the JLabel text to "hello world"
What I can't do
I don't know how to modify an UNIQUE MouseListener.
What I tried
I tried to set an jButton.actionPerformed( new jLabel1.addMouseListener()) for each button, but they create two instance of MouseListener.
I don't want to set one MouseListener for several JButtons, but several JButton changing the status of my MouseListener.
Thanks alot :)
Better to give the JLabel a MouseListener from the get-go, but give it boolean if-blocks that will turn on or off functionality depending on the state of class boolean fields. In your button ActionListeners, simply change the state of these boolean fields. For example in the code below, the boolean flag labelListenerOn is toggled on or off in the first JButton's ActionListener. The JLabel's MouseListener checks the state of this variable and changes the labels background color if the flag is true only. Similarly for the other boolean flag and other ActionListener:
import java.awt.Color;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.*;
public class ButtonListener extends JPanel {
private static final String TURN_ON_MOUSE = "Turn On Mouse";
private static final String TURN_OFF_MOUSE = "Turn Off Mouse";
private JButton button1 = new JButton(TURN_ON_MOUSE);
private JButton button2 = new JButton("Button 2");
private JLabel label1 = new JLabel("Label 1");
private MouseListener labelListener = new LabelListener();
private boolean labelListenerOn = false;
private boolean labelChangeText = false;
public ButtonListener() {
label1.setOpaque(true);
label1.addMouseListener(labelListener);
button1.addActionListener(e -> {
if (labelListenerOn) {
labelListenerOn = false;
((JButton) e.getSource()).setText(TURN_ON_MOUSE);
} else {
labelListenerOn = true;
((JButton) e.getSource()).setText(TURN_OFF_MOUSE);
}
});
button2.addActionListener(e -> {
labelChangeText = true;
});
add(button1);
add(button2);
add(label1);
}
private class LabelListener extends MouseAdapter {
#Override
public void mousePressed(MouseEvent e) {
Color labelColor = label1.getBackground();
if (labelListenerOn) {
if (labelColor.equals(Color.RED)) {
label1.setBackground(null);
} else {
label1.setBackground(Color.RED);
}
// label1.repaint(); // per Rob Camick's comment, this is not necessary
}
if (labelChangeText) {
label1.setText("Hello World");
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
private static void createAndShowGui() {
ButtonListener mainPanel = new ButtonListener();
JFrame frame = new JFrame("ButtonListener");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
}
If you want to get fancy, look up M-V-C for "model-view-controller", where you separate the program logic (here the state of the boolean flags) from the program view code (the Swing GUI code), usually in their own classes, and then use a master class to hook all the components up. This would add an additional layer of indirection and complexity, and would be over-kill in this situation, but in large programs, and especially in programs that are likely going to be updated, changed and grown, this will actually reduce complexity in the long run, and make the program much more "scalable" -- easier to grow and modify. Again, I do not recommend that you do this here, but do look it over for possible future use.

Java Swing and ActionListeners

I am still new to using Swing and creating GUIs in Java. I was working on a simple test code where the color of a button changes to a random color when it is pressed. Although it works, every time I press the button, it minimizes the previous window and opens a new one and they keep piling up. How will I make it so that this does not happen? Does this occur because I am creating an object in the actionPerformed method? The reason why I have made an object there is to link the Swing class with the separate Action class I have made in order to manipulate the button variable.
Therefore, my two questions are:
How can I prevent multiple windows from appearing and instead have them replace each other?
Is there a way to utilize ActionListener within the same class and would it make things easier?
Any help is greatly appreciated!
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Random;
import javax.swing.*;
public class Swing extends JFrame{
private JFrame f;
private JLabel l;
private JButton b;
private JPanel p;
public Swing(){
test();
}
//*
public JFrame getJFrame(){
return f;
}
public JLabel getJLabel(){
return l;
}
public JButton getJButton(){
return b;
}
public JPanel getJPanel(){
return p;
}
//*
public void test(){
// Frame Setup
f = new JFrame("Frame");
f.setVisible(true);
f.setSize(500, 500);
f.setResizable(true);
f.setDefaultCloseOperation(EXIT_ON_CLOSE);
//
// Panel Setup
p = new JPanel();
p.setVisible(true);
//
// Other
b = new JButton("Button");
l = new JLabel("Label");
b.addActionListener(new Action());
//
// Additions
p.add(b);
p.add(l);
f.add(p); // ***
//
}
public static void main(String[] args){
Swing swing = new Swing();
swing.test();
}
}
final class Action implements ActionListener{
public void actionPerformed(ActionEvent e){
Swing swingObject = new Swing(); //
JButton button = swingObject.getJButton(); //
button.setBackground(randomColor());
}
public Color randomColor(){
Random rn = new Random();
ArrayList<Color> color = new ArrayList<Color>();
color.add(Color.BLUE);
color.add(Color.GREEN);
color.add(Color.RED);
color.add(Color.YELLOW);
color.add(Color.PINK);
color.add(Color.CYAN);
color.add(Color.ORANGE);
color.add(Color.MAGENTA);
int s = color.size();
int random = rn.nextInt(s);
return color.get(random);
}
}
From your listener, you're executing
Swing swingObject = new Swing();
This does what it should do: create a new Swing JFrame. You don't want a new JFrame, so don't call its constructor. From the listener, simply get the button that fired the event, and change its color:
JButton button = (JButton) e.getSource();
button.setBackground(randomColor());
You could also pass the button to modify when creating the listener:
class Action implements ActionListener{
private JButton buttonToUpdate;
public Action(JButton buttonToUpdate) {
this.buttonToUpdate = buttonToUpdate;
}
public void actionPerformed(ActionEvent e){
buttonToUpdate.setBackground(randomColor());
}
}
And, to create it:
b = new JButton("Button");
b.addActionListener(new Action(b));

Java Applet: Basic Drum Set

I am trying to program an applet that has four buttons, all of which play a short audio file. The goal is to try and have the user successfully click the buttons any number of times, therefore creating a beat. Here is my attempt:
import java.awt.*;
import java.applet.*;
import java.awt.event.*;
import javax.swing.*;
public class drumKit extends JApplet
{
private JButton snareButton;
private JButton hiHatButton;
private JButton bassButton;
private JButton cymbalsButton;
private AudioClip snare;
private AudioClip hiHat;
private AudioClip bass;
private AudioClip cymbals;
public void init()
{
setLayout (new FlowLayout());
sampleButtons();
snare = getAudioClip(getDocumentBase(), "Snare.wav");
hiHat = getAudioClip(getDocumentBase(), "HiHat.wav");
bass = getAudioClip(getDocumentBase(), "Kick.wav");
cymbals = getAudioClip(getDocumentBase(), "Crash.wav");
}
private void sampleButtons()
{
snareButton = new JButton("Snare");
hiHatButton = new JButton("Hi Hat");
bassButton = new JButton("Kick");
cymbalsButton = new JButton("Cymbals");
snareButton.addActionListener(new ButtonListener());
hiHatButton.addActionListener(new ButtonListener());
bassButton.addActionListener(new ButtonListener());
cymbalsButton.addActionListener(new ButtonListener());
add(snareButton);
add(hiHatButton);
add(bassButton);
add(cymbalsButton);
}
private class ButtonListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
if (e.getSource() == snareButton)
snare.play();
if (e.getSource() == hiHatButton)
hiHat.play();
if (e.getSource() == bassButton)
bass.play();
if (e.getSource() == cymbalsButton)
cymbals.play();
}
}
}
The problem is, when I click the buttons, nothing plays. I referred to the solutions listed here, a window pops up preventing any further interactions with the applet. Sorry, a bit of a newbie here.
//Thanks for your help.
When you say "applet or GUI" I think you really mean applet or application--they are both GUIs. I'm not really familiar with AudioClip, but if it works as easy as it seems, then all you need to do is change your JApplet to a JPanel, then create a main method which creates a JFrame and set its content pane to your JPanel:
disclaimer: This code has not been tested and probably contains complilation errors (I will correct anything pointed out).
import java.awt.*;
import java.applet.*;
import java.awt.event.*;
import javax.swing.*;
public class drumKit extends JPanel implements ActionListener
{
private final JButton snareButton;
private final JButton hiHatButton;
private final JButton bassButton;
private final JButton cymbalsButton;
private final AudioClip snare;
private final AudioClip hiHat;
private final AudioClip bass;
private final AudioClip cymbals;
public drumKit()
{
super();
// create buttons
snareButton = new JButton("Snare");
hiHatButton = new JButton("Hi Hat");
bassButton = new JButton("Kick");
cymbalsButton = new JButton("Cymbals");
// setup audio clips
snare = getAudioClip(getDocumentBase(), "Snare.wav");
hiHat = getAudioClip(getDocumentBase(), "HiHat.wav");
bass = getAudioClip(getDocumentBase(), "Kick.wav");
cymbals = getAudioClip(getDocumentBase(), "Crash.wav");
// set layout
setLayout (new FlowLayout());
// add this action listener to the buttons and add to this panel
sampleButtons();
}
private void sampleButtons()
{
// add this as the each button's action listener
snareButton.addActionListener(this);
hiHatButton.addActionListener(this);
bassButton.addActionListener(this);
cymbalsButton.addActionListener(this);
// add each button to this panel
this.add(snareButton);
this.add(hiHatButton);
this.add(bassButton);
this.add(cymbalsButton);
}
public void actionPerformed(ActionEvent e)
{
if (e.getSource() == snareButton)
snare.play();
else if (e.getSource() == hiHatButton)
hiHat.play();
else if (e.getSource() == bassButton)
bass.play();
else if (e.getSource() == cymbalsButton)
cymbals.play();
}
/**
* main method creates a frame which contains this custom panel
* and displays it.
*/
public static void main(String ...args){
// set the look and feel to the system's look and feel
try{
UIManager.setLookAndFeel(
UIManager.getSystemLookAndFeelClassName());
}catch(Exception e){
// if this fails, who cares, the look and feel will be Java's
// just continue
}
// create frame and make sure that when you close the frame the
// program exits!
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// create your panel, set it to the frame's content pane,
// then show the frame
final JPanel panel = new drumKit();
frame.setContentPane(panel);
frame.setVisible(true);
// resize the frame to be the preferred size of your panel
frame.pack();
}
If you cannot read the files, then I would suggest putting in the fully qualified path name rather than just "Snare.wav" (for example) which looks in the current CLASSPATH directory (which for eclipse, I believe is the project directory).

Passing values between classes

I have a JPanel form which contains a JList and some JButton.
The JPanel looks like this
When I click the Add List button, a separate JFrame form is displayed.
The JFrame form will look like this
When the add button on the JFrame is clicked, I need to add the value of the JTextfield (named List Name) to the JList on the previous JPanel. I wonder how to pass the value from the JFrame to the JPanel? Any suggestion would be appreciated.
Here is a code of the JPanel form (using Designer GUI)
package multimediaproject;
public class musicPlayerPanel extends javax.swing.JPanel {
public musicPlayerPanel() {
initComponents();
}
private void initComponents() {
//...here is the generated code by using designer GUI
}
// Variables declaration - do not modify
//..generated code
// End of variables declaration
}
Here is the code of JFrame form (using Designer GUI)
package multimediaproject;
public class addListFrame extends javax.swing.JFrame {
public addListFrame() {
initComponents();
this.setLocation(515, 0);
setVisible(true);
}
private void initComponents() {
//..here is the generated code by using Designer GUI
}
private void addBtnActionPerformed(java.awt.event.ActionEvent evt){
//some validation
if(...)
{
//validation
}
else
{
//IF VALUE IS CORRECT, ADD the List Name JTextfield value to the JList on the previous JPanel
errorMessage.setText("");
}
}
public static void main(String args[]) {
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new addListFrame().setVisible(true);
}
});
}
// Variables declaration - do not modify
//....generated code
// End of variables declaration
}
UPDATE with your code.
You can take advantage of PropertyChangeListener and PropertyChangeSupport (This classes implements Observer Pattern).
I give you an example you for guidance:
public class MusicPlayerPanel extends JPanel {
private JList list;
private JButton addButton;
private PropertyChangeListener listener = new MyPropertyChangeListener();
//..in some place
addButton.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e){
JFrame form = new FrameForm();
form.addPropertyChangeListener(FrameForm.BUTTON_CLICKED,listener);
form.setVisible(true);
}
});
//in another place
private class MyPropertyChangeListener implements PropertyChangeListener{
#Override
public void propertyChange(PropertyChangeEvent evt){
if(evt == null)
return;
if(evt.getPropertyName().equals(FrameForm.BUTTON_CLICKED)){
String value = (String) evt.getNewValue();
((DefaultListModel)list.getModel()).addElement(value);
}
}
}
}
And the frame form like this:
public class AddListFrame extends JFrame{
private JTextField textfield;
private JButton submitButton;
public static final String BUTTON_CLICKED ="buttonClicked";
// in some place
submitButton.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent evt){
firePropertyChange(BUTTON_CLICKED,null,textfield.getText());
}
});
}
Note: In java by convention, classes start with uppercase and follow a camel style. This is very important for readability.
OK.This is easy if i understand your problem.
Step 1:Create setter and getter for your JList object reference.
Step 2:On button click , when you open new JFrame pass your panel reference in constructor of class which inherits JFrame.
Step 3:By doing this you are able to call getter method on panel reference.
Step 4:Now you have reference of JList,do what you want.
I hope this is best solution of your problem
"when I click the add button, a separate jFrame form is displayed. The jFrame contain a jTextfield and a submit button."
Did you seriously create an entirely new JFrame for a JTextField and a JButton?!
Have you not heard of JOptionPane? That's exactly what you are trying to replicate. The only code you need is this:
String s = JOptionPane.showInputDialog(component, message);
model.addElement(s);
The first line will cover all your code for your custom JFrame.
Take a look at this example
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class JOPDemo extends JPanel {
JList list;
JButton button = new JButton("Add Name");
String name;
DefaultListModel model;
public JOPDemo() {
model = new DefaultListModel();
list = new JList(model);
setLayout(new BorderLayout());
add(list, BorderLayout.CENTER);
add(button, BorderLayout.SOUTH);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
name = JOptionPane.showInputDialog(this, "Enter a name");
model.addElement(name);
}
});
}
public Dimension getPreferredSize() {
return new Dimension(300, 300);
}
private static void createAndShowGui() {
JFrame frame = new JFrame();
frame.add(new JOPDemo());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
Edit
What you can do is have an inner class which is your JFrame. Personally, I'd go with a JDialog though.
From comment: Have your frame as an inner class of your main class. That way it can access all the variables from your main class. You can have a String listName also in the GUI class. From the other frame when you hit add, it sets the listName in GUI class, then adds to the list.
public class GUI {
String listName;
JList list;
InnerFrame inner = new InnerFrame();
private class InnerFrame extends JFrame {
JButton addButton;
}
}

Why isn't my method adding up the values in my other classes? (sscce included)

So I'm very new to java.
This program runs right now. It's an ordering system for food. It uses tabs with grids in each. Each tabs has its own prices.
My problem is when I runs and compiles the program, it runs but the prices don't add up.
Basically, in the GUI class listed below, there's a method that takes the prices from each tab and adds them up....except it's not doing that. It does appear but the "$0.00" isn't changing.
Like I said it compiles, however, when I do press buttons, I can see the compiler comes up with this error:
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
This is the main class:
import javax.swing.JFrame;
public class Pizzamain
{
public static void main (String[] args)
{
JFrame frame = new JFrame ("Pizza Mutt Ordering Service");
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new PizzaMuttPanel());
frame.pack();
frame.setVisible(true);
}
}
This class holds all the GUI. It also adds up the prices in each tab. I commented out the other tabs.
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.text.NumberFormat;
public class PizzaMuttPanel extends JPanel
{
private JLabel totalLabel;
private double total;
public PizzaMuttPanel()
{
setLayout (new BorderLayout());
JLabel name = new JLabel("Pizza Mutt Ordering Service WOOF! WOOF!");
JPanel namePanel = new JPanel();
namePanel.add(name);
add(namePanel, BorderLayout.NORTH);
JTabbedPane mainTabPane = new JTabbedPane();
mainTabPane.add("Pizza", new PizzaPanel());
// mainTabPane.add("Drinks", new DrinksPanel());
// mainTabPane.add("Specials", new SpecialsPanel());
add(mainTabPane, BorderLayout.CENTER);
total = 0.0;
JPanel totalPanel = new JPanel();
totalPanel.add (new JLabel("Your total is:"));
totalLabel = new JLabel("$0.00");
totalPanel.add(totalLabel);
add(totalPanel, BorderLayout.SOUTH);
}
public void addTotal (double intake)
{
total += intake;
NumberFormat dollars = NumberFormat.getCurrencyInstance();
totalLabel.setText(dollars.format(total));
}
}
This an example of one of the tabs. Btw, ALL the tabs follow this logic. As you can see, in the action section, there's something that adds prices each time a button is pressed then relays the data to the GUI class.
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class PizzaPanel extends JPanel
{
private double price;
private final JButton pl;
private final JButton ps;
private final JButton cl;
private final JButton cs;
private final JButton vl;
private final JButton vs;
private PizzaMuttPanel mainPanel;
public PizzaPanel()
{
setLayout (new GridLayout (2, 3));
setBackground (Color.red);
pl = new JButton ("Large Pepperoni: $7");
ps = new JButton ("Small Pepperoni: $4");
cl = new JButton ("Large Cheese: $6.50");
cs = new JButton ("Small Cheese: $3.50");
vl = new JButton ("Large Vegetable: $7");
vs = new JButton ("Small Vegetable: $4");
add (pl);
add (ps);
add (cl);
add (cs);
add (vl);
add (vs);
pl.addActionListener(new ButtonListener());
ps.addActionListener(new ButtonListener());
cl.addActionListener(new ButtonListener());
cs.addActionListener(new ButtonListener());
vl.addActionListener(new ButtonListener());
vs.addActionListener(new ButtonListener());
}
//Here we listen for button presses
private class ButtonListener implements ActionListener
{
public void actionPerformed (ActionEvent e)
{
if (e.getSource().equals(pl))
{
price+=7;
}
if(e.getSource().equals(ps))
{
price+=4;
}
if (e.getSource().equals(cl))
{
price+=6.5;
}
if (e.getSource().equals(cs))
{
price+=3.5;
}
if (e.getSource().equals(vl))
{
price+=7;
}
if (e.getSource().equals(vs))
{
price+=4;
}
//This adds all the prices together.
mainPanel.addTotal(price);
}}}
One way, perhaps over-kill for you, but which is a very useful technique to know and to use is to make the object that holds the information displayed by the JPanel's a "bound property" which allows other classes the ability to listen for and respond to changes in its state.
Specifically:
Give your class that holds the info of interest a SwingPropertyChangeSupport field.
If your class extends JComponent or JPanel (or any class that derives from JComponent), it already has one of these.
Give your class a private count int field
Give this field a public getter and setter method.
In the setter field, call the SwingPropertyChangeSupport's firePropertyChange(String propertyName, int oldValue, int newValue) method with the updated and the old value.
Never change the bound property directly but only through its setter method.
Have any class that wants to listen for changes add a PropertyChangeListener to this class.
If you need a more specific example, consider creating and posting an sscce, and I can show you how to modify it to get this to work.
Edit
Your current code has a problem with references -- you need the sub panels to have a valid reference to the main panel, and you should solve this by passing in a reference.
e.g.
private MainPanel mainPanel;
public SubPanelA(MainPanel mainPanel) {
this.mainPanel = mainPanel;
And then when filling tabs:
mainTabPane.add("A", new SubPanelA(this));
mainTabPane.add("B", new SubPanelB(this));
mainTabPane.add("C", new SubPanelC(this));
This way your tab pane classes can call methods from the main class on a valid reference to the displayed main class.
Edit 2
You state:
I'm a little confused. But I have a reference, right? In the buttonlistener class, first I private PizzaMuttPanel mainPanel; at the top, and then I referenced it as mainPanel.addTotal(price);. Addtotal is in the main GUI class, and holds the prices. Price is the price being taken from the button presses in that specific tab's classes. Are you saying I should change the latter to: mainTabPane.add("A", new SubPanelA(this));
Points:
This: PizzaMuttPanel mainPanel; is not a reference but rather only a declaration of a reference variable. After declaration, it references null, until you give it a valid reference.
You state "and then I referenced it as mainPanel.addTotal(price);", ??? this creates no reference whatsoever, and looks to me will only throw a NPE. To give a variable a reference you must assign the reference to it, meaning you need some statement that begins mainPanel = something goes here.
So what i understand is that you have three different tabs on a jtabbedpane. And every tab is class that extends JPanel. So you want to add an actionlistener to each tab you only have to implement the interface Actionlistener on each panel, or implement on each button.
class tab extends JPanel implements Actionlistener
or if you want a specific actionlistener
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//Action here for the button
}
});
And then you want to get the information from each tab you have to make the variable price public or private. But to access a private variable you have to make getters.
public int price;
or for the private version.
private int price;
public int getPrice(){ return price; }
The last one is the preferred way because you cant change the value of the price outside the class that holds that variable.
And for last you want to get the information from all three tabs you can do like this.
public void prices()
{
Tab1 tab1 = new Tab1();
Tab2 tab2 = new Tab2();
Tab3 tab3 = new Tab3();
System.out.println("tab1: " + tab1.price + " tab2: " + tab2.price + " tab3: " + tab3.price);
// or if you use getters
System.out.println("tab1: " + tab1.getPrice() + " tab2: " + tab2.getPrice() + " tab3: " + tab3.getPrice());
}
So where do you declare it?
class tab extends JPanel implements ActionListener
{
/*
* Declare variables here
*/
private int price;
private JLabel label;
/*
* Methods here
*/
}
EDIT
The problems is see is that you are checking if the button is clicked by its text not the variable. And the other thing is that you are giving a new instance of the button listener every time. Instead of creating a new class called ButtonListener we are just implement the interface ActionListener on the PizzaPanel class.
public class PizzaPanel extends JPanel implements ActionListener{
private JButton b1 = null;
private JButton b2 = null;
private int Price;
public int getPrice() {
return Price;
}
public PizzaPanel() {
b1 = new JButton("B1");
b2 = new JButton("B2");
b1.addActionListener(this);
b2.addActionListener(this);
add(b1);
add(b2);
}
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource().equals(b1)){
Price++;
System.out.println("Button 1 clicked");
}
if(e.getSource().equals(b2))
{
Price--;
System.out.println("Button 2 clicked");
}
}
}

Categories