GVKun编程网logo

JMenu ActionListener

7

在这篇文章中,我们将为您详细介绍JMenuActionListener的内容。此外,我们还会涉及一些关于action和actionListener之间的区别、ActionListener关键字、Act

在这篇文章中,我们将为您详细介绍JMenu ActionListener的内容。此外,我们还会涉及一些关于action 和 actionListener 之间的区别、ActionListener关键字、ActionListener如何工作?、ActionListener未实现的知识,以帮助您更全面地了解这个主题。

本文目录一览:

JMenu ActionListener

JMenu ActionListener

我想知道是否可以测试是否单击了JMenu(而不是JMenuItem)。我尝试向其中添加一个ActionListener,但似乎无法识别它。我只需要它在按下JMenu按钮时执行一个操作,以便可以在打开菜单之前更改该菜单的JMenuItems。也欢迎所有取得这一结果的工作!

谢谢

答案1

小编典典
  • 对于JMenu使用MenuListener

import java.awt.*;import java.awt.event.*;import javax.swing.*;import javax.swing.event.*;public class ActionExample {    public ActionExample() {        JMenu menu = new JMenu("Menu");        menu.setMnemonic(KeyEvent.VK_M);        menu.addMenuListener(new SampleMenuListener());        JMenu menu1 = new JMenu("Tool");        menu1.setMnemonic(KeyEvent.VK_T);        menu1.addMenuListener(new SampleMenuListener());        JFrame f = new JFrame("ActionExample");        JMenuBar mb = new JMenuBar();        mb.add(menu);        mb.add(menu1);        f.setJMenuBar(mb);        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);        f.pack();        f.setLocationRelativeTo(null);        f.setVisible(true);    }    public static void main(String[] args) {        EventQueue.invokeLater(new Runnable() {            @Override            public void run() {                ActionExample actionExample = new ActionExample();            }        });    }}class SampleMenuListener implements MenuListener {    @Override    public void menuSelected(MenuEvent e) {        System.out.println("menuSelected");    }    @Override    public void menuDeselected(MenuEvent e) {        System.out.println("menuDeselected");    }    @Override    public void menuCanceled(MenuEvent e) {        System.out.println("menuCanceled");    }}
  • JMenuItem仅用于ButtonModel

action 和 actionListener 之间的区别

action 和 actionListener 之间的区别

actionactionListener 什么区别,什么时候应该使用 actionactionListener


#1 楼

在调用 Action 并确定下一页的位置之前,将首先触发 ActionListener 并提供修改响应的选项。

如果您在同一页面上有多个按钮,这些按钮应该移至相同的位置,但执行的操作略有不同,则可以为每个按钮使用相同的 Action,但使用不同的 ActionListener 处理稍微不同的功能。

这是描述关系的链接:

http://www.java-samples.com/showtutorial.php?tutorialid=605


#2 楼

actionListener

如果您想执行实际业务操作之前有一个钩子请使用 actionListener ,例如将其记录和 / 或设置其他属性(通过 <f:setPropertyActionListener> ),和 / 或访问调用了动作(可通过 ActionEvent参数获得)。 因此,纯粹是为了在调用实际业务操作之前进行准备。

默认情况下, actionListener 方法具有以下签名:

import javax.faces.event.ActionEvent;
// ...

public void actionListener(ActionEvent event) {
    // ...
}

并且应该声明为以下内容,并且不带任何方法括号:

<h:commandXxx ... actionListener="#{bean.actionListener}" />

请注意,EL 2.2 无法传递其他参数。 但是,您可以通过传递并指定自定义参数来完全覆盖 ActionEvent 参数。 以下示例是有效的:

<h:commandXxx ... actionListener="#{bean.methodWithoutArguments()}" />
<h:commandXxx ... actionListener="#{bean.methodWithOneArgument(arg1)}" />
<h:commandXxx ... actionListener="#{bean.methodWithTwoArguments(arg1, arg2)}" />
public void methodWithoutArguments() {}
public void methodWithOneArgument(Object arg1) {}
public void methodWithTwoArguments(Object arg1, Object arg2) {}

