Unable to add JComponents using methods to my constructor - java

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

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.

JPanel appears as a small white box

I am in the early stages of trying to create a Java 2d graphics paint program. I'm using a flow layout, and I'm using three panels. The first two are rows of buttons, combo boxes, etc. and the third is meant to be a large, blank, white panel that will be used to paint on. The first two panels show up beautifully, but the paint panel appears as a small white box next to the second button panel. Any help would be appreciated.
public class DrawingApp extends JFrame
{
private final topButtonPanel topPanel = new topButtonPanel();
private final bottomButtonPanel bottomPanel = new bottomButtonPanel();
private final PaintPanel paintPanel = new PaintPanel();
public DrawingApp()
{
super("Java 2D Drawings");
setLayout(new FlowLayout());
add(topPanel);
add(bottomPanel);
add(paintPanel);
}
public static void main(String[] args)
{
DrawingApp frame = new DrawingApp();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(750,500);
frame.setVisible(true);
}
}
public class topButtonPanel extends JPanel
{
private final String[] names = {"Line", "Oval", "Rectangle"};
private final JButton undo = new JButton("Undo");
private final JButton clear = new JButton("Clear");
private final JLabel shape = new JLabel("Shape:");
private final JComboBox<String> shapesComboBox = new JComboBox(names);
private final JCheckBox filled = new JCheckBox("Filled");
public topButtonPanel()
{
super();
setLayout(new FlowLayout());
add(undo);
add(clear);
add(shape);
shapesComboBox.setMaximumRowCount(3);
add(shapesComboBox);
add(filled);
}
}
public class bottomButtonPanel extends JPanel
{
private final JCheckBox useGradient = new JCheckBox("Use Gradient");
private final JButton firstColor = new JButton("1st Color");
private final JButton secondColor = new JButton("2nd Color");
private final JLabel lineWidthLabel = new JLabel("Line Width:");
private final JLabel dashLengthLabel = new JLabel("Dash Length:");
private final JTextField lineWidthField = new JTextField(2);
private final JTextField dashLengthField = new JTextField(2);
private final JCheckBox filled = new JCheckBox("Dashed");
public bottomButtonPanel()
{
super();
setLayout(new FlowLayout());
add(useGradient);
add(firstColor);
add(secondColor);
add(lineWidthLabel);
add(lineWidthField);
add(dashLengthLabel);
add(dashLengthField);
add(filled);
}
}
public class PaintPanel extends JPanel
{
public PaintPanel()
{
super();
setBackground(Color.WHITE);
setSize(700,400);
}
}
Basically, it's a misunderstanding of how the Swing API works.
Swing relies (heavily) on the layout management API which is used to make decisions about how large components should be (and where they should be placed)
Using setSize is pointless, as the layout manager will make it's own decisions about what it thinks the size of your component should be and will adjust it accordingly.
You can make suggestions to the layout manager about how large you'd like the component to be using getPreferred/Minimum/MaximumSize, for example
public class PaintPanel extends JPanel
{
public PaintPanel()
{
super();
setBackground(Color.WHITE);
}
public Dimension getPreferredSize() {
return new Dimension(700, 400);
}
}
Just remember, layout managers are well within their right to ignore these values, so you need to have a better understanding of how these managers work
See Laying Out Components Within a Container for more details

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");

Repaint on child jpanel

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

Categories