无法通过第二页调用第三页

时间:2013-08-21 06:22:13

标签: java swing class jframe

我想创建一个包含三个页面的软件:“主页”(在JFrame“框架”上绘制),“第2页”和“第3页”。

第2页和第3页在“框架”上绘制。

一个使用位于页面左侧的导航窗格,主要内容保存在右侧。

我目前只能导航到第二页。调用在JFrame上绘制第2页的类似乎无法调用第3页。

我的代码如下:

// The Home Page

package Try;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class HomePage {
    JPanel panelHomeWrapper = new JPanel();
    JPanel panelNavigation = new JPanel();
    JPanel panelDisplay = new JPanel();

    JButton buttonNavigation = new JButton("Button Home = Menu Items");
    JButton buttonBody = new JButton("Button body Page Home = Home body Items");

    public static void main (String[] args) {
        HomePage home = new HomePage();
        home.homePanel();
    }

    public void homePanel () {
        JFrame frame = new JFrame("Home");

        JButton button = new JButton("Button");

        ActionListener actionListener = new ActionListener() {
            public void actionPerformed(ActionEvent actionEvent) {
                System.out.println("Panel 2 was called.");

                Page2 panel2 = new Page2();

                panelNavigation.remove(buttonNavigation);
                panelDisplay.remove(buttonBody);

                panelNavigation.add(panel2.buttonNavigation);
                panelDisplay.add(panel2.buttonBody);

                panelNavigation.validate();
                panelNavigation.repaint();

                panelDisplay.validate();
                panelDisplay.repaint();
            }
        };

        button.addActionListener(actionListener);


        buttonNavigation.addActionListener(actionListener);

        panelNavigation.add(buttonNavigation);
        panelDisplay.add(buttonBody);

        panelHomeWrapper.add(panelNavigation);
        panelHomeWrapper.add(panelDisplay);

        frame.add(panelHomeWrapper);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(455, 355);
        frame.setVisible(true);
    }
} // End of Home Page

第2页

// Page 2

package Try;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JPanel;

public class Page2 {
    JButton buttonNavigation = new JButton("Button 2 = Menu Items");
    JButton buttonBody = new JButton("Button body Page 2 = Page 2 body Items");

    ActionListener actionListenerCallAnotherPage = new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent actionEvent) {
            System.out.println("Button Body 3 was called.");

            HomePage home = new HomePage();
            Page3 panel3 = new Page3();

            home.panelDisplay.remove(buttonBody);
            home.panelDisplay.add(panel3.buttonBody3);

            home.panelDisplay.validate();
            home.panelDisplay.repaint();

        }
    };

    public void addAction () {
        buttonNavigation.addActionListener(actionListenerCallAnotherPage);
    }
}

第3页

// Page 3

package Try;

import javax.swing.JButton;

public class Page3 {
    JButton buttonBody3 = new JButton("Page 3");
} // End of Page 3

请帮我弄清楚如何让第2课(第2页)拨打第3课(第3页)。提前谢谢大家。

1 个答案:

答案 0 :(得分:2)

问题似乎是addAction类中的方法Page2从未被调用过。它似乎负责将actionListenerCallAnotherPage注册到buttonNavigation JButton ....

现在,已经说过......这似乎是一项很难获得的努力。

您应该使用某种管理导航的模型,而不是尝试以这种方式硬链接导航。

基本上,您可以依次将此模型的引用传递给每个页面,并且每个页面在准备好后,请求模型移动到下一页。该模型将触发某种更改事件,以向主视图指示当前页面已更改,并且视图将相应地更新自身。

您可以与CardLayout结合使用,这意味着您甚至不需要向模型提供组件的引用,而是使用与{相关联的“页面名称” {1}},进一步解耦你的程序......

基于模型的方法

基本的想法是将你的观点彼此分开,即使他们需要共享数据,我仍然使用某种数据模型,但让我们专注于导航模型。

你需要什么......

  • 了解所有可用视图及其应在
  • 中显示的顺序
  • 当前“有效”视图
  • 某些更改视图的方法,例如上一个/下一个...
  • 某种方式提供有关状态变化的通知......
  • 您还希望将模型与实际组件分离。虽然“严格地”说它并没有错,但我只是不喜欢让我的组件开始转移到他们可能会在我不知情的情况下修改的地方,如果我能帮助它的话。更新视图也不是模型的责任,这是控制器的责任......这也意味着过去在屏幕上显示的实际组件与模型无关......

像...一样的东西。

CardLayout

......例如

现在,我希望有一个抽象的实现,可以完成所有无聊,重复的工作......

public interface ViewModel {

    /**
     * Returns the name of the current "active" view name
     * @return
     */
    public String getCurrentView();

    /**
     * Instructs the model to move to the next view if one is
     * available...
     */
    public void nextView();

    /**
     * Instructs the model to move to the previous view if one is
     * available...
     */
    public void previousView();

    /**
     * Returns the number of views in this model
     */
    public int size();

    /**
     * Returns the name of the view at the specified index...
     * @param index
     * @return 
     */
    public String getViewAt(int index);

    /**
     * Adds a ChangeListeners to the model, which will be notified when
     * the current view changes
     */
    public void addChangeListener(ChangeListener listener);

    /**
     * Remove a ChangeListeners from the model
     */
    public void removeChangeListener(ChangeListener listener);

}

这允许我设计不同的实现以满足我的需求......

例如,在这里,我提供了一个“线性”视图模型,该模型将一直移动到最后一个视图并停止或一直到第一个视图和停止。创建一个圆形视图模型并不需要太多,当它到达模式的任何一端时,会翻转到另一端......

public abstract class AbstractViewModel implements ViewModel {

    private EventListenerList listenerList;
    private List<String> views;

    public void addView(String name) {
        getViews().add(name);
    }

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

    @Override
    public int size() {
        return views.size();
    }

    @Override
    public String getCurrentView() {
        return getViewAt(getCurrentViewIndex());
    }

    protected abstract int getCurrentViewIndex();

    protected List<String> getViews() {
        if (views == null) {
            views = new ArrayList<>(25);
        }
        return views;
    }

    @Override
    public String getViewAt(int index) {
        return index >= 0 && index < size() ? getViews().get(index) : null;
    }

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

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

    protected EventListenerList getListenerList() {
        if (listenerList == null) {
            listenerList = new EventListenerList();
        }
        return listenerList;
    }

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

要开始使用,您需要一些方法将视图名称映射到代表性组件。您还需要一些方法来监控模型的更改...

public class LinearViewModel extends AbstractViewModel {

    private int currentIndex;

    @Override
    protected int getCurrentViewIndex() {
        return currentIndex;
    }

    @Override
    public void nextView() {
        if (currentIndex + 1 < size()) {
            currentIndex++;
            fireStateChanged();
        }
    }

    @Override
    public void previousView() {
        if (currentIndex - 1 >= 0) {
            currentIndex--;
            fireStateChanged();
        }
    }    
}

现在,您可能想知道,我的视图如何转移到下一个/上一个视图......?

没有。相反,我会创建一个导航栏,它将存在于主屏幕上,用于与模型本身交互...让每个页面/视图与整个过程分离......