请注意无参数方法表达式中括号的重要性。 如果不存在,JSF 仍将期望带有 ActionEvent 参数的方法。

如果您使用的是 EL 2.2+,则可以通过 <f:actionListener binding> 声明多个动作侦听器方法。

<h:commandXxx ... actionListener="#{bean.actionListener1}">
    <f:actionListener binding="#{bean.actionListener2()}" />
    <f:actionListener binding="#{bean.actionListener3()}" />
</h:commandXxx>
public void actionListener1(ActionEvent event) {}
public void actionListener2() {}
public void actionListener3() {}

注意在 binding 属性中括号的重要性。 如果不存在,EL 会令人困惑地抛出 javax.el.PropertyNotFoundException: Property ''actionListener1'' not found on type com.example.Bean ,因为默认情况下, binding 属性被解释为值表达式,而不是方法表达式。 添加 EL 2.2 + 样式括号会透明地将值表达式转换为方法表达式。 另请参见 ao 如果 JSF 不支持 <f:actionListener> 为何可以将它绑定到任意方法?


行动

如果要执行业务操作并在必要时处理导航,请使用 actionaction 方法可以(因此不是必须)返回一个 String ,它将用作导航案例的结果(目标视图)。 返回值 nullvoid 将使其返回同一页面并使当前视图范围保持活动状态。 空字符串或相同视图 ID 的返回值也将返回到同一页面,但是将重新创建视图作用域,从而销毁任何当前活动的视图作用域 Bean,并在适用时重新创建它们。

action 方法可以是任何有效的 MethodExpression ,也可以是使用 EL 2.2 自变量的方法,例如:

<h:commandXxx value="submit" action="#{bean.edit(item)}" />

使用此方法:

public void edit(Item item) {
    // ...
}

请注意,当您的操作方法仅返回一个字符串时,您也可以只在 action 属性中确切指定该字符串。 因此,这非常笨拙:

<h:commandLink value="Go to next page" action="#{bean.goToNextpage}" />

通过这种无意义的方法,可以返回一个硬编码的字符串:

public String goToNextpage() {
    return "nextpage";
}

相反,只需将该硬编码字符串直接放在属性中:

<h:commandLink value="Go to next page" action="nextpage" />

请注意,这反过来表明设计不好:通过 POST 导航。 这既不是用户也不是 SEO 友好。 在何时应该使用 h:outputLink 代替 h:commandLink 进行解释? 并且应该解决为

<h:link value="Go to next page" outcome="nextpage" />

另请参见如何在 JSF 中导航? 如何使 URL 反映当前页面(而不是上一页) 。


f:ajax 监听器

自 JSF 2.x 以来,存在第三种方法,即 <f:ajax listener>

<h:commandXxx ...>
    <f:ajax listener="#{bean.ajaxListener}" />
</h:commandXxx>

默认情况下, ajaxListener 方法具有以下签名:

import javax.faces.event.AjaxBehaviorEvent;
// ...

public void ajaxListener(AjaxBehaviorEvent event) {
    // ...
}

在 Mojarra 中, AjaxBehaviorEvent 参数是可选的,下面的效果很好。

public void ajaxListener() {
    // ...
}

但是在 MyFaces 中,它将抛出 MethodNotFoundException 。 当您想省略参数时,下面的方法在两种 JSF 实现中均有效。

<h:commandXxx ...>
    <f:ajax execute="@form" listener="#{bean.ajaxListener()}" render="@form" />
</h:commandXxx>

Ajax 侦听器在命令组件上并不是真正有用。 它们在输入和选择组件 <h:inputXxx> / <h:selectXxx> 。 在命令组件中,只需坚持使用 action 和 / 或 actionListener 获得清晰性和更好的自记录代码。 此外,像 actionListener 一样, f:ajax listener 器不支持返回导航结果。

<h:commandXxx ... action="#{bean.action}">
    <f:ajax execute="@form" render="@form" />
</h:commandXxx>

