简体   繁体   中英

how can I use a variable in multiple jpanels?

I have a frame with a var , I added that var to a JPanel, and if I want to add the same var to another JPanel, it`s disappearing from the first JPanel. I want a logical explanation for my problem please, thank you ! I want to store my JLabel in both of my jpanels.

public class Gui {
    JPanel panel1, panel2;
    JLabel text = new JLabel("some text");
    JFrame frame = new JFrame();

    public Gui {
        panel1 = new JPanel();
        panel1.setLayout(null);
        panel1.add(text);
        panel1.getComponent(0).setBounds(50,50,50,50);
        panel1.setBorder(BorderFactory.createLineBorder(Color.black));
        panel1.setBounds(x,y,w,h);
        // it`s working, the labels it`s visible

        panel2 = new JPanel();
        panel2.setLayout(null);
        panel2.add(text);
        panel2.getComponent(0).setBounds(100,100,50,50);
        panel2.setBorder(BorderFactory.createLineBorder(Color.black));
        panel2.setBounds(x,y,w,h);
        //it`s not working, the label ins`t visible ...

        frame.add(panel1);
        frame.add(panel2);
    }
}

Disclaimer: I am editing my answer in response to comments from the OP. However, I am still not entirely sure about some of the details of the question. I will gladly edit my answer as more clarifications are given.

Answer: One possible solution is to create subclasses of the Swing components you are using. For example,

public class MyPanel extends JPanel {
  private JLabel label = new JLabel("some text");

  public MyPanel() {
    this.add(label);
  }
}

Now you can create multiple instances of MyPanel which each have its own JLabel. Then you can add these panels to your frame.

Added: With the additional information given in the comments, I would go a step further and create a custom JFrame class:

public class MyFrame extends JFrame {
  private MyPanel panel = new MyPanel();

  public MyFrame() {
    this.add(panel);
  }
}

Now you can create several instances of MyFrame . If you want to go even further, you can add parameters to the constructors of both of these custom classes to set the JLabel text to different values in each instance MyFrame . I will leave the details as an exercise to the reader. (Of course, please ask if you get stuck, though.)

Just as it's discussed with in other posts. All Swing UI components (ie JLabel included) can only have one parent (ie JPanel). If you add it to another panel it will remove itself from the prior parent. There are very good reasons for this behavior. For example, JPanel 1 might not use the same Layout as JPanel 2 and hence the label would have to support two different placements within each JPanel. The whole point of using Objects as components is to provide encapsulation of data like (font, position within the parent, width, height, etc) inside that object. If you want two visual elements just create another element. Now that creates a problem "How do you synchronize the data across all of these controls?" That's basically scratching how do you build a proper Swing architecture for your program?

What you don't want to do is use the Swing component model (ie. Jabel, JTextField, etc) as your data model. And after reading your question and code I believe that's what you are doing. You may not realize it. UI Components should be used for display only. They reflect what is in the data model. So you'll want to create a model that doesn't involve Swing. It should model your problem regardless of how its displayed. That means you shouldn't assume it will always be Swing or web, etc.

There are very practical reasons for this. Say in a year you want to redesign your UI. If you combined the view components and data model together you pretty much have to start completely over. Even if you aren't switching technologies. Say you are switching from a JList to a JTable or a JTreeTable. Just simple changes of the types of components you have on the screen can be an absolute nightmare if you don't segment your view from the model. Plus the View displays thing, but the model might need information that isn't displayed to the user but is tied to what is being displayed. For example, the ID of the row in the database. If you stuff the view and data model together you have to play little hacks to store this invisible information in weird ways. Things that make it hard for other people to understand.

If you don't know what I mean you either will in 6 months when you have to make your first major redesign or you'll save yourself some pain now and try and understand what I mean now. Just simple POJOs will suffice. Then share those POJOs with your Swing components. For example:

MySpecialPanel panel1 = new MySpecialPanel();
MyOtherSPecialPanel panel2 = new MyOtherSpecialPanel();
frame.add( panel1 );
frame.add( panel2 );

...a little while later...

MySpecialPOJO specialPOJO = ...some call to a service...;
panel1.setSpecialPOJO( specialPOJO );
panel2.setSpecialPOJO( specialPOJO );

Notice that I created two subclasses of JPanel called MySpecialPanel and MyOtherSpecialPanel. Inside there they create the components contained within them. Then then expose a setter method taking a data model object of type MySpecialPOJO. Inside those methods we might see something like the following:

public void setSpecialPOJO( MySpecialPOJO specialPOJO ) {
   this.model = specialPOJO;
   textField1.setText( specialPOJO.getName() );
   textField2.setText( specialPOJO.getDescription() );
   radioButtonGroup.setSelected( specialPOJO.getGender() );
   ....
}

Now you have a way to take a model object, and update the relative UI components that make up that view. Notice it doesn't care about any other external dependencies (ie where it got the object from). It just updates the controls it owns to reflect what's carried by the POJO. Now if you follow these simple rules it makes instantiating your special panels easy. Whether you need only one instance or many instances. Also if you need to move panels within your program it's pretty easy to do that if you reduce your dependencies to just your POJOs. There's a lot more to this, but for now this will get you started. You still have to figure out how to get data out of the UI and back into your POJOs (events!). Controllers, Services, etc.

This might help you as well:

Up-to-date Swing MVC example + Question

You can't. As you noticed, a control can only be attached to one window at a time, and if you try to attach it to another one, it will remove itself from the first.

Suggestions:

panel2.add(text.clone()); // clone the existing label
panel2.add(new JLabel("some text")); // make a new label from scratch

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM