简体   繁体   English

如何多次实例化Swing组件的Java类

[英]How to Instantiate Java Class of Swing Components Multiple Times

I have a java class being used as a container, it is coded to have a JPanel and a TabbedPane 我有一个java类用作容器,它被编码为具有JPanelTabbedPane

I have another java class that builds a JPanel containing JLabel s and JTextField s that I want added to the TabbedPane of the container class. 我有另一个Java类,该类构建一个JPanel,其中包含要添加到容器类的TabbedPane的JLabelJTextField I want a new instance of the class that adds the JPanel, so I can add multiple tabs to the container class. 我想要一个添加JPanel的类的新实例,以便可以向容器类添加多个选项卡。

I have reviewed the following: Can we reuse Java Swing application components in other instances of same application? 我已经审查了以下内容: 我们可以在同一应用程序的其他实例中重用Java Swing应用程序组件吗? , Multiple instances of model components in Java Swing? Java Swing中模型组件的多个实例? , Multiple instance of ONE JFrame , and multiple web authors. 一个JFrame的多个实例和多个Web作者。 I am not a student doing an assignment, I am an old dude, new to Java, moving my top-down skills to OOP. 我不是做作业的学生,​​我是Java的新老朋友,将自上而下的技能转移到了OOP。

Here is my code: 这是我的代码:

import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.border.EmptyBorder;

@SuppressWarnings("serial")
public class TestContainer extends JFrame {

private JPanel contentPane;
public static JTabbedPane tabbedPane1;

/**
 * Launch the application.
 */
public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        @Override
        public void run() {
            try {
                TestContainer frame = new TestContainer();
                frame.setVisible(true);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
}

/**
 * Create the frame.
 */
public TestContainer() {

    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setBounds(100, 100, 450, 300);
    contentPane = new JPanel();
    contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
    setContentPane(contentPane);
    contentPane.setLayout(null);

    JScrollPane scrollBasePane = new JScrollPane();
    scrollBasePane.setBounds(10, 11, 414, 239);
    contentPane.add(scrollBasePane);

    JPanel panelBase = new JPanel();
    scrollBasePane.setViewportView(panelBase);
    panelBase.setLayout(null);

    tabbedPane1 = new JTabbedPane(JTabbedPane.TOP);
    tabbedPane1.setBounds(10, 11, 392, 215);
    panelBase.add(tabbedPane1);

    // add new JPanel to TabbedPane via a reusable Class
    MoreTabs mt1 = new MoreTabs();

    tabbedPane1.addTab( mt1() ); //non-static
    }
 }

And

import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;

public class MoreTabs{

private JPanel panel = new JPanel();
private JLabel lblPutStuffOn = new JLabel("Put stuff on this panel, T3-MoreTabs.");
private JTextField text = new JTextField();

panel.add(lblPutStuffOn);
panel.add(text);

public String getLblText() {
    String lblText;
    lblText = lblPutStuffOn.getText();
    return lblText;
}

public void setLblText(String s){
    lblPutStuffOn.setText(s);
}

public String getTxtText() {
    String txtText;
    txtText = text.getText();
    return txtText;
}

public void setTxtText(String s){
    text.setText(s);
  }

}

Do not make the JTabbedPane static. 不要使JTabbedPane静态。 Such JComponentents cannot be shared: they have a single parent Container for instance. 此类JComponentents无法共享:例如,它们具有单个父容器。

One can make a container class, say JMyPanel, and create several instances at several places. 可以创建一个容器类(例如JMyPanel),并在多个位置创建多个实例。

If those instances also should refer to the same data model, say the JTextFields alter the same text, and both instances are accessible at the same time, then in swing one needs change listeners on those text fields. 如果这些实例也应该引用相同的数据模型,比如说JTextFields更改了相同的文本,并且两个实例可以同时访问,则需要在这些文本字段上更改侦听器。

This calls for a Model-View-Controller paradigm. 这需要模型-视图-控制器范例。

One can make one separate controller class containing the data model (texts as String), and let changes to a JTextField (a view) call the controller to update the model and port the updated value to other views. 可以使一个包含数据模型的单独的控制器类(文本为String),然后让对JTextField(视图)的更改调用控制器以更新模型并将更新后的值移植到其他视图。

Use the Document : 使用文件

jTextComponent.getDocument()

You can have two JTextFields having their own Document and use a reciproke notification of true changes. 您可以有两个JTextField具有自己的Document,并使用对真实更改的重新记录通知。 Or as the javadoc of Document suggests use one shared Document. 或正如Document的javadoc建议使用一个共享Document。 The latter I remember using seldom, as in general the data model consists out of more input components. 我记得后者很少使用,因为通常数据模型由更多的输入组件组成。

(BTW. In JavaFX a TextField would be bound to a StringProperty which can be held in the data model, and notifies on changes and can be bound more than once.) (顺便说一句。在JavaFX中,TextField将绑定到StringProperty,该StringProperty可以保存在数据模型中,并通知更改,并且可以多次绑定。)

LuxxMiner is right in his comment.. MoreTabs should extend JPanel Then you can add multiple instances of MoreTabs if that's what you want to do. LuxxMiner在他的评论中是正确的。MoreTabs应该扩展JPanel然后,如果您要这样做,则可以添加MoreTabs的多个实例。

There are a couple of other major issues with your code: 您的代码还有其他几个主要问题:

1) In MoreTabs you have lines: 1)在MoreTab中,您有以下几行:

panel.add(lblPutStuffOn);
panel.add(text);

randomly at the top of your class. 随机排在班级顶部 You can't do this and it will be a compile error. 您不能这样做,这将是编译错误。 You should have a constructor in the MoreTabs class to initialize your variables. 在MoreTabs类中应该有一个构造函数来初始化变量。

Constructor: 构造函数:

public MoreTabs(String labelText){
    lblPutStuffOn = new JLabel(labelText);
    add(lblPutStuffOn);
    add(text);
}

2) These two lines don't make sense: 2)这两行没有意义:

// add new JPanel to TabbedPane via a reusable Class
MoreTabs mt1 = new MoreTabs();

tabbedPane1.addTab( mt1() ); //non-static

It looks like what you are trying to do is instantiate MoreTabs and add as a tab to the tabbed Panel. 看来您要尝试实例化MoreTabs并将其作为选项卡添加到选项卡式面板中。 You cant just call mt1(). 您不能只调用mt1()。 You need to prefix it with 'new' like this: 您需要像这样用“ new”作为前缀:

// add new JPanel to TabbedPane via a reusable Class
MoreTabs mt1 = new MoreTabs("Label 1");
MoreTabs mt2 = new MoreTabs("Label 2");
MoreTabs mt3 = new MoreTabs("Label 3");

tabbedPane1.addTab( "More Tabs 1", mt1);
tabbedPane1.addTab( "More Tabs 2", mt2);
tabbedPane1.addTab( "More Tabs 3", mt3);

Note that The constructor I created accepts a String parameter, which is used to set the label in the tab and when calling new MoreTab("Some Label") you will create a new MoreTab instance and pass in the label you want displayed. 请注意,我创建的构造函数接受一个String参数,该参数用于在选项卡中设置标签,并且在调用new MoreTab(“ Some Label”)时,您将创建一个新的MoreTab实例并传递要显示的标签。

Here is your code after modification, which runs and should do basically what you want: 这是修改后的代码,该代码可以运行,并且基本上应该执行您想要的操作:

import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.border.EmptyBorder;

@SuppressWarnings("serial")
public class TestContainer extends JFrame {

private JPanel contentPane;
public static JTabbedPane tabbedPane1;

/**
 * Launch the application.
 */
public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        @Override
        public void run() {
            try {
                TestContainer frame = new TestContainer();
                frame.setVisible(true);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
}

/**
 * Create the frame.
 */
public TestContainer() {

    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setBounds(100, 100, 450, 300);
    contentPane = new JPanel();
    contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
    setContentPane(contentPane);
    contentPane.setLayout(null);

    JScrollPane scrollBasePane = new JScrollPane();
    scrollBasePane.setBounds(10, 11, 414, 239);
    contentPane.add(scrollBasePane);

    JPanel panelBase = new JPanel();
    scrollBasePane.setViewportView(panelBase);
    panelBase.setLayout(null);

    tabbedPane1 = new JTabbedPane(JTabbedPane.TOP);
    tabbedPane1.setBounds(10, 11, 392, 215);
    panelBase.add(tabbedPane1);

    // add new JPanel to TabbedPane via a reusable Class
    MoreTabs mt1 = new MoreTabs("Label 1");
    MoreTabs mt2 = new MoreTabs("Label 2");
    MoreTabs mt3 = new MoreTabs("Label 3");

    tabbedPane1.addTab( "More Tabs 1", mt1); //non-static
    tabbedPane1.addTab( "More Tabs 2", mt2); //non-static
    tabbedPane1.addTab( "More Tabs 3", mt3); //non-static
    }
}

And

import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;

public class MoreTabs extends JPanel{

private JLabel lblPutStuffOn;
private JTextField text = new JTextField();

public MoreTabs(String labelText){
    lblPutStuffOn = new JLabel(labelText);
    add(lblPutStuffOn);
    add(text);
}

public String getLblText() {
    return lblPutStuffOn.getText();
}

public void setLblText(String s){
    lblPutStuffOn.setText(s);
}

public String getTxtText() {
    return text.getText();
}

public void setTxtText(String s){
    text.setText(s);
  }

}

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

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