2013-08-06 3 views
1

Концепции Я пытаюсь работать в мою программу в основном:Как я могу переключить JPanels удаленно?

-Главного Window: основной класс, который содержит основной каркас программы, то есть:

public class MainWindow extends JFrame { 
    ... 
} 

-Других классы: классы которые проходят JPanel, так что они могут быть легко добавлены в MainWindow в качестве одного объекта или субъекта, а именно:

public class SomePanel extends JPanel { 
    ... 
} 

таким образом, я могу сказать, для главного окна:

public MainWindow() { 
... 
SomePanel sp = new SomePanel(); 
add(sp); 
... 
} 

Когда некоторые ActionEvent срабатывает, я могу сказать, в классе MainWindow:

// remove the current panel 
getContentPane().remove(sp); 
// insert the new panel 
getContentPane().add(someOtherPanel); 
validate(); 
repaint(); 

Понятие, я полагаю, это как CardLayout, за исключением того, я не удосужился обучение CardLayout еще и я было похоже на попытку этой концепции. Вероятно, я, возможно, изучу CardLayout в какой-то момент, в зависимости от того, что проще.

Но мой главный вопрос: как я могу переключаться между JPanels удаленно, как это, на основе триггера ActionEvent, если все в разных классах? Я думал, что между классами должен быть какой-то общий компонент, но это, похоже, не работает. Я на правильном пути?

Код, который я пытаюсь удалить() и add(), кажется, не работает, так как ничего не меняется, когда я запускаю ActionEvent для компонента (слушатель добавлен и все). Я также включаю validate() и repaint(), но все равно ничего не происходит.

Я уже не новичок, но и не невероятно переживаю, так что несите меня, если есть что-то очевидное, что мне не хватает. Спасибо за любую помощь.

ответ

7

Вы, безусловно, находитесь на правильном пути и почти имеете его. Обратите внимание, как вы используете add(sp); в своем конструкторе, но в нижнем примере используйте getContentPane().remove(sp); и getContentPane().add(someOtherPanel);. Существует, безусловно, метод remove(Component c) для JPanel, поэтому используйте это.

Кроме того, все будет проще, если вы будете манипулировать своими компонентами в одном месте. Мне нравится делать это прямо в основном методе или в основном классе. Например:

public class Start implements ActionListener { 
    Window theWindow = new Window(); 
    CustomPanel mainMenu = new CustomPanel(); 
    CustomPanel optionsMenu = new CustomPanel(); 
    Button myButton = new Button(); 
    public static void main(String[] args) { 
     theWindow.add(mainMenu); 
     mainMenu.add(myButton); 
     myButton.addActionListener(this); 

     theWindow.setVisible(true); 
     theWindow.repaint(); 
    } 

    public void actionPerformed(Event e) { 
     theWindow.remove(mainMenu); 
     theWindow.add(optionsMenu); 
     theWindow.repaint(); 
    } 

Обратите внимание на то, как легко было все это сделать, даже не вникая в специфику с пользовательскими классами. Я предлагаю структурировать ваши программы и gui's вот так.

Также как MadProgrammer, вы можете использовать theWindow.revalidate() вместо repaint().

+1

'theWindow.revalidate()', вероятно, лучше работать – MadProgrammer

+0

я не знал этого метода, я всегда использую 'repaint'. Спасибо, я отредактировал свой ответ. – snickers10m

+0

Теперь я могу с уверенностью утверждать: D – MadProgrammer

5

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

Так, например. Вы можете создать модель, которая позволила бы связать компонент с именованным действием (например). Когда в вашем приложении появятся некоторые действия, вы должны указать модели на setCurrentAction и передать ей название действия, которое должно быть доступно.

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

Таким образом, вы отвязать модель из пользовательского интерфейса

Обновленный с примером

Это доказательство концепции. Главное, чтобы продемонстрировать средство, с помощью которого вы можете отвязать модели из пользовательского интерфейса, так что модель не заботится, чьи управления выходом, только, что он может сказать кому-то ...

import java.awt.BorderLayout; 
import java.awt.Component; 
import java.awt.EventQueue; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.util.HashMap; 
import java.util.Map; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 
import javax.swing.event.ChangeEvent; 
import javax.swing.event.ChangeListener; 
import javax.swing.event.EventListenerList; 

public class PageFlipper { 

    public static void main(String[] args) { 
    new PageFlipper(); 
    } 