有关 executerender 属性的说明,请转到了解 PrimeFaces 流程 / 更新和 JSF f:ajax 执行 / 渲染属性 。


调用顺序

始终以与在视图中声明并附加到组件的顺序相同的顺序在 action 之前调用 actionListener 。 始终任何操作侦听器之前调用 f:ajax listener 器。 因此,以下示例:

<h:commandButton value="submit" actionListener="#{bean.actionListener}" action="#{bean.action}">
    <f:actionListener type="com.example.ActionListenerType" />
    <f:actionListener binding="#{bean.actionListenerBinding()}" />
    <f:setPropertyActionListener target="#{bean.property}" value="some" />
    <f:ajax listener="#{bean.ajaxListener}" />
</h:commandButton>

将按以下顺序调用方法:

  1. Bean#ajaxListener()
  2. Bean#actionListener()
  3. ActionListenerType#processAction()
  4. Bean#actionListenerBinding()
  5. Bean#setProperty()
  6. Bean#action()

异常处理

actionListener 支持一个特殊的异常: AbortProcessingException 。 如果从 actionListener 方法抛出此异常,那么 JSF 将跳过所有剩余的动作侦听器和该动作方法,并继续直接呈现响应。 您将不会看到错误 / 异常页面,但是 JSF 会将其记录下来。 每当从 actionListener 抛出任何其他异常时,也将隐式完成此操作。 因此,如果由于业务异常而打算通过错误页面来阻止该页面,那么您肯定应该在 action 方法中执行该作业。

如果使用 actionListener 的唯一原因是让 void 方法返回同一页面,那么那是一个不好的选择。 与某些 IDE 通过 EL 验证让您相信的相反, action 方法也可以完美地返回 void 。 请注意, PrimeFaces 展示示例在所有地方都散布着这种 actionListener 。 这确实是错误的。 不要以此为借口自己做。

但是,在 ajax 请求中,需要特殊的异常处理程序。 这与是否使用 <f:ajax> listener 属性无关。 有关说明和示例,请转到 JSF ajax request 中的异常处理 。


#3 楼

正如 BalusC 指出的 actionListener ,默认情况下, actionListener 吞下异常,但是在 JSF 2.0 中,还有更多的东西。 即,它不仅吞咽和记录日志,而且实际上发布了异常。

这是通过这样的调用发生的:

context.getApplication().publishEvent(context, ExceptionQueuedEvent.class,                                                          
    new ExceptionQueuedEventContext(context, exception, source, phaseId)
);

此事件的默认侦听器是 ExceptionHandler ,对于 Mojarra 它将设置为 com.sun.faces.context.ExceptionHandlerImpl 。 此实现基本上将抛出任何异常,除非它涉及记录的 AbortProcessingException。 ActionListener 将客户代码引发的异常包装在 AbortProcessingException 中,该异常解释了为什么始终记录这些异常。

但是,可以在 faces-config.xml 中使用自定义实现替换此 ExceptionHandler

<exception-handlerfactory>
   com.foo.myExceptionHandler
</exception-handlerfactory>

除了全局监听之外,单个 bean 也可以监听这些事件。 以下是这一概念的证明:

@ManagedBean
@RequestScoped
public class MyBean {

    public void actionMethod(ActionEvent event) {

        FacesContext.getCurrentInstance().getApplication().subscribeToEvent(ExceptionQueuedEvent.class, new SystemEventListener() {

        @Override
        public void processEvent(SystemEvent event) throws AbortProcessingException {
            ExceptionQueuedEventContext content = (ExceptionQueuedEventContext)event.getSource();
            throw new RuntimeException(content.getException());
        }

        @Override
        public boolean isListenerForSource(Object source) {
            return true;
        }
        });

        throw new RuntimeException("test");
    }

}

(请注意,这不是通常应该编写侦听器的方式,这只是出于演示目的!)

从 Facelet 这样调用:

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core">
    <h:body>
        <h:form>
            <h:commandButton value="test" actionListener="#{myBean.actionMethod}"/>
        </h:form>
    </h:body>
