我在使用带有actionListener的匿名内部类时遇到了困难。有人可以向我解释我的代码有什么问题以及如何在actionListener中使用匿名内部类。我正在尝试在一个类中创建菜单栏,在另一个类中创建动作侦听器。当我尝试使用匿名内部类时遇到了一些困难。 java网站不清楚。你可以向我解释一下并帮我修改我的代码。
public class Listener implements ActionListener {
HangmanView hangmanView = new HangmanView();
JFrame dialogFrame = new JFrame();
ImageIcon logo = new ImageIcon("logo.png");
public void listener1() {
hangmanView.getMenuItem().addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {// right click key
JOptionPane.showMessageDialog(dialogFrame, "Developer: Joe"
, "Developer",
JOptionPane.INFORMATION_MESSAGE, logo);
}// end actionPerformed method
});
}
}
另一堂课:
public class HangmanView {
public JMenuItem getMenuItem() {
JMenuItem menuItem = new JMenuItem("Developer", KeyEvent.VK_T);
menuItem.addActionListener(new Listener());
return menuItem;
}
public JMenuBar menuBar() {
JMenuBar menuBar = new JMenuBar();
JMenu menu = new JMenu("File");
menuBar.add(menu);
menu.add(getMenuItem());// return here
return menuBar;
}
答案 0 :(得分:3)
如果您正在尝试为不同的JMenuItem
实现侦听器,那么我要做的是创建一个可用于多个Action
的自定义JMenuItem
类,如JMenuItem
是何时使用Action
的一个很好的例子。
private class MyAction extends AbstractAction {
String name;
public MyAction(String name, Icon icon) {
super(name, icon);
this.name = name;
}
public MyAction(String name, Icon icon, String desc,
Integer mnemonic, KeyStroke accelorator) {
super(name, icon);
putValue(Action.SHORT_DESCRIPTION, desc);
putValue(Action.MNEMONIC_KEY, mnemonic);
putValue(Action.ACCELERATOR_KEY, accelorator);
this.name = name;
}
@Override
public void actionPerformed(ActionEvent e) {
switch (name) {
case "menu1Action":
// do something for menuItem1
break;
case "menu2Action":
// do something for menuItem2
break;
case "menu3Action":
// do something for menuItem3
break;
}
}
}
将此类作为HangmanView
的内部类。然后,您可以为每个Action
创建此自定义JMenuItem
类的实例。这是一个例子
Action menu1Action = new MyAction(
/* arg 1 */ "menu1Action",
/* arg 2 */ someIcon,
/* arg 3 */ "Some Short description of the action",
/* arg 4 */ new Integer(KeyEvent.VK_T),
/* arg 5 */ KeyStroke.getKeyStroke(KeyEvent.VK_T, ActionEvent.CTRL_MASK));
当您向Action
添加JMenu
时,Action
的标题将自动按照您在JMenu
中的显示放置。因此,您只需将此自定义Action
添加到JMenu
即可。您根本不必实际创建JMenuItem
。 Action
将替代JMenuItem
。只需将所有MyAction
个对象添加到JMenu
。
menu.add(menu1Action);
我遗漏的是switch case
中每个单独actionPerformed
的实施。 case
将是您在构造函数中命名action
的内容。因为我将Action
命名为“menu1Action”,所以我应该在switch case中有相应的名称。在这种情况下,当您点击或通过键盘访问JOptionPane
时,您可以执行JMenuItem
或其他您希望执行的操作。
使用Action
的另一个好处是它可以用于多种用途。使用您创建的相同MyAction menu1Action
,您可以对Action
使用相同的JToolBar
。如果不对上述menu1Action
进行任何更改,您可以这样做:
JTooBar toolbar = new JToolBar();
toolbar.add(menu1Action);
现在,在工具栏和菜单项中,您可以执行相同的操作。工具栏仅显示图标而不显示名称。
这是一个例子。我所做的是创建三个不同的MyAction
对象。一个用于左对齐,一个用于中心对齐,一个用于右对齐。这三个动作分别用于三个独立的组件,一个菜单项,一个收费栏和一个按钮
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ActionInterfaceDemo extends JFrame {
static JPanel buttonPanel = new JPanel();
static FlowLayout flowLayout = new FlowLayout();
public ActionInterfaceDemo(){
ImageIcon centerIcon = new ImageIcon(
ActionInterfaceDemo.class.getResource("image/centeralignment.png"));
ImageIcon rightIcon = new ImageIcon(
ActionInterfaceDemo.class.getResource("image/rightalignment.png"));
ImageIcon leftIcon = new ImageIcon(
ActionInterfaceDemo.class.getResource("image/leftalignment.png"));
Action leftAction = new MyAction("Left", leftIcon,
"Left alignment for the buttons in the panel",
new Integer(KeyEvent.VK_L),
KeyStroke.getKeyStroke(KeyEvent.VK_L, ActionEvent.CTRL_MASK));
Action rightAction = new MyAction("Right", rightIcon,
"Right alignment for the buttons in the panel",
new Integer(KeyEvent.VK_R),
KeyStroke.getKeyStroke(KeyEvent.VK_R, ActionEvent.CTRL_MASK));
Action centerAction = new MyAction("Center", centerIcon,
"Center alignment for the buttons in the panel",
new Integer(KeyEvent.VK_C),
KeyStroke.getKeyStroke(KeyEvent.VK_C, ActionEvent.CTRL_MASK));
JMenuBar menuBar = new JMenuBar();
JMenu menuAlignment = new JMenu("Alignment");
setJMenuBar(menuBar);
menuBar.add(menuAlignment);
menuAlignment.add(leftAction);
menuAlignment.add(centerAction);
menuAlignment.add(rightAction);
JToolBar toolBar = new JToolBar("Alignment");
toolBar.setBorder(BorderFactory.createLineBorder(Color.BLUE));
toolBar.add(leftAction);
toolBar.add(centerAction);
toolBar.add(rightAction);
buttonPanel.setLayout(flowLayout);
JButton jbtLeft = new JButton(leftAction);
JButton jbtCenter = new JButton(centerAction);
JButton jbtRight = new JButton(rightAction);
buttonPanel.add(jbtLeft);
buttonPanel.add(jbtCenter);
buttonPanel.add(jbtRight);
add(toolBar, BorderLayout.EAST);
add(buttonPanel, BorderLayout.CENTER);
pack();
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
public void run(){
new ActionInterfaceDemo();
}
});
}
private class MyAction extends AbstractAction {
String name;
public MyAction(String name, Icon icon, String desc,
Integer mnemonic, KeyStroke accelorator) {
super(name, icon);
putValue(Action.SHORT_DESCRIPTION, desc);
putValue(Action.MNEMONIC_KEY, mnemonic);
putValue(Action.ACCELERATOR_KEY, accelorator);
this.name = name;
}
@Override
public void actionPerformed(ActionEvent e) {
switch (name) {
case "Left":
flowLayout.setAlignment(FlowLayout.LEFT);
break;
case "Right":
flowLayout.setAlignment(FlowLayout.RIGHT);
break;
case "Center":
flowLayout.setAlignment(FlowLayout.CENTER);
break;
}
buttonPanel.revalidate();
}
}
}
您可以在菜单,工具栏或按钮中按“向左”,它们将产生相同的结果,因为它们来自相同的Action
。
以下是我想要测试的图像
注意您不必使用这些完全构造函数中的任何一个。您可以使用不同的参数创建自己的参数。这只是我喜欢使用的一个自定义的。
答案 1 :(得分:0)
Listener
,通过其继承层次结构为ActionListener
,
public class Listener implements ActionListener {
需要实现actionPerfomed(ActionEvent)
方法
@Override
public void actionPerformed(ActionEvent e) {
// implement it
}
但是,由于您似乎要添加匿名ActionListener
,因此请不要使用Listener
类实现ActionListener
。删除那一点。
答案 2 :(得分:0)
您的面向对象编程已遍布各处。您在OP中的代码看起来应该是某种GUI,不同的类以某种方式协同工作,但它只是在整个地方创建新对象。它有太多原因无效。我建议你坚持一些简单的事情,直到你更好地掌握这一切是如何运作的。
在你的另一个问题中,你也有一个非常好的建议,就像这个很多,但你并没有真正遵循它。你的代码完全不同。
这是一个非常基本的GUI。你有一个对象,其中包含所有字段。一切都在一个地方。包含对象是侦听器,并根据事件源决定要执行的操作。你应该坚持使用这样的设计,直到你对OOP更加熟悉。
public class HangmanView
implements ActionListener {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new HangmanView().setFrameVisible(true);
}
});
}
private JFrame theFrame = new JFrame("Main Window");
private JPanel theContent = new JPanel();
private JMenuBar theBar = new JMenuBar();
private JMenu fileMenu = new JMenu("File");
private JMenuItem exitMenuItem = new JMenuItem("Exit");
private JMenuItem devMenuItem = new JMenuItem("Developer");
public HangmanView() {
assert SwingUtilities.isEventDispatchThread();
exitMenuItem.addActionListener(this);
devMenuItem.addActionListener(this);
fileMenu.add(exitMenuItem);
theBar.add(fileMenu);
theBar.add(devMenuItem);
theContent.setPreferredSize(new Dimension(500, 500));
theFrame.setJMenuBar(theBar);
theFrame.setContentPane(theContent);
theFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
theFrame.pack();
theFrame.setLocationRelativeTo(null);
}
public void setFrameVisible(boolean vis) {
theFrame.setVisible(vis);
}
@Override
public void actionPerformed(ActionEvent ae) {
if(ae.getSource() == devMenuItem) {
showDevDiag();
} else if(ae.getSource() == exitMenuItem) {
systemExit();
}
}
private void showDevDiag() {
JOptionPane.showMessageDialog(
theFrame,
"Developer: Joe",
"Developer",
JOptionPane.INFORMATION_MESSAGE,
null
);
}
private void systemExit() {
System.exit(0);
}
}
答案 3 :(得分:0)
如果我应该使用匿名类,那应该做什么:
public static void main(String args[]){
/*bla bla bla...*/
JButton button1=new JButton("button1");
button1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae){
/*bla bla bla...*/
}
};
}
另一方面,我总是这样做:
public class Class implements Runnable,ActionListener
{
private static Map<Thread,ActionEvent> THREAD_ATTRIB
=new HashMap<Thread,ActionEvent> (0);
JButton button1=new JButton("button1");
JButton button2=new JButton("button2");
//constructor
public Class(){
this.button1.addActionListener(this);
this.button2.addActionListener(this);
}
@Override
public void actionPerformed(ActionEvent ae){
Thread thread=new Thread(this);
THREAD_ATTRIB.put(thread,ae);
thread.start();
}
@Override
public void run(){
ActionEvent ae=THREAD_ATTRIB.get(Thread.currentThread());
if(ae!=null){
Object source=ae.getSource();
if(source.equals(this.button1){
/*bla bla bla...*/
} else if(source.equals(this.button2){
/*bla bla bla...*/
}
} else{
/*bla bla bla...*/
}
}
}