2012-10-18 2 views
0

У меня есть Класс VTreePanel, который простирается от CPanel, который простирается от JPanel. Класс имеет объект JSplitPane, который разделен на две области: слева & справа. Левая сторона содержит объект выбора дерева. На правой стороне находится JTabbedPane объект. Класс VTreePanel как это:Вкладка, добавленная в JTabbedPane, не отображается

public final class VTreePanel extends CPanel 
    implements ActionListener 
{ 
    private JSplitPane centerSplitPane = new JSplitPane(); 

    private JTabbedPane tabbedPane; 

    ... 

    // GET method for the tabbedPane  
    public JTabbedPane getTabbedPane() { 
     return tabbedPane; 
    } 

    // Constructor 
    public VTreePanel(int WindowNo, boolean hasBar, boolean editable) 
    { 

     ... 

     tabbedPane = new JTabbedPane(); 
     centerSplitPane.add(treePart, JSplitPane.LEFT); 
     centerSplitPane.add(tabbedPane, JSplitPane.RIGHT); // Look at this 

     ... 
    } 

} 

В конструктора, я добавил выбор дерева (treePart) и JTabbedPane объект (tabbedPane) в объект (centerSplitPane Панель с разделителем). Я еще не добавил Tab в tabbedPane. Посмотрите на скриншот ниже:

http://i45.tinypic.com/2v3j0nl.jpg

Тогда как я могу добавить вкладку, когда пользователь нажимает одну из меню?

Я AMENU класс, где он осуществил PropertyChangeListener что выпустили метод propertyChange когда пользователь нажал на меню:

public final class AMenu extends CFrame 
    implements ActionListener, PropertyChangeListener, ChangeListener 
{ 

    private VTreePanel treePanel = null; // this is the VTreePanel object 

    ... 

    public void propertyChange(PropertyChangeEvent e) 
    { 
     ... 

     // Here I pass the VTreePanel object as parameter to AMenuStartItem thread object 
     (new AMenuStartItem(cmd, true, sta, this, treePanel)).start(); 
    } 

} 

Вы можете видеть, что у меня есть VTreePanel объект (TreePanel) и я прохожу VTreePanel объект как параметр to AMenuStartItem нить. AMENUStartItem содержит логику, которая выполняет добавление Tab в JTabbedPane (помните, что объект JTabbedPane (tabbedPane) находится в VTreePanel).

Вот AMenuStartItem класс нить:

public class AMenuStartItem extends Thread implements ActionListener 
{ 
    private VTreePanel m_vtreePanel; 

    public AMenuStartItem (int ID, boolean isMenu, String name, AMenu menu, VTreePanel vtreepanel) 
    { 
     ... 

     m_vtreePanel = vtreepanel; // save the VTreePanel object 
    } 

    // The thread method that executed when thread is started 
    public void run() 
    { 
     ... 

     startWindow(0, cmd); 

     ... 
    } 

    private void startWindow(int AD_Workbench_ID, int AD_Window_ID) 
    { 
     ... 

     // Here I perform adding new tab 
     m_vtreePanel.getTabbedPane().addTab(frame.getTitle(), frame.getAPanel()); 

     ... 
    } 

} 

Итак, getTabbedPane() возвратил объект JTabbedPane и метод addTab() выполняется, но нет вкладки не появился вовсе.

Кто-нибудь знает, как исправить эту проблему?

+0

Во-первых, ваш мели один из самых важных трасс свинг, вы пытаетесь обновить компоненты пользовательского интерфейса извне [Event Dispatching Thread] (http://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html). Прочитайте [Concurrency in Swing] (http://docs.oracle.com/javase/tutorial/uiswing/concurrency/index.html) о способах его работы. Во-вторых, вам нужно вызвать invalidate и repaint на JTabbedPane – MadProgrammer

+0

Вы имели в виду, что я должен использовать этот код в методе propertyChange()? javax.swing.SwingUtilities.invokeLater (новый AMenuStartItem (cmd, true, sta, this, treePanel)); Я пробовал, но до сих пор не появилась табуляция. – null

+0

Hi MadProgrammer, я ошибся при тестировании приложения ^^. Оказалось, что я тестировал неправильную вкладку Main (вкладка Main Tab - горизонтальная вкладка, состоящая из: Accounting, Finance, CRM и т. Д.). Так получилось, что все работает хорошо. Я удалю свой вопрос в следующий час. Однако мой исходный код работает хорошо, не используя SwingUtilities.invokeLater(). Спасибо за совет в любом случае. – null

ответ

1

Все взаимодействия с UI должен быть сделано через Event диспетчерские тему, без исключений ...

public class AMenuStartItem extends Thread implements ActionListener 
{ 
    private VTreePanel m_vtreePanel; 

    public AMenuStartItem (int ID, boolean isMenu, String name, AMenu menu, VTreePanel vtreepanel) 
    { 
     ... 

     m_vtreePanel = vtreepanel; // save the VTreePanel object 
    } 

    // The thread method that executed when thread is started 
    public void run() 
    { 
     ... 

     startWindow(0, cmd); 

     ... 
    } 

    private void startWindow(final int AD_Workbench_ID, final int AD_Window_ID) 
    { 
     ... 

     if (EventQueue.isDispatchingThread()) { 
      // This is safe, we're in the EDT 
      m_vtreePanel.getTabbedPane().addTab(frame.getTitle(), frame.getAPanel()); 
      m_vtreePanel.getTabbedPane().invalidate(); 
      m_vtreePanel.getTabbedPane().repaint(); 
     } else { 
      // This is unsafe, we need to resync with the EDT 
      SwingUtilities.invokeLater(new Runnable() { 
       public void run() { 
        // Here I perform adding new tab 
        m_vtreePanel.getTabbedPane().addTab(frame.getTitle(), frame.getAPanel()); 
        m_vtreePanel.getTabbedPane().invalidate(); 
        m_vtreePanel.getTabbedPane().repaint(); 

       } 
      }); 
     } 

     ... 
    } 

} 
+0

Hi MadProgrammer, Я ошибся при тестировании приложения ^^. Оказалось, что я тестировал неправильную вкладку Main (вкладка Main Tab - горизонтальная вкладка, состоящая из: Accounting, Finance, CRM и т. Д.). Так получилось, что все работает хорошо. Я удалю свой вопрос в следующий час. Однако мой исходный код работает хорошо, не используя SwingUtilities.invokeLater(). Спасибо за совет в любом случае. – null

+0

Недействителен() и перерисовывается() необходимо? Я оставил их и не нашел проблем. У меня также были эти строки: m_vtreePanel.getTabbedPane.indexOfComponent() и m_vtreePanel.getTabbedPane.setSelectedIndex(), следует ли также помещать эти две строки внутри invokeLater()? – null

+1

недействительны метки * недопустимый контейнер, указывающий, что контейнер должен быть выложен *, перескажите запрос, чтобы диспетчер перекраски добавлял наш контейнер в грязный список для обновления в течение следующего цикла рисования. Требуются ли они не всегда, но если у вас проблемы с компонентами, которые не появляются, это помогает. 'setSelectedIndex' изменяет пользовательский интерфейс, поэтому да, он должен быть вызван из EDT – MadProgrammer

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