Repaint on child jpanel - java

Ok say I have a JPanel "controls" and jpanel "graphPanel" within another jpanel
public class outer extends JPanel implements ActionListener{
private JPanel controls,graphPanel;
private JButton doAction
public outer(){
JPanel controls = new JPanel();
JButton doAction = new JButton("Do stuff");
doAction.addActionListener(this);
controls.add(doAction);
JPanel graphPanel = new JPanel();
this.add(controls);
this.add(graphPanel);
}
public void actionPerformed(ActionEvent e) {
if(e.getSource()==doAction){
//How do I fire paintComponent of controls JPanel on this click
}
How do i make "graphPanel" repaint after my button is clicked

The doAction and graphPanel are declared twice - once at the class level, then again in the method:
private JPanel controls,graphPanel; // declared here first
private JButton doAction; // declared here first
public outer(){
JPanel controls = new JPanel(); // Whoops, declared here again
JButton doAction = new JButton("Do stuff"); // Whoops, declared here again
doAction.addActionListener(this);
controls.add(doAction);
JPanel graphPanel = new JPanel(); // Whoops, declared here again
...
In the method remove the declaration, and make them simple assignments, like this:
controls = new JPanel(); // no leading 'JPanel'
Do that and the additional repaint code won't throw a NPE

Related

How to create a new copy of an existing JPanel? [duplicate]

Basically I need to duplicate a JPanel, for example if we do it with Integer variables this should work:
Integer intaux,int1;
int1 = 3;
intaux = int1;
But this doesn't work with panels:
jPanelaux = jPanel1;
Is there any setter method I don't know?
As Kira San already said, you will need an instance for every panel you want to display.
For example:
public class MyPanel extends JPanel {
//creates a JPanel with the text "hello"
public MyPanel() {
super();
this.add(new JLabel("Hello"));
}
}
public class someClass {
public void someMethod() {
MyPanel myPanel = new MyPanel();
//here we add the same instance of MyPanel twice to panel1, which ..
JPanel panel1 = new JPanel();
//...adds myPanel
panel1.add(myPanel);
//...removes myPanel from the container it was added to first and adds it to this container (which is panel1 in both cases)
panel1.add(myPanel);
//here we add two separate instances of MyPanel to panel2, which should both be shown
JPanel panel2 = new JPanel();
panel2.add(new MyPanel());
panel2.add(new MyPanel());
}
}
Make your own JPanel child class that contains all you want.
Something like:
public class MyPanel extends JPanel {
JButton okButton;
JButton cancelButton;
JTextField nameTextField;
public MyPanel() {
okButton = new JButton();
JLabel nameLabel = new JLabel("Name:");
setLayOut(...);
add(okButton);
...
}
}
Either you use a GUI editor, or copy all from your current code.
Then you can use two new MyPanel()s to have identical complex components.
If you only want a duplicate image of the original panel then creating another JPanel that uses the original JPanel to paint could work.
JPanel dup = new JPanel(){
#Override
public void paintComponent(Graphics g){
jPanel1.paintComponent(g);
}
#Override
public Dimension getPreferredSize(){
return jPanel1.getPreferredSize();
}
#Override
public Dimension getMaximumSize(){
return jPanel1.getMaximumSize();
}
#Override
public Dimension getMinimumSize(){
return jPanel1.getMinimumSize();
}
};
This would only create a view of the original panel and none of the components would be functional, eg JButton or JTextField would not receive input.There would also need to be some work done to cause repainting.

Unable to add JComponents using methods to my constructor

I have a problem with this nested class of mine. I can't add my JComponents to my panels for some reason in the constructor. It gives an error of
The method of add(JComponent, String) is undefined for the HomePanel.inputFrame
The HomePanel is the outer class while inputFrame is my inner class. My methods return JComponents and I am able to add it to my outer class but my inner class just doesn't allow it so I decided to just use add.(enterButton(), BorderLayout.SOUTH) which doesn't give any errors but when I try to use this inner class from mainWindow class, it says
The method add(JComponent) in the type container is not applicable for the arguments (HomePanel.inputFrame)
But the problem is I can use the outer class from mainWindow class which makes it confusing as to what went wrong. Is it due to it being an inner class or my order is wrong?
mainWindow class
public class mainWindow extends JFrame{
CardLayout cl = new CardLayout();
private JFrame mainPage = new JFrame("Food Expiry");
private JPanel mainPanel = new JPanel(cl);
private static final String homePage = "HomePage";
private static final String expiryDateEntry = "Expiry Date Entry";
private JPanel card1 = new JPanel();
public JPanel card2 = new JPanel();
HomePanel getGui = new HomePanel();
HomePanel.inputFrame nextPane = getGui.new inputFrame();
CardLayout cardLayout = (CardLayout) mainPanel.getLayout();
public mainWindow(){
mainPage.setSize(500, 300);
mainPage.setLocationRelativeTo(null);
mainPage.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainPage.add(mainPanel);
mainPage.setVisible(true);
}
protected void mainPanel(){
card1.add(getGui);
}
protected void getInput(){
card2.add(nextPane);
}
}
HomePanel
public class HomePanel extends JPanel{
private JButton inputButton, storeButton;
private JLabel label, itemLabel;
private JPanel textAreaPanel, buttonPanel, labelPanel;
private JTextField itemField, itemCategory, expiryDate;
public HomePanel(){
setLayout(new BorderLayout());
this.add(getLabelPanel("Home"), BorderLayout.NORTH);
this.add(getButtonPanel(), BorderLayout.CENTER);
}
protected JComponent getButtonPanel(){
//add some buttons to a buttonPanel
return buttonPanel;
}
protected JComponent getLabelPanel(String topText){
//labelPanel
return labelPanel;
}
class inputFrame {
private JLabel categoryLabel, expiryLabel;
private JButton enter, back;
protected JComponent getInputFrame(){
textAreaPanel = new JPanel();
textAreaPanel.setLayout(new BoxLayout(textAreaPanel,
BoxLayout.Y_AXIS));
itemLabel = new JLabel("Item Name: ");
itemField = new JTextField(15);
textAreaPanel.add(itemLabel);
textAreaPanel.add(itemField);
categoryLabel = new JLabel("Category Name: ");
itemCategory = new JTextField(33);
textAreaPanel.add(categoryLabel);
textAreaPanel.add(itemCategory);
expiryLabel = new JLabel("Expiry Date: ");
expiryDate = new JTextField(33);
textAreaPanel.add(expiryLabel);
textAreaPanel.add(expiryDate);
return textAreaPanel;
}
protected JComponent enterButton(){
buttonPanel = new JPanel();
enter = new JButton("Enter");
back = new JButton("Back");
enter.addActionListener(new getInput());
back.addActionListener(new previousFrame());
buttonPanel.add(back);
buttonPanel.add(enter);
return buttonPanel;
}
public inputFrame(){
setLayout(new BorderLayout());
add(getLabelPanel("Expiry Date Entry"),BorderLayout.NORTH);
add(getInputFrame(), BorderLayout.CENTER);
add(enterButton(), BorderLayout.SOUTH);
}
}
I couldn't find any duplicates on this question and if anyone is able to find any, please do link it in the comments or answer it. Thank you.
So, based on...
public class HomePanel extends JPanel{
//...
class inputFrame {
//...
}
}
inputFrame extends (by default) from Object, making it compatible with Container#add, which expects some class which extends from Component.
Based on the current implementation, inputFrame is actually modifying the state of the instance of HomePanel from which it was instantiated, rather then adding components to itself
Something like...
public class HomePanel extends JPanel{
//...
class inputFrame extends JPanel {
//...
}
}
should alleviate the most pressing issues

How to duplicate a JPanel?

Basically I need to duplicate a JPanel, for example if we do it with Integer variables this should work:
Integer intaux,int1;
int1 = 3;
intaux = int1;
But this doesn't work with panels:
jPanelaux = jPanel1;
Is there any setter method I don't know?
As Kira San already said, you will need an instance for every panel you want to display.
For example:
public class MyPanel extends JPanel {
//creates a JPanel with the text "hello"
public MyPanel() {
super();
this.add(new JLabel("Hello"));
}
}
public class someClass {
public void someMethod() {
MyPanel myPanel = new MyPanel();
//here we add the same instance of MyPanel twice to panel1, which ..
JPanel panel1 = new JPanel();
//...adds myPanel
panel1.add(myPanel);
//...removes myPanel from the container it was added to first and adds it to this container (which is panel1 in both cases)
panel1.add(myPanel);
//here we add two separate instances of MyPanel to panel2, which should both be shown
JPanel panel2 = new JPanel();
panel2.add(new MyPanel());
panel2.add(new MyPanel());
}
}
Make your own JPanel child class that contains all you want.
Something like:
public class MyPanel extends JPanel {
JButton okButton;
JButton cancelButton;
JTextField nameTextField;
public MyPanel() {
okButton = new JButton();
JLabel nameLabel = new JLabel("Name:");
setLayOut(...);
add(okButton);
...
}
}
Either you use a GUI editor, or copy all from your current code.
Then you can use two new MyPanel()s to have identical complex components.
If you only want a duplicate image of the original panel then creating another JPanel that uses the original JPanel to paint could work.
JPanel dup = new JPanel(){
#Override
public void paintComponent(Graphics g){
jPanel1.paintComponent(g);
}
#Override
public Dimension getPreferredSize(){
return jPanel1.getPreferredSize();
}
#Override
public Dimension getMaximumSize(){
return jPanel1.getMaximumSize();
}
#Override
public Dimension getMinimumSize(){
return jPanel1.getMinimumSize();
}
};
This would only create a view of the original panel and none of the components would be functional, eg JButton or JTextField would not receive input.There would also need to be some work done to cause repainting.

gui help... with an actionListener

I'm writing my first GUI program that actually does something and I am having problems with the action listener. The program when complete will take a double input and make conversions from one unit to another based on some radio button selections which i haven't added yet. The problem right now is the Action listener doesn't recognize my text fields.
I have an input text field and an output text fields in separate panels. I created an action listener and I added the input text field to the listener.
ActionListener handler = new HandlerClass();
textField.addActionListener(handler);
then I created an in class definition for the handler class but when I write the action preformed method textField and output cannot be resolved by the program. Can anyone see what I'm doing wrong?
public class conversionDisplay extends JFrame{
/**
*
*/
private static final long serialVersionUID = 1L;
private JPanel northPanel;
private JPanel southPanel;
private JPanel eastPanel;
private JPanel westPanel;
public conversionDisplay() {
super("Temperature Conversion");
northPanel = new JPanel(); //create northPanel
northPanel.setLayout(new GridLayout(1,2,5,5));
northPanel.add(new JPanel());
JPanel northLabelPanel = new JPanel(new BorderLayout()) ;
northLabelPanel.add(new JLabel("Input"), BorderLayout.EAST);
northPanel.add(northLabelPanel);
JTextField textField =new JTextField(10);
northPanel.add(textField);
northPanel.add(new JPanel());
southPanel = new JPanel(); //create southPanel
southPanel.setLayout(new GridLayout(1,2));
southPanel.add(new JPanel());
JPanel southLabelPanel = new JPanel(new BorderLayout());
southLabelPanel.add(new JLabel("Output "), BorderLayout.EAST);
southPanel.add(southLabelPanel);
JTextField output;
southPanel.add(output = new JTextField( 10));
output.setEditable(false);
southPanel.add(new JPanel());
add(northPanel,BorderLayout.NORTH); //add north panel
add(southPanel,BorderLayout.SOUTH); //add north panel
ActionListener handler = new HandlerClass();
textField.addActionListener(handler);
setSize(350, 200);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
private class HandlerClass implements ActionListener{
public void actionPerformed(ActionEvent e) {
double input = textField.getText();
if (input != 0)
{
output.setText(input); //Perform conversion
}
}
}
}
Your textField JTextField is declared inside of a constructor and is thus only visible within that block (again the constructor). You need to make it an instance field of the class.
i.e.,
public class Foo {
private Bar bar = new Bar(); // this field is visible throughout the object
public Foo() {
Baz baz = new Baz(); // this is only visible within this constructor
}
So just like the bar variable above is visible while the baz variable that is declared in the constructor is not, you'll want to move your JTextField variable declarations out of the constructor.
you must parse String to Double value
public void actionPerformed(ActionEvent e) {
double input = Double.parseDouble(textField.getText());
if (input != 0)
{
output.setText(input+""); //Perform conversion
}
}
and declare JTextField output,textField as Globel.
public class conversionDisplay extends JFrame{
/**
*
*/
private static final long serialVersionUID = 1L;
private JPanel northPanel;
private JPanel southPanel;
private JPanel eastPanel;
private JPanel westPanel;
JTextField output = new JTextField(10);
public conversionDisplay() {
super("Temperature Conversion");

NullPointerException for instantiated button in action listener

The following code is a snippet of a program I am getting a nullpointer exception from. When I press the "Add" button on the GUI, an error message pointing to this line:
buttonPanel.addButton.setEnabled(false);
is displayed. I'm guessing that the addButton is null for some reason although I instantiated it in the constructor of buttonPanel:
addButton = new JButton("Add");
addButton.addActionListener(buttonListener);
Why is the null pointer error
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at AddButtonListener.actionPerformed(AddButtonListener.java:21)
appearing? When the listener is coded inside the buttonPanel class, the program runs fine with no errors. Thanks in advance for your help!
import java.awt.GridLayout;
import javax.swing.*;
public class ButtonPanel extends JPanel{
public JButton addButton,
editButton,
deleteButton,
acceptButton,
cancelButton,
exitButton;
public JPanel topPanel,
exitPanel;
private ParentFrame parentFrame;
public static String buttonStatus;
public ButtonPanel(ParentFrame parent){
parentFrame = parent;
buttonStatus = "idle";
//Create Buttons
AddButtonListener buttonListener = new AddButtonListener(parent);
addButton = new JButton("Add");
addButton.addActionListener(buttonListener);
editButton = new JButton("Edit");
deleteButton = new JButton("Delete");
acceptButton = new JButton("Accept");
cancelButton = new JButton("Cancel");
exitButton = new JButton("Exit");
//Manipulate Buttons
acceptButton.setEnabled(false);
cancelButton.setEnabled(false);
//Add to panels
topPanel = new JPanel();
topPanel.add(addButton);
topPanel.add(editButton);
topPanel.add(deleteButton);
topPanel.add(acceptButton);
topPanel.add(cancelButton);
exitPanel = new JPanel();
exitPanel.add(exitButton);
this.setLayout(new GridLayout(2,1));
this.add(topPanel);
this.add(exitPanel);
}
}
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class AddButtonListener implements ActionListener{
private ParentFrame myFrame;
private ButtonPanel buttonPanel;
public AddButtonListener(ParentFrame parent){
myFrame = parent;
buttonPanel = parent.buttonPanel;
}
#Override
public void actionPerformed(ActionEvent ae) {
buttonPanel.buttonStatus = "add";
buttonPanel.addButton.setEnabled(false);
buttonPanel.editButton.setEnabled(false);
buttonPanel.deleteButton.setEnabled(false);
buttonPanel.acceptButton.setEnabled(true);
buttonPanel.cancelButton.setEnabled(true);
}
}
import java.awt.BorderLayout;
import javax.swing.JFrame;
public class ParentFrame extends JFrame{
public ButtonPanel buttonPanel;
public ParentFrame(){
this.setResizable(false);
buttonPanel = new ButtonPanel(this);
this.add(buttonPanel, BorderLayout.SOUTH);
this.pack();
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(400, 300);
}
public static void main(String[] args){
ParentFrame frame = new ParentFrame();
frame.setVisible(true);
}
}
Your buttonpanel requires a reference to ParentFrame to be constructed. ButtonPanel is being constructed in parent frame and creating a listener, which references the parent frame's button panel.
Unfortunately, the button panel hasn't been assigned at that point, and so your action listener has a null value assigned to its instance of button panel.
I think the problem is your button panel instance is null in your AddButtonListener.
You can fix this by passing a ButtonPanel instance into your AddButtonListener constructor. As AddButtonListener isn't using ParentFrame, don't bother passing it at all.
private ButtonPanel buttonPanel;
public AddButtonListener(ButtonPanel panel){
myFrame = parent;
buttonPanel = panel;
}
And then in your button panel constructor:
public ButtonPanel(ParentFrame parent){
parentFrame = parent;
buttonStatus = "idle";
//Create Buttons
AddButtonListener buttonListener = new AddButtonListener(this);
//rest the code
Aside, you shouldn't be structuring things like this. What you're doing is tightly coupling your ButtonPanel with your ParentFrame. This means if your parent frame changes it could cause another change in ButtonPanel, which makes for less maintanable code.
You are adding the new AddButtonListener(parent); before the ButtonPanel(ParentFrame parent) is fully initialized, so all it componets are null.
Do the following
In AddButtonListener
public void actionPerformed(ActionEvent ae) {
// change all references to buttonPanel to myFrame.buttonPanel
myFrame.buttonPanel.buttonStatus = "add";
...
}
This is because while you construct the ButtonPanel, the buttonPanel variable inside ParentFrame you pass around is null at that very moment.
see
public ParentFrame(){
...
// when you initialize this, buttonPanel is null until constructing is complete
buttonPanel = new ButtonPanel(this);
...
}
Therefore AddButtonListener.buttonPanel is null.
you might have delete the initialization code which is:
public yourClass()
{
initComponents();
btn(false);
}

Categories