2016-02-14 2 views
1

У меня есть класс Java используется в качестве контейнера, он кодируется иметь JPanel и TabbedPaneКак Инстанцировать Java Класс компонентов Swing несколько раз

У меня есть еще один класс Java, который строит JPanel, содержащий JLabel s и JTextField s, который я хочу добавить в TabbedPane класса контейнера. Я хочу новый экземпляр класса, который добавляет 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, перенося свои навыки сверху вниз на ООП.

Вот мой код:

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

} 
+1

Некоторые общие советы: Не используйте нуль-макеты, используйте соответствующие [ менеджеров компоновки] (https://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html). И я думаю, что было бы более разумно, если бы «MoreTabs» расширил «JPanel», но, возможно, это только я. Но я не совсем понимаю, почему вы хотите использовать один и тот же экземпляр «MoreTabs» для нескольких вкладок. Почему бы просто не создать несколько экземпляров? (например, если 'MoreTabs' будет расширять' JPanel' нечто вроде 'tabbedPane1.addTab (« title1 », new MoreTabs()); tabbedPane2.addTab (« title2 », new MoreTabs());) –

+0

@LuxxMiner, я не могу благодарю вас за ваши комментарии. И да, я перехожу к менеджерам макетов. Я получаю свою голову вокруг Flow (довольно понятный) и Form (непонятно по спецификациям Col and Row). Опять же, большое спасибо. – EricG

ответ

1

LuxxMiner прямо в его комментарий .. MoreTabs должен расширить JPanel Затем вы можете добавить несколько экземпляров MoreTabs, если это то, что вы хотите сделать.

Есть несколько других основных проблем с вашим кодом:

1) В MoreTabs у вас есть строки:

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

случайным образом в верхней части класса. Вы не можете сделать это, и это будет ошибка компиляции.У вас должен быть конструктор класса MoreTabs для инициализации ваших переменных.

Constructor:

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(). Вам необходимо префикс с «новым», как это:

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

Обратите внимание, что конструктор я создал принимает параметр типа String, который используется для установки метки в закладке и при вызове нового MoreTab («Some Ярлык») вы создадите новый экземпляр 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); 
    } 

} 
+0

Благодарим вас за исправление кода, основанное на комментариях @LuxxMiner. Большое спасибо всем вам. Прошло почти 20 лет с тех пор, как я написал код. – EricG

3

Не делайте JTabbedPane статичным. Такие JComponentents нельзя использовать: у них есть один родительский контейнер, например.

Можно создать класс контейнера, например JMyPanel, и создать несколько экземпляров в нескольких местах.

Если эти экземпляры также должны ссылаться на одну и ту же модель данных, скажем, что JTextFields изменяют один и тот же текст, и оба экземпляра доступны одновременно, тогда в качелях нужно изменить прослушиватели в этих текстовых полях.

Это требует парадигмы Model-View-Controller.

Можно сделать один отдельный класс контроллера, содержащий модель данных (тексты как String), и позволить изменениям в JTextField (представление) вызвать контроллер для обновления модели и переноса обновленного значения в другие виды.

Используйте Document:

jTextComponent.getDocument() 

Вы можете иметь два текстовых полей JTextField, имеющих свой собственный документ и использовать reciproke уведомление об истинных изменений. Или, поскольку в javadoc документа предлагается использовать один общий документ. Последнее, как я помню, используется редко, так как в целом модель данных состоит из более входных компонентов.

(КСТАТИ. В JavaFX текстовое поле будет привязан к StringProperty который можно держать в модели данных, и уведомляет об изменениях и может быть связано более чем один раз.)

+0

Спасибо, Джоп. Я могу абстрактно представить вашу рекомендацию. Однако у меня нет необходимых навыков и уровней воздействия, чтобы двигаться в этом направлении. – EricG

Смежные вопросы