    public PageFlipper() { 
    startUI(); 
    } 

    public void startUI() { 
    EventQueue.invokeLater(new Runnable() { 
     @Override 
     public void run() { 
     try { 
      UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
     } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
      ex.printStackTrace(); 
     } 

     JFrame frame = new JFrame("Testing"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.add(new MainView()); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
     } 
    }); 
    } 

    public class MainView extends JPanel { 

    private DefaultViewModel model; 

    public MainView() { 
     setLayout(new BorderLayout()); 
     model = new DefaultViewModel(); 
     model.addChangeListener(new ChangeListener() { 
     @Override 
     public void stateChanged(ChangeEvent e) { 
      System.out.println("Current view = " + model.getCurrentViewName()); 
      removeAll(); 
      add(model.getCurrentView()); 
      revalidate(); 
      repaint(); 
     } 
     }); 
     model.addView("Menu", new ActionPane("Menu", "Settings", model)); 
     model.addView("Settings", new ActionPane("Settings", "Menu", model)); 
     model.setCurrentView("Menu"); 
    } 

    } 

    public class ActionPane extends JPanel { 

    private final String nextView; 
    private final ViewModel model; 

    public ActionPane(String name, String nextView, ViewModel model) { 
     this.nextView = nextView; 
     this.model = model; 
     setLayout(new BorderLayout()); 
     JLabel label = new JLabel(name); 
     label.setHorizontalAlignment(JLabel.CENTER); 
     label.setVerticalAlignment(JLabel.CENTER); 
     add(label); 

     JButton btn = new JButton("Next"); 
     btn.addActionListener(new ActionListener() { 
     @Override 
     public void actionPerformed(ActionEvent e) { 
      ActionPane.this.model.setCurrentView(ActionPane.this.nextView); 
     } 
     }); 
     add(btn, BorderLayout.SOUTH); 
    } 

    } 

    public interface ViewModel { 

    public void setCurrentView(String name); 
    public Component getCurrentView(); 
    public void addChangeListener(ChangeListener listener); 
    public void removeChangeListener(ChangeListener listener); 

    } 

    public class DefaultViewModel implements ViewModel { 

    private final Map<String, Component> views; 
    private final EventListenerList listenerList; 
    private String currentView; 

    public DefaultViewModel() { 
     views = new HashMap<>(25); 
     listenerList = new EventListenerList(); 
    } 

    public void addView(String name, Component comp) { 
     views.put(name, comp); 
    } 

    public void removeView(String name) { 
     views.remove(name); 
    } 

    @Override 
    public void setCurrentView(String name) { 
     if (currentView == null ? name != null : !currentView.equals(name)) { 
     currentView = name; 
     fireStateChanged(); 
     } 
    } 

    public String getCurrentViewName() { 
     return currentView; 
    } 

    @Override 
    public Component getCurrentView() { 
     return currentView == null ? null : views.get(currentView); 
    } 

    @Override 
    public void addChangeListener(ChangeListener listener) { 
     listenerList.add(ChangeListener.class, listener); 
    } 

    @Override 
    public void removeChangeListener(ChangeListener listener) { 
     listenerList.remove(ChangeListener.class, listener); 
    } 

    protected void fireStateChanged() { 
     ChangeListener[] listeners = listenerList.getListeners(ChangeListener.class); 
     if (listeners.length > 0) { 
     ChangeEvent evt = new ChangeEvent(this); 
     for (ChangeListener listener : listeners) { 
      listener.stateChanged(evt); 
     } 
     } 
    } 

    } 

} 

Вы могли легко изменить его, чтобы иметь более значимые имена вид/действие (т.е. использовать какой-то Object вместо String), а также обеспечить более продвинутую навигацию (например, next и previous, например)

0

вы можете попробовать это:

~ добавьте оба jpanels один раз

~ всякий раз, когда есть событие, переключают обзорности панелей ...

пример:

//global variables 
int i = 0; 
JPanel p2 = new JPanel(); 
JPanel p = new JPanel(); 

, когда есть вызов событием этого метода: switchPanels(), но вы можете назвать его, как вы хотите. ..: D

public void switchPanels() { 
    i++; 
    if(i % 2 == 0){ 
     p.setVisible(true); 
     p2.setVisible(false); 
    }else{ 
     p.setVisible(false); 
     p2.setVisible(true); 
    } 

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