我正在深入研究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);
答案 0 :(得分:1)
您可以使用Observer Pattern。
步骤:
使用以下方法将 Observer 添加到 Observables :
addObserver();
如果您希望收到通知,请致电:
setChanged();
notifyObservers();
在 Observers 上实施 update()方法,因为在发生通知时将调用此方法。
此处还阅读了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中。
答案 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