无法通过第二页调用第三页 [英] Can't call a the third page via the 2nd Page

查看:82
本文介绍了无法通过第二页调用第三页的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'd like to create a software that has three pages: The "Home Page" (That's drawn on a JFrame "frame"), "Page 2" and "Page 3".

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

Pages 2 and 3 are drawn on "frame".

一个使用位于页面左侧和主页面上的导航窗格。内容位于右侧。

One uses a navigation pane that sits on the left side of the page and the main content is held on the right.

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

I'm currently only able to navigate to the 2nd page. The class called to draw page 2 on the JFrame can't seem to call Page three.

我的代码如下:

// 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页)称为第3课(第3页)。谢谢大家。

Please help me figure out how to make the 2nd class(page 2) call the 3rd Class(page 3). Thank you all in advance.

推荐答案

问题似乎在于方法 addAction Page2 类中的code>不会被调用。似乎负责将 actionListenerCallAnotherPage 注册到 buttonNavigation JButton ....

The problem seems to be the fact that the method addAction in your Page2 class is never called. It seems responsible for registering the actionListenerCallAnotherPage to the buttonNavigation JButton....

现在,说了……这似乎是艰苦的工作,却没有多大的收获。

Now, having said that...this seems like a lot of hard work for little gain.

您应该使用某种模型来管理导航,而不是尝试通过这种方式对导航进行硬链接。

Instead of trying to hard chain the navigation in this manner, you should use some kind of model that manages the navigation.

基本上,您可以通过引用将模型依次转到每个页面,准备就绪后,每个页面都将要求模型移至下一页。该模型将触发某种更改事件,以向主视图指示当前页面已更改,并且视图将相应地进行更新。

Basically, you would pass a reference of this model to each page in turn and each page would, when it's ready, ask the model to move to the next page. The model would fire some kind of change event to indicate to the main view that the current page has changed and the view would update itself accordingly.

您可以同时执行此操作与 CardLayout ,这意味着您甚至不需要为模型提供组件的引用,而是使用与 CardLayout 关联的页面名称 ,进一步解耦您的程序...

You could do this in conjuntion with a CardLayout, meaning that you wouldn't even need to give a reference of the component to the model, but instead use the "page name" which is associated with the CardLayout, further decoupling your program...

基于模型的方法

基本思想是将您的视图彼此分开,即使它们需要共享数据,我仍然会使用某种数据模型,但让我们专注于导航模型。

The basic idea is to separate your views from each other, even if they need to share data, I'd still use some kind of data model, but lets stay focused on the navigation model.

您需要什么...


  • 对所有可用视图及其应在其中显示的顺序有所了解

  • 当前的活动视图

  • 某种方式更改视图,例如上一个/下一个...

  • 以某种方式提供有关状态更改的通知...

  • 您还想要使模型与实际组件脱钩。尽管严格地讲这没错,但我只是不希望让我的组件开始传递到可能在我不知情的情况下对其进行修改的地方,如果我能帮助的话。更新视图也不是模型的责任,这是控制器的责任...这也意味着以前在屏幕上显示的实际组件与模型无关...

  • Some idea of all the available views and the order they should be displayed in
  • The current "active" view
  • Some way to change the views, previous/next for example...
  • Some way to provide notifications about the change in state...
  • You also want to decouple the model from the actual components. While "strictly" speaking it's not wrong, I just don't like having my components begin passed around to places that they might get modified without my knowledge if I can help it. It's also not the responsibility of the model to update the views, that's the controllers responsibility...This also means that the actual component used to be displayed on the screen is irrelevant to the model...

类似...

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

}

...例如

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

Now, I like to have an abstract implementation which does all the boring, repetitive work...

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

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

For example, here, I've provided a "linear" view model, this model will move all the way to the last view and stop or all the way to first view and stop. It wouldn't take much to create a circular view model which when it reach either end of the mode, would flip around to the other end...

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

要开始使用,需要某种方式将视图名称映射到具有代表性的组件。您还需要某种方式来监视模型的更改...

To get started, you would need some way to map the view names to there representative components. You would also need some way to monitor for changes to the model...

private Map<String, Component> mapViews;
private Component currentView;
private LinearViewModel model;

public ViewModelTest() {

    // Maps the view name to the component...
    mapViews = new HashMap<>(25);
    model = new LinearViewModel();
    mapViews.put("Page01", new Page01());
    mapViews.put("Page02", new Page02());
    mapViews.put("Page03", new Page03());
    mapViews.put("Page04", new Page04());

    // Add the view names to the model...
    model.addView("Page01");
    model.addView("Page02");
    model.addView("Page03");
    model.addView("Page04");

    // Initialise out view with the first page...
    currentView = mapViews.get("Page01");
    add(currentView);

    // Monitor for changes...
    model.addChangeListener(new ChangeListener() {
        @Override
        public void stateChanged(ChangeEvent e) {
            remove(currentView);
            currentView = mapViews.get(model.getCurrentView());
            add(currentView);
            revalidate();
        }
    });

}

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

Now, you're probably wondering, how does my view move to the next/previous view...?

不是。相反,我将创建一个导航栏,该导航栏将存在于主屏幕上,该导航栏将用于与模型本身进行交互...使每个页面/视图与整个过程脱钩...

It doesn't. Instead, I would create a navigation bar, which would exist on the main screen, which would be used to interact with the model itself...leaving each page/view decoupled from the whole process...

这篇关于无法通过第二页调用第三页的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