简体   繁体   English

如何在多个jpanel中使用变量?

[英]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. 我有一个带有var的框架,我将var添加到JPanel,如果我想将相同的var添加到另一个JPanel,它会从第一个JPanel中消失。 I want a logical explanation for my problem please, thank you ! 我想对我的问题进行合理的解释,谢谢! I want to store my JLabel in both of my jpanels. 我想将JLabel存储在我的两个jpanel中。

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. 免责声明:我正在编辑我的回答以回应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. 答:一种可能的解决方案是创建您正在使用的Swing组件的子类。 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. 现在,您可以创建MyPanel多个实例,每个实例都有自己的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: 补充:通过评论中提供的附加信息,我会更进一步,创建一个自定义JFrame类:

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

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

Now you can create several instances of MyFrame . 现在,您可以创建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 . 如果您想更进一步,可以将参数添加到这两个自定义类的构造函数中,以将JLabel文本设置为每个实例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). 所有Swing UI组件(包括JLabel)只能有一个父组件(即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. 例如,JPanel 1可能不使用与JPanel 2相同的布局,因此标签必须支持每个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? 这基本上是在抓你如何为你的程序构建一个合适的Swing架构?

What you don't want to do is use the Swing component model (ie. Jabel, JTextField, etc) as your data model. 您不想做的是使用Swing组件模型(即Jabel,JTextField等)作为您的数据模型。 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. UI组件应仅用于显示。 They reflect what is in the data model. 它们反映了数据模型中的内容。 So you'll want to create a model that doesn't involve Swing. 因此,您需要创建一个不涉及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. 这意味着你不应该假设它总是Swing或web等。

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. 假设您正在从JList切换到JTable或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. 此外,View会显示事物,但模型可能需要未向用户显示但与所显示内容相关的信息。 For example, the ID of the row in the database. 例如,数据库中行的ID。 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. 如果你不知道我的意思,你将在6个月内完成你的第一次重大重新设计,或者你现在可以省去一些痛苦并试着理解我现在的意思。 Just simple POJOs will suffice. 只需简单的POJO即可。 Then share those POJOs with your Swing components. 然后与Swing组件共享这些POJO。 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. 请注意,我创建了两个名为MySpecialPanel和MyOtherSpecialPanel的JPanel子类。 Inside there they create the components contained within them. 在那里,他们创建了包含在其中的组件。 Then then expose a setter method taking a data model object of type MySpecialPOJO. 然后公开一个采用MySpecialPOJO类型的数据模型对象的setter方法。 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. 现在,您可以获取模型对象,并更新构成该视图的相对UI组件。 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. 它只是更新它拥有的控件以反映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. 此外,如果您需要在程序中移动面板,那么如果您将依赖关系减少到仅仅是POJO,则很容易实现。 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!). 您仍然需要弄清楚如何从UI中获取数据并返回到您的POJO(事件!)。 Controllers, Services, etc. 控制器,服务等

This might help you as well: 这也可能对你有所帮助:

Up-to-date Swing MVC example + Question 最新的Swing MVC示例+问题

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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