</html>

将导致显示错误页面。


#4 楼

TL; DR

ActionListener (可以有多个)以 action 之前注册的顺序执行

长答案

业务 action 通常会调用 EJB 服务,并且如果不是您正在执行的 actionListener 则业务 action 通常会调用最终服务和 / 或导航到其他视图 actionListener 更适合,即当用户与组件交互时,例如 h:commandButtonh:link 可以通过在 UI Component 的 actionListener 属性中传递托管 bean 方法的名称来实现,也可以通过实现 ActionListener 接口并将实现类名称传递给 UI Component 的 actionListener 属性来进行处理。

ActionListener关键字

ActionListener关键字

    

addActionListener

public void ( l)
添加指定的动作侦听器,以接收发自此按钮的动作事件。当用户在此按钮上按下或释放鼠标时,发生动作事件。如果 l 为 null,则不抛出任何异常,也不执行任何动作。
  • 方法摘要 void actionPerformed(ActionEvent e) 
    发生操作时调用。

 

 ActionListener是java中关于事件处理的一个接口,继承自EventListener。用于接收操作事件的侦听器接口.

        Java Swing组件自动产生各种事件来响应用户行为。如当用户点击按钮或选择菜单项目时,Swing组件会产生一个 ActionEvent.

        Java Swing中处理各组件事件的一般步骤是:
  
  1. 新建一个组件(如JButton)。
  
  2. 将该组件添加到相应的面板(如JPanel)。
  
  3. 注册监听器以监听事件源产生的事件(如通过ActionListener来响应用户点击按钮)。
  
  4. 定义处理事件的方法(如在ActionListener中的actionPerformed中定义相应方法)。
  
  以上步骤我们可以用多种方法实现。但人们通常用二种方法。第一种方法是只利用一个监听器以及多个if语句来决定是哪个组件产生的事件;第二种方法是使用多个内部类来响应不同组件产生的各种事件,其具体实现又分两种方式,一种是匿名内部类,一种是一般内部类。

actionlistener的三种实现方法:

