2

I have a java class being used as a container, it is coded to have a JPanel and a TabbedPane

I have another java class that builds a JPanel containing JLabels and JTextFields that I want added to the TabbedPane of the container class. I want a new instance of the class that adds the JPanel, so I can add multiple tabs to the container class.

I have reviewed the following: 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, and multiple web authors. I am not a student doing an assignment, I am an old dude, new to Java, moving my top-down skills to 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);
  }

}
Community
  • 1
  • 1
EricG
  • 65
  • 9
  • 1
    Some general advice: Don't use null-layouts, use proper [layout managers](https://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html) instead. And I think it would make more sense if `MoreTabs` would extend `JPanel`, but maybe that's just me. But I don't quite get why you want to use the same instance of `MoreTabs` for multiple tabs. Why not just create multiple instances? (e.g. if `MoreTabs` would extend `JPanel` something like `tabbedPane1.addTab("title1", new MoreTabs()); tabbedPane2.addTab("title2", new MoreTabs());`) – Lukas Rotter Feb 14 '16 at 18:08
  • @LuxxMiner, I cannot thank you enough for your on-point comments. And yes, I am moving to layout managers. I am getting my head around Flow (pretty understandable) and Form (not clear on Col and Row specs). Again, many thanks. – EricG Feb 14 '16 at 19:09

2 Answers2

3

Do not make the JTabbedPane static. Such JComponentents cannot be shared: they have a single parent Container for instance.

One can make a container class, say JMyPanel, and create several instances at several places.

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.

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.

Use the Document:

jTextComponent.getDocument()

You can have two JTextFields having their own Document and use a reciproke notification of true changes. Or as the javadoc of Document suggests use one shared 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.)

Joop Eggen
  • 107,315
  • 7
  • 83
  • 138
  • Thank you Joop. I can abstractly conceive your recommendation. However, I am not at the necessary skill and exposure levels to move in this direction. – EricG Feb 14 '16 at 19:43
1

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.

There are a couple of other major issues with your code:

1) In MoreTabs you have lines:

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.

Constructor:

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

2) These two lines don't make sense:

// 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. You cant just call mt1(). You need to prefix it with 'new' like this:

// 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.

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

}
pczeus
  • 7,709
  • 4
  • 36
  • 51
  • Thank you for the code correction based off of @LuxxMiner comments. Many thanks to all of you. It has been nearly 20 years since I wrote code. – EricG Feb 14 '16 at 19:40