Reputation: 785
if you have a look at my code below, what im trying to do is modify my addExpense() method to generate a new ExpensePanel and add it to one of my panels (panel 3) and the vector and update the UI on panel 3 and update the stats too.
However after countless modification i can't seem to get it to work. Can anyone lend some insight?
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Panel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Vector;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.UIManager;
class Expenses extends JFrame implements ActionListener{
ExpensesPanel widget;
public String n;
public String d;
public int c;
public int e;
public Expenses(){
// Set Dimension, size, and close operations
setSize(400,400);
setTitle("Expenses");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setResizable(true);
setLocationRelativeTo(null);
// Set the look and feel of the application to that if the OS
try{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch(Exception e){
System.out.print(e);
}
// Add Panel 1, or our main panel
JPanel p1 = new JPanel();
getContentPane().add(p1);
p1.setLayout(new BoxLayout(p1, BoxLayout.Y_AXIS));
// Add our second panel, panel 2 with a grid layout
JPanel p2 = new JPanel();
p2.setLayout(new GridLayout(4,2));
p1.add(p2);
// Add our labels
JLabel label1 = new JLabel("Name: ", JLabel.LEFT);
JTextField name = new JTextField(JTextField.EAST);
n = name.getText();
JLabel label2 = new JLabel("Date: ", JLabel.LEFT);
JTextField date = new JTextField(JTextField.EAST);
d = date.getText();
JLabel label3 = new JLabel("Cost: ", JLabel.LEFT);
JTextField cost = new JTextField(JTextField.EAST);
p2.add(label1);
p2.add(name);
p2.add(label2);
p2.add(date);
p2.add(label3);
p2.add(cost);
// Add our buttons
JButton b1 = new JButton("Add");
p2.add(b1);
JButton b2 = new JButton("Clear");
p2.add(b2);
// Set the preferred size of our windows
p2.setMaximumSize(new Dimension(Integer.MAX_VALUE, p2.getPreferredSize().height));
// Panel 3, this will hold the expenses panel
final JPanel p3 = new JPanel();
p3.setLayout(new BoxLayout(p3, BoxLayout.Y_AXIS));
JScrollPane scroll = new JScrollPane(p3);
p1.add(scroll);
// Panel 4, with a 2x2 Grid
JPanel p4 = new JPanel();
p4.setLayout(new GridLayout(2,2));
p1.add(p4);
// Add labels, and ensure they are not editable
JLabel p4l1 = new JLabel("Total", JLabel.LEFT);
JTextField p4t1 = new JTextField(JTextField.EAST);
p4t1.setEditable(false);
JLabel p4l2 = new JLabel("Average", JLabel.LEFT);
JTextField p4t2 = new JTextField(JTextField.EAST);
p4t2.setEditable(false);
p4.add(p4l1);
p4.add(p4t1);
p4.add(p4l2);
p4.add(p4t2);
// Set the preferred size to fit the rest of the window
p4.setMaximumSize(new Dimension(Integer.MAX_VALUE, p2.getPreferredSize().height));
// Action listeners for both buttons
// Action listner for button 1
b1.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
System.out.println("Button 1 Clicked");
addExpense(p3);
}
});
// Action Listener for button 2
b2.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
System.out.println("Button 2 Clicked");
}
});
}
public void addExpense(JPanel p3){
Vector expenseHolder = new Vector();
ExpensesPanel e = new ExpensesPanel(n, d, 2, 1);
p3.add(e);
expenseHolder.add(p3);
p3.revalidate();
}
@Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
}
public static void main(String[] args){
// Main method
Expenses e = new Expenses();
// Set the application to be visible
e.setVisible(true);
}
}
class ExpensesPanel extends JPanel{
public String n;
public String d;
public int c;
public int e;
public ExpensesPanel(String name, String date, int cost, int expense){
n = name; d = date; c = cost; e = expense;
// Create new Panel and set it on horizontal axis
JPanel exp = new JPanel();
exp.setLayout(new BoxLayout(exp, BoxLayout.X_AXIS));
Box horizontalBox;
// Labels
JLabel newName = new JLabel("Name: ", JLabel.CENTER);
JLabel newDate = new JLabel("Date", JLabel.CENTER);
JLabel newCost = new JLabel("Cost: ", JLabel.CENTER);
JLabel newExp = new JLabel("Expense: ", JLabel.CENTER);
exp.add(newName, Box.createHorizontalGlue());
exp.add(newDate, Box.createHorizontalGlue());
exp.add(newCost, Box.createHorizontalGlue());
exp.add(newExp, Box.createHorizontalGlue());
}
// Override default paint component
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setBackground(Color.BLUE);
}
}
Upvotes: 1
Views: 571
Reputation: 285450
Your problem is that your ExpensePanel class has two JPanels, one you add components to called, exp, and the other, the this
or JPanel that is the object of the class, you add no components to. Well you're adding the second JPanel to your GUI so nothing gets shown. Note also that exp is declared in the constructor and so its scope is limited to the constructor only.
One possible solution: get rid of exp and add everything to this
. Note that you could use the this.
form of expression, such as this.add(someComponent)
which explicitly shows your intention, but it's unnecessary and adds extra words with little benefit in this situation, so I generally avoid it.
i.e., change your constructor to:
public ExpensesPanel(String name, String date, int cost, int expense) {
n = name;
d = date;
c = cost;
e = expense;
// Create new Panel and set it on horizontal axis
// JPanel exp = new JPanel();
setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
Box horizontalBox;
// Labels
JLabel newName = new JLabel("Name: ", JLabel.CENTER);
JLabel newDate = new JLabel("Date", JLabel.CENTER);
JLabel newCost = new JLabel("Cost: ", JLabel.CENTER);
JLabel newExp = new JLabel("Expense: ", JLabel.CENTER);
add(newName, Box.createHorizontalGlue());
add(newDate, Box.createHorizontalGlue());
add(newCost, Box.createHorizontalGlue());
add(newExp, Box.createHorizontalGlue());
}
The other possible solution is to keep the exp JPanel, but promote it to be an instance field with a getter method, and then not have ExpensesPanel extend JPanel. Either would work, and there are some advantages to the latter which should be discussed at a later time (regarding the advantages of using composition over inheritance).
As an aside, this will do nothing:
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setBackground(Color.BLUE);
}
since you never draw or clear (clearRect(...)
actually) with g2d after changing its Color state.
Better and much easier is to call in your constructor:
setBackground(Color.blue);
Problem next, this is wrong:
add(newCost, Box.createHorizontalGlue());
That's not how you add glue. Please check the tutorials and API on this -- you're doing an awful lot of guess work which never works.
Upvotes: 1
Reputation: 8246
As well as @Hovercraft Full Of Eels answer, you should also make changes to GUI components via something like...
EventQueue.invokeLater(new Runnable(){
public void run()
{
//make gui change here
}
});
This updates it from the Event Dispatch Thread (EDT).
Upvotes: 1