#摘自zenith-lee
/**
  * Simple1.java - 处理事件的第一种方法
  * 在这个例子中,利用一个ActionListener来监听事件源产生的事件
  * 用一些if语句来决定是哪个事件源
  */
  
  
  import java.awt.*;
  import java.awt.event.*;
  import javax.swing.*;
  
  public class Simple1
  {
       private static JFrame frame; // 定义为静态变量以便main使用
       private static JPanel myPanel; // 该面板用来放置按钮组件
       private JButton button1; // 这里定义按钮组件 
       private JButton button2; // 以便让ActionListener使用
   
       public Simple1() // 构造器, 建立图形界面
       {
           // 新建面板
           myPanel = new JPanel();
           // 新建按钮
           button1 = new JButton("按钮1"); // 新建按钮1
           button2 = new JButton("按钮2");
  
           SimpleListener ourListener = new SimpleListener();
          // 建立一个actionlistener让两个按钮共享
           button1.addActionListener(ourListener);
           button2.addActionListener(ourListener);
  
           myPanel.add(button1); // 添加按钮到面板
           myPanel.add(button2);
       }
  
       private class SimpleListener implements ActionListener
       {
       /**
       * 利用该内部类来监听所有事件源产生的事件
       * 便于处理事件代码模块化
       */
           public void actionPerformed(ActionEvent e)
           {
               // 利用getActionCommand获得按钮名称
               // 也可以利用getSource()来实现
               // if (e.getSource() ==button1)
  
               String buttonName = e.getActionCommand();
               if (buttonName.equals("按钮1"))
               JOptionPane.showMessageDialog(frame,
               "按钮1 被点击");
               else if (buttonName.equals("按钮2"))
               JOptionPane.showMessageDialog(frame,
               "按钮2 被点击");
               else
               JOptionPane.showMessageDialog(frame,
               "Unknown event" );
           }
       }
  
       public static void main(String s[])
       {
           Simple1 gui = new Simple1(); // 新建Simple1组件
           
           frame = new JFrame("Simple1"); // 新建JFrame
           // 处理关闭事件的通常方法
           frame.addWindowListener(new WindowAdapter() {
           public void windowClosing(WindowEvent e)
           {System.exit(0);} });
          
           frame.getContentPane().add(myPanel);
           frame.pack(); 
           frame.setVisible(true);
       }
  }
  

    让我们来看看以上代码是如何工作的。在main方法中,我们定义了一个JFrame,然后将面板Jpanel添加到窗体中,该面板包括两个按钮。相应的变量Frame,button1,button2定义在程序的开头部分。
  
  在程序入口main方法中,首先新建Simple1组件,通过构造器建立用户GUI,定义一个面板Jpanle,,增加两个按钮,然后利用 JButton.addActionListerner将两个按钮加入到一个活动监听器SimpleLister中,最后,两个按钮添加到面板。当GUI 建立后,我们将面板添加到窗体并显示结果。当用户点击按钮时,程序调用actionPerformed方法,通过if语句来判断是哪一个按钮被点击,然后在对话框中显示相应的内容。
  
  利用一个监听器来处理事件的缺点是,当程序比较复杂时,需要一大串的if 语句来实现,程序代码较难阅读与维护。当然,如果处理的事件较少,这种方式比较简单。
  
  通过使用匿名内部类可以解决上述存在的问题。使用简单的匿名内部类作为addActionListener的变量即可。以下是实现代码:

 /**
  * Simple2.java - 处理事件的第二种方法
  * 在这个例子中,利用匿名内部类来监听每一个事件源产生的事件
  * 避免使用一些if语句来决定是哪个事件源
  */
  
  import java.awt.*;
  import java.awt.event.*;
  import javax.swing.*;
  
  public class Simple2
  {
       private static JFrame frame; // 定义为静态变量以便main使用
       private static JPanel myPanel; // 该面板用来放置按钮组件
       private JButton button1; // 这里定义按钮组件 
       private JButton button2; // 以便让ActionListener使用
       
       public Simple2() // 构造器, 建立图形界面
       {
           // 新建面板
           myPanel = new JPanel();
           // 新建按钮
           button1 = new JButton("按钮1"); // 新建按钮1
           button2 = new JButton("按钮2");
          
           // 每一个事件源需要一个监听器
           // 定义一个匿名内部类来监听事件源产生的事件
           button1.addActionListener(
               new ActionListener()
               {
                   public void actionPerformed(ActionEvent e)
                   {
                       JOptionPane.showMessageDialog(frame,"按钮1 被点击");
                   }
               }
           );
          
           button2.addActionListener(
               new ActionListener()
               {
                   public void actionPerformed(ActionEvent e)
                   {
                       JOptionPane.showMessageDialog(frame,"按钮2 被点击");
                   }
               }
           );
          
           myPanel.add(button1); // 添加按钮到面板
           myPanel.add(button2);
        }
          
        public static void main(String s[])
        {
            Simple2 gui = new Simple2(); // 新建Simple2组件
                               
            frame = new JFrame("Simple2"); // 新建JFrame
            // 处理关闭事件的通常方法
            frame.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e)
            {System.exit(0);} });
            frame.getContentPane().add(myPanel);
            frame.pack(); 
            frame.setVisible(true);
        }
  }
 

 使用匿名内部类同样存在许多另外的问题。首先,根据组件在代码中被定义的不同位置,类的定义以及处理事件的代码将分散在程序的各个部分,不是集中在一块,同样不便于阅读与维护。各事件的处理全部由嵌套的程序块组成,视觉上很难定位程序代码。如果事件处理程序比较复杂,内部类中的代码将变得很长,你将找不到相应的组件定义位置。最后,当工具栏、菜单栏目等需要处理同样的用户行为时,该方法将使代码更难维护。
  
  我们使用一般的命名内部类可以解决以上许多问题。所有的事件处理方法都集中在一块,并且都具有有意义的名称,程序非常容易阅读与维护。单个的事件处理程序也可以被工具栏、菜单栏等重复使用.

 
 
 
  import  java.awt.*;
   import  java.awt.event.*;
   import  javax.swing.*;
  
   public  class  Simple3
  {
         private  static  JFrame frame;  // 定义为静态变量以便main使用
         private  static  JPanel myPanel;  // 该面板用来放置按钮组件
         private  JButton button1;  // 这里定义按钮组件 
         private  JButton button2;  // 以便让ActionListener使用
        
         // 利用一般内部类来监听每一个事件源产生的事件如(button1, button2)
         private  class  Button1Handler  implements  ActionListener
        {
             public  void  actionPerformed(ActionEvent e)
            {
                JOptionPane.showMessageDialog(frame, "按钮1 被点击" );
            }
        }
        
         private  class  Button2Handler  implements  ActionListener
        {
             public  void  actionPerformed(ActionEvent e)
            {
                JOptionPane.showMessageDialog(frame, "按钮2 被点击" );
            }
        }
        
         public  Simple3()  // // 构造器, 建立图形界面
        {
             // 新建面板
            myPanel =  new  JPanel();
             // 新建按钮
            button1 =  new  JButton( "按钮1" );  // 新建按钮1
            button2 =  new  JButton( "按钮2" );
           
             // 对每一个组件注册监听内部类
            button1.addActionListener( new  Button1Handler());
            button2.addActionListener( new  Button2Handler());
           
            myPanel.add(button1);  // 添加按钮到面板
            myPanel.add(button2);
        }
       
         public  static  void  main(String s[])
        {
            Simple3 gui =  new  Simple3();  // 新建Simple3组件
           
            frame =  new  JFrame( "Simple3" );  // 新建JFrame
             // 处理关闭事件的通常方法 
            frame.addWindowListener( new  WindowAdapter() {
                 public  void  windowClosing(WindowEvent e)
                {System.exit( 0 );} });
           
            frame.getContentPane().add(myPanel);
            frame.pack(); 
            frame.setVisible( true );
        }
  }

 

ActionListener如何工作?

ActionListener如何工作?

我对如何使用动作监听器和实现它们有一个想法,但是我想知道是否有人可以告诉我他们如何监听事件?有某种轮询机制吗?

ActionListener未实现

ActionListener未实现

JFrameWithPanel不是抽象的,并且不会重写java.awt.event.ActionListener公共类中的抽象方法actionPerformed(java.awt.event.ActionEvent)JFrameWithPanel扩展了JFrame实现ActionListener

我没有得到这个代码。Book and Java网站告诉我这是该方法的语法,但是此错误再次不断出现。

import javax.swing.*;
import javax.swing.JOptionPane;
import java.awt.*;
import java.awt.event.*;
import java.lang.Math.*;
import java.lang.Integer.*;
import java.util.*;
import java.util.Random;
import java.io.*;
import java.text.*;
import java.text.DecimalFormat.*;

public class JFrameWithPanel extends JFrame implements ActionListener
{
 JButton button = new JButton("Exit");

 public JFrameWithPanel()
 {
  super("JFrame with Panel");

  JComboBox packageChoice = new JComboBox();
  packageChoice.addItem("A+ Certification");
  packageChoice.addItem("Network+ Certification ");
  packageChoice.addItem("Security+ Certifictation");
  packageChoice.addItem("CIT Full Test Package");

  packageChoice.addActionListener(this);

  setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  JPanel pane = new JPanel();
  pane.add(button);
  pane.add(packageChoice);
  setContentPane(pane);
  setSize(200,100);
  setVisible(true);

 }
}

然后再

public class CreateJFrameWithPanel
{
 public static void main(String[] args)
 {
  JFrameWithPanel panel = new JFrameWithPanel();
 }
}

我们今天的关于JMenu ActionListener的分享就到这里,谢谢您的阅读,如果想了解更多关于action 和 actionListener 之间的区别、ActionListener关键字、ActionListener如何工作?、ActionListener未实现的相关信息,可以在本站进行搜索。

本文标签: