【问题标题】:How to Instantiate Java Class of Swing Components Multiple Times如何多次实例化 Swing 组件的 Java 类
【发布时间】:2016-02-14 17:54:13
【问题描述】:

我有一个 java 类被用作容器,它被编码为有一个 JPanel 和一个 TabbedPane

我有另一个 java 类,它构建了一个 JPanel,其中包含我想要添加到容器类的 TabbedPane 中的 JLabelJTextField .我想要一个添加 JPanel 的类的新实例,因此我可以向容器类添加多个选项卡。

我查看了以下内容:Can we reuse Java Swing application components in other instances of same application?Multiple instances of model components in Java Swing?Multiple instance of ONE JFrame 和多个网络作者。我不是做作业的学生,​​我是一个老伙计,刚接触 Java,将我的自上而下的技能转移到 OOP。

这是我的代码:

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
    }
 }

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

}

【问题讨论】:

  • 一些一般性建议:不要使用空布局,而是使用正确的layout managers。我认为如果MoreTabs 扩展JPanel 会更有意义,但也许这只是我。但我不太明白为什么要对多个选项卡使用MoreTabs 的相同实例。为什么不只创建多个实例? (例如,如果 MoreTabs 将扩展 JPanel 类似于 tabbedPane1.addTab("title1", new MoreTabs()); tabbedPane2.addTab("title2", new MoreTabs());
  • @LuxxMiner,我非常感谢您的现场 cmets。是的,我正在转向布局管理器。我对 Flow(很容易理解)和 Form(在 Col 和 Row 规范上不清楚)有所了解。再次,非常感谢。

标签: java swing multiple-instances


【解决方案1】:

不要将 JTabbedPane 设为静态。此类 JComponentent 不能共享:例如,它们只有一个父 Container。

可以创建一个容器类,比如 JMyPanel,并在多个位置创建多个实例。

如果这些实例也应该引用相同的数据模型,比如 JTextField 更改相同的文本,并且两个实例可以同时访问,那么在摇摆中,需要更改这些文本字段上的侦听器。

这需要模型-视图-控制器范式。

可以创建一个包含数据模型(文本为字符串)的单独控制器类,并让对 JTextField(视图)的更改调用控制器来更新模型并将更新后的值移植到其他视图。

使用Document

jTextComponent.getDocument()

您可以让两个 JTextField 拥有自己的 Document,并使用真实更改的交互通知。或者正如 Document 的 javadoc 建议使用一个共享文档。后者我记得很少使用,因为通常数据模型由更多的输入组件组成。

(顺便说一句。在 JavaFX 中,TextField 将绑定到可以保存在数据模型中的 StringProperty,并通知更改并且可以多次绑定。)

【讨论】:

  • 谢谢乔普。我可以抽象地设想你的建议。但是,我还没有达到朝这个方向发展所需的技能和曝光水平。
【解决方案2】:

LuxxMiner 在他的评论中是正确的.. MoreTabs 应该扩展 JPanel 然后,如果您愿意,可以添加多个 MoreTabs 实例。

您的代码还有其他几个主要问题:

1) 在 MoreTabs 中有行:

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

随机排名第一。你不能这样做,这将是一个编译错误。您应该在 MoreTabs 类中有一个构造函数来初始化您的变量。

构造函数:

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

2) 这两行没有意义:

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

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

看起来您正在尝试做的是实例化 MoreTabs 并作为选项卡添加到选项卡式面板。你不能只调用 mt1()。你需要像这样在它前面加上'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);

请注意,我创建的构造函数接受一个字符串参数,该参数用于设置选项卡中的标签,当调用 new MoreTab("Some Label") 时,您将创建一个新的 MoreTab 实例并传入您要显示的标签.

这是你修改后的代码,它运行并且基本上应该做你想要的:

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
    }
}

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

}

【讨论】:

  • 感谢您根据@LuxxMiner cmets 进行的代码更正。非常感谢你们所有人。我写代码已经快 20 年了。
猜你喜欢
  • 2011-09-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-18
  • 1970-01-01
相关资源
最近更新 更多