How to duplicate a JPanel? - java

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.

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

JPanel displayed empty in Java

I am making a program which displays 3 buttons, and when user clicks on "single player", it activates mouse listener which creates new panel, and is supposed to replace the existing panel with that newly created panel. But all I get after I click "single player" is the new window with white empty background. Here is the code:
public class UserInterface extends JFrame {
private JLabel singlePlayer,multiPlayer,quit;
private Container menu;
public JPanel mainPanel,fieldPanel;
private Field field;
private Snake snake1,snake2;
private Food food;
public UserInterface(){
// Adjust window
mainPanel=new JPanel();
mainPanel.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
mainPanel.setSize(700, 500);
setSize(710, 510);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setResizable(false);
setTitle("Snake");
//add(mainPanel);
setVisible(true);
this.getContentPane().setBackground(Color.ORANGE);
//mainPanel.setBackground(Color.GREEN);
// Instantiate buttons
singlePlayer=new JLabel();
multiPlayer=new JLabel();
quit=new JLabel();
singlePlayer.setIcon(new ImageIcon("files/singleplayer.jpg"));
multiPlayer.setIcon(new ImageIcon("files/multiplayer.jpg"));
quit.setIcon(new ImageIcon("files/quit.jpg"));
quit.addMouseListener(new Mouse());
singlePlayer.addMouseListener(new Mouse());
multiPlayer.addMouseListener(new Mouse());
// Create menu panel
menu=new JPanel(new GridLayout(3,1,0,0));
menu.setBackground(Color.ORANGE);
menu.add(singlePlayer);
menu.add(multiPlayer);
menu.add(quit);
menu.setMaximumSize(new Dimension(164,150));
// Insert menu to the center
mainPanel.add(menu, gbc);
add(mainPanel);
}
public void singlePlayer(){
field=new Field("single player");
snake1=new Snake();
food=new Food();
setVisible(false);
removeAll();
mainPanel=field.getFieldPanel();
add(mainPanel);
//setContentPane(mainPanel);
invalidate();
validate();
setVisible(true);
Thread fieldThread=new Thread(field, "Field thread");
//fieldThread.start();
Thread snake1Thread=new Thread(snake1, "Snake thread");
//snake1Thread.start();
}
private class Mouse implements MouseListener {
#Override
public void mouseClicked(MouseEvent e) {
if(e.getSource()==quit){
System.exit(0);;
} else if(e.getSource()==singlePlayer){
singlePlayer();
} else if(e.getSource()==multiPlayer){
}
}
and here is the field class:
public class Field extends JFrame implements Runnable {
private JPanel fieldPanel;
private JPanel leftPanel;
private JPanel centralPanel;
private JPanel rightPanel;
private String type;
private JLabel leftScore,rightScore;
private int score;
private int foodX,foodY;
private JLabel [][] field;
private final int FIELD_WIDTH=50,FIELD_HEIGHT=50;
private static final long serialVersionUID = 1L;
public JPanel getFieldPanel(){return fieldPanel;}
public Field(String type){
fieldPanel=new JPanel(new GridLayout(1,3,0,0));
fieldPanel.setPreferredSize(new Dimension(700,500));
this.type=type;
// Adjust playground and score tables
leftPanel=new JPanel();
centralPanel=new JPanel();
rightPanel=new JPanel();
leftPanel.setMaximumSize(new Dimension(100,500));
leftPanel.setPreferredSize(new Dimension(100,500));
centralPanel.setMaximumSize(new Dimension(500,500));
centralPanel.setPreferredSize(new Dimension(500,500));
rightPanel.setMaximumSize(new Dimension(100,500));
rightPanel.setPreferredSize(new Dimension(100,500));
// Set leftPanel
score=0;
leftScore=new JLabel("Score:\n"+score);
leftPanel.add(leftScore);
// Adjust field
field=new JLabel[FIELD_WIDTH][FIELD_HEIGHT];
for(int i=0;i<FIELD_WIDTH;i++){
for(int j=0;j<FIELD_HEIGHT;j++){
field[i][j]=new JLabel("");
field[i][j].setSize(new Dimension(10,10));
field[i][j].setOpaque(true);
field[i][j].setBackground(Color.LIGHT_GRAY);
}
}
for(int i=0;i<FIELD_WIDTH;i++){
for(int j=0;j<FIELD_HEIGHT;j++){
if(i==0)
field[i][j].setBackground(Color.BLACK);
else if(j==0)
field[i][j].setBackground(Color.BLACK);
else if(i==FIELD_WIDTH-1)
field[i][j].setBackground(Color.BLACK);
else if(j==FIELD_HEIGHT-1)
field[i][j].setBackground(Color.BLACK);
}
}
// Adjust centralPanel
centralPanel.setLayout(new GridLayout(50,50,0,0));
for(int i=0;i<FIELD_WIDTH;i++){
for(int j=0;j<FIELD_HEIGHT;j++){
centralPanel.add(field[i][j]);
}
}
// Adjust rightPanel
rightPanel.add(new JLabel("Player 2 score: "));
fieldPanel.setLayout(new BoxLayout(fieldPanel,BoxLayout.Y_AXIS));
fieldPanel.add(leftPanel);
fieldPanel.add(centralPanel);
fieldPanel.add(rightPanel);
}
", it activates mouse listener which creates new panel,
It won't solve your problem, but don't use a MouseListener. A JButton is designed to be used with an ActionListener.
after I click "single player" is the new window with white empty background.
When creating a GUI that is designed to share the same space with multiple panels then you should be using a CardLayout to control the visible panel. Read the section from the Swing tutorial on How to Use a CardLayout for more information and examples.
Otherwise if you attempt to mange the swapping of panels manually then the basic code should be:
panel.remove(...);
panel.add(...);
panel.revalidate(); // to invoke the layout manager
panel.repaint(); // to repaint the components

Add component in a JPanel subclass

I want to create a JPanel subclass thats holds some JLabels. I started to write my code but I immediatly find a big problem. Component added to the JPanel subclass are not visible (or they are not added to JPanel I don' t kano). This is the code of the JPanel Subclass:
public class ClientDetails extends JPanel
{
private JLabel nameAndSurname = new JLabel ("Name & Surname");
private JLabel company = new JLabel ("Company");
private JPanel topPanel = new JPanel ();
public ClientDetails ()
{
this.setBackground(Color.white);
this.setLayout(new BorderLayout());
topPanel.setLayout(new BoxLayout(topPanel, BoxLayout.Y_AXIS));
topPanel.add(nameAndSurname);
topPanel.add(company);
this.add(topPanel,BorderLayout.PAGE_START);
}
}
You need to
put the JPanel in a top level container (like a JFrame)
call pack() on it so the LayoutManager finds room for your stuff
.
public class Test extends JPanel {
private JLabel nameAndSurname = new JLabel ("Name & Surname");
private JLabel company = new JLabel ("Company");
private JPanel topPanel = new JPanel ();
JFrame frame;
public Test()
{
this.setBackground(Color.white);
this.setLayout(new BorderLayout());
topPanel.setLayout(new BoxLayout(topPanel, BoxLayout.Y_AXIS));
topPanel.add(nameAndSurname);
topPanel.add(company);
this.add(topPanel,BorderLayout.PAGE_START);
frame = new JFrame("test");
frame.add(this);
frame.pack();
frame.setVisible(true);
}
}

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