从菜单到父类

时间:2016-01-02 05:07:00

标签: java swing user-interface

我正在深入研究JAVA应用程序,我正在尝试将重载主文件中的内容清理干净,以实现更加分散的设计。

我按照tutorial将菜单移动到了自己的类。

在主类的init()方法中,我有类似的内容:

JMenuBar myMenu = new MainMenu();
setJMenuBar(myMenu);

在课程MainMenu中,我创建了一个菜单。菜单显示,我可以捕获MainMenu中的菜单点击,但我需要在实际创建myMenu的班级中触发一些活动。

我正在使用这样的东西:

someMethod(){
  ....
  noteReadingMenuItem.setAction(doSomething);
  ....
}

我已经在我班级的顶部创建Action作为MainMenu的私人成员,如下所示:

private Action doSomething = new AbstractAction("Do Something", new ImageIcon(getClass().getResource("/images/icon.png"))   ) {
    public void actionPerformed(ActionEvent e) {    
        //Do local processing here
    }
};

在阅读文档时,似乎有其他方法可以创建操作,或者只使用.addActionLister(this),因此在actionPerformed(ActionEvent e)类的MainMenu中处理它(实现ActionListener 1}})。

如何通知Main类,或者其他关于菜单操作的类?

我试图"发送"该消息基于其他一些帖子,但我不知道如何在Main类中接收它,它不会在Main类的actionPerformed()中收到,也不会处理任何错误:

java.awt.Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(e);

Component source = (Component) SwingUtilities.windowForComponent(parent);

source.dispatchEvent(e);

3 个答案:

答案 0 :(得分:1)

您可以使用Observer Pattern

步骤:

  1. 在您希望通知的类中实施 观察者界面
  2. 通知Observers
  3. 的类中扩展Observable类
  4. 使用以下方法将 Observer 添加到 Observables

    addObserver();
    
  5. 如果您希望收到通知,请致电:

    setChanged();
    notifyObservers();
    
  6. Observers 上实施 update()方法,因为在发生通知时将调用此方法。

  7. 此处还阅读了Observer的Java文档:https://docs.oracle.com/javase/7/docs/api/java/util/Observer.html

    这里是Observable:https://docs.oracle.com/javase/7/docs/api/java/util/Observable.html

    你不需要实现任何东西,它都在JDK中。

    enter image description here

答案 1 :(得分:1)

第一种方法

最简单的方法是在MainMenu中维护对Main类的引用,并将其称为一些notify方法。

检查以下代码。

JMenuBar myMenu = new MainMenu();
myMenu.setMain(this);//this is the Main class reference
setJMenuBar(myMenu);
//setMain inside MainMenu
public void setMain(Main main) {
    this.main = main;
}

Main类有notifyMain方法

public class Main {
    ...

    public void notifyMain(Object notification) {
        //do something with notification
    }
}

现在,由于MainMenu引用了Main类,因此可以在其上调用notifyMain方法。

第二种方法

另一种方法是从匿名类访问Main实例。

为此,我们必须使JMenuBar成为一个抽象类,添加一个abstractMethod notifyMain()

abstract class MainMenu {
    public abstract void notifyMain();
}
//inside Main class
JMenuBar menu = new MainMenu() {
    public abstract void notifyMain(Object notification) {
        Main.this.notifyMain(notification);
    }
};

现在MainMenu再次引用了Main类,但它不必为它声明一个专用字段。它保持了一种功能封闭形式。

此方法的优点是您可以在其他类中执行相同的操作,并以与下面相同的方式通知它们。

//Inside Other Class
JMenuBar menu = new MainMenu() {
    public abstract void notifyMain() {
        Other.this.notifyMain();
    }
};

第三种方法

第三种方法是设计模式,观察者模式。由于@Saibot已经在他的回答中写了这篇文章,所以我在这里添加更多信息。

答案 2 :(得分:1)

你可以......

public class AndroidBug5497Workaround { // For more information, see https://code.google.com/p/android/issues/detail?id=5497 // To use this class, simply invoke assistActivity() on an Activity that already has its content view set. public static void assistActivity (Activity activity, int svChildLayoutId) { new AndroidBug5497Workaround(activity, svChildLayoutId); } private View mChildOfContent; private int usableHeightPrevious; private FrameLayout.LayoutParams frameLayoutParams; View svChildLayout; int originalGravity; Activity activity; private AndroidBug5497Workaround(Activity activity, int svChildLayoutId) { this.activity = activity; svChildLayout = activity.findViewById(svChildLayoutId); originalGravity = ((ScrollView.LayoutParams)svChildLayout.getLayoutParams()).gravity; FrameLayout content = (FrameLayout) activity.findViewById(android.R.id.content); mChildOfContent = content.getChildAt(0); mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { public void onGlobalLayout() { possiblyResizeChildOfContent(); } }); frameLayoutParams = (FrameLayout.LayoutParams) mChildOfContent.getLayoutParams(); } private void possiblyResizeChildOfContent() { int usableHeightNow = computeUsableHeight(); if (usableHeightNow != usableHeightPrevious) { int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight(); int heightDifference = usableHeightSansKeyboard - usableHeightNow; if (heightDifference > (usableHeightSansKeyboard/4)) { // keyboard probably just became visible onKeyboardVisible(); frameLayoutParams.height = usableHeightSansKeyboard - heightDifference; } else { // keyboard probably just became hidden onKeyboardHidden(); frameLayoutParams.height = usableHeightSansKeyboard; } mChildOfContent.requestLayout(); usableHeightPrevious = usableHeightNow; } } private int computeUsableHeight() { Rect r = new Rect(); mChildOfContent.getWindowVisibleDisplayFrame(r); return (r.bottom - r.top); } private void onKeyboardVisible() { ScrollView.LayoutParams params = (ScrollView.LayoutParams) svChildLayout.getLayoutParams(); params.gravity = Gravity.TOP; svChildLayout.requestLayout(); final ScrollView parentSv = (ScrollView) svChildLayout.getParent(); parentSv.post(new Runnable() { @Override public void run() { View focusedEditText = activity.getWindow().getCurrentFocus(); parentSv.smoothScrollTo(0, focusedEditText.getTop() ); } }); } private void onKeyboardHidden() { ScrollView.LayoutParams params = (ScrollView.LayoutParams) svChildLayout.getLayoutParams(); params.gravity = originalGravity; svChildLayout.requestLayout(); } } 课程添加ActionListener支持,可能类似于......

MainMenu

然后,您可以在创建主课时为public class MainMenu extends JMenuBar { //... public void addActionListener(ActionListener listener) { listenerList.add(ActionListener.class, listener); } public void removeActionListener(ActionListener listener) { listenerList.remove(ActionListener.class, listener); } protected void fireActionPerformed(ActionEvent evt) { ActionListener[] listeners = listenerList.getListeners(ActionListener.class); for (ActionListener listener : listeners) { listener.actionPerformed(evt); } } } 课程注册ActionListener

然后,在MainMenu课程中,您只需拨打Action的{​​{1}}方法

但是,坦率地说,这往往会破坏使用MainMenu的意义,而不是......

你可以......

定义fireActionPerformed和您的主类之间的合约,该合约描述您的“主”类可以执行的预期操作,例如......

Action

然后您的主要类会实现此界面,而您的MainMenu将允许您提供对它的引用(以及可能的其他内容,例如public interface ApplicationAction { public void save(File file); public void open(File file); public void exit(); } s?)

MainMenu

然后在EditAction中,您可以简单地执行所需的功能,例如......

public class MainMenu extends JMenuBar {

    //...

    private ApplicationAction applicationAction;

    //...

    public void setApplicationAction(ApplicationAction applicationAction) {
        this.applicationAction = applicationAction;
    }

    public ApplicationAction getApplicationAction() {
        return applicationAction;
    }

}

你可以......

只需创建Action类而无需public class OpenAction extends AbstractAction { private ApplicationAction applicationAction; public OpenAction(ApplicationAction applicationAction) { this.applicationAction = applicationAction; } @Override public void actionPerformed(ActionEvent e) { // Use a JFileChooser to allow the user to select the file if (action == JFileChooser.APPROVE_OPTION) { File selectedFile = fileChooser.getSelectedFile(); applicationAction.open(selectedFile); } } } 类,并使用工厂或构建器模式构建Action的实例,并使用您需要的MainMenu