我应该在哪里放置事件监听器?

我制作了许多对象,例如 JButton、JLabel、JCheckBox 等。我已经为对象添加了一个事件侦听器。像这样。对象 obj = new obj(); obj.listneraddActionListener(){}; 但是,如果侦听器使用其他对象,则必须在侦听器代码之前创建该对象。我在考虑是提前排序对象定义还是把所有监听拉到下面。我该怎么办?


编辑:对不起,我没有发布,因为代码太大了。以下是代码的一部分。我从复选框(chkName、chkAddress、chkType、chkComment)中收到错误消息


    JButton btnSearch = new JButton("");

    btnSearch.addActionListener(new ActionListener() {

        public void actionPerformed(ActionEvent arg0) {             

            String str = "";

            ResultSet rsSid, rsNM = null;

            int count = 0;


            if (chkName.isSelected()) {str += "(SELECT " + tableName + "_SID FROM " + tableName + " WHERE " + tableName + "_NM LIKE '%" + txtSearch.getText() + "%') UNION "; ++count;}

            if (chkAddress.isSelected()) {str += "(SELECT " + tableName + "_SID FROM " + tableName + " WHERE " + "ADDR LIKE '%" + txtSearch.getText() +"%') UNION "; ++count;}

            if (chkType.isSelected()) {str += "(SELECT " + tableName + "_SID FROM " + tableName + " WHERE " + "TYPE LIKE '%" + txtSearch.getText() +"%') UNION "; ++count;}

            if (chkComment.isSelected()) {str += "(SELECT " + tableName + "_SID FROM " + tableName + " WHERE " + "COMMENT LIKE '%" + txtSearch.getText() +"%') UNION "; ++count;}

            if (count == 0) return;


            if (txtSearch.getText() != "")

                str = str.substring(0, str.length() - 7) + ';';

            else

                str = "SELECT * FROM " + tableName;


            rsSid = jdbc.executeQuery(conn, str);

            try {

                behindList.clear();

                lstSRmodel.clear();

                TableSummary temp = new TableSummary();

                while(rsSid.next()) {

                    for (int i = 1; i <= rsSid.getMetaData().getColumnCount(); ++i) {

                        temp.TABLE_SID = rsSid.getInt(i);

                        

            }

        }

    });


   

呼啦一阵风
浏览 167回答 2
2回答

蝴蝶刀刀

您应该拆分您ActionListener和您的业务代码:您不应该执行长时间运行的查询,ActionListener因为它会通过阻止 EDT(事件调度线程)来冻结您的应用程序。在处理 Swing(或其他框架,如 Java FX、SWT 等)时,我最好执行以下操作:创建 GUI 组件,例如字段,...配置或“初始化”布局,即将组件添加到它们的父级等等配置任何事件监听器那将是(如果您愿意,可以将“init”替换为“configure”):private JCheckBox checkBox;MyClass() { // constructor&nbsp; this.init();}void init() {&nbsp; initComponents();&nbsp; initEventListeners();}void initComponents() {&nbsp; this.checkBox = new JCheckBox("..."); // or in the constructor if you want final field.&nbsp; // layout for the parent component&nbsp;&nbsp; this.add(new JLabel("Label 1"));&nbsp; this.add(checkBox);}void initEventListeners() {&nbsp; this.checkBox.addActionListener(System.out::println);}此外,如果附加到 Swing 组件的事件是 lambda 或匿名类,则应尽可能简单:相反,创建一个私有方法并使用其引用:&nbsp; btnSearch.addActionListener(this::searchActionListener);以及我使用另一个线程 ( ForkJoinPool.commonPool()) 在 EDT(事件调度线程)之外执行长时间运行的工作的方法。否则,界面将被冻结。业务方法在外部完成,在另一个对象(business此处称为)中。应该禁用搜索按钮,否则用户(在那种情况下)可能会向按钮发送垃圾邮件,从而导致数据库出现不必要的问题......private void searchActionListener(ActionEvent event) {&nbsp; &nbsp; btnSearch.setEnabled(false);&nbsp; // user should not be able to search while it's running&nbsp; &nbsp; // extract Swing data before running outside the EDT&nbsp; &nbsp; String query = txtSearch.getText()&nbsp; &nbsp; boolean useName = chkName.isSelected();&nbsp; &nbsp; boolean useAddress = chkAddress.isSelected();&nbsp; &nbsp; // ... and so on&nbsp; &nbsp; // do work OUTSIDE the EDT&nbsp; &nbsp; ForkJoinPool.commonPool().execute(() -> {&nbsp; &nbsp; &nbsp; Result result = business.find(query, useName, useAddress);&nbsp; &nbsp; &nbsp; SwingUtilities.invokeLater(() -> {&nbsp; &nbsp; &nbsp; &nbsp; processResult(result); // do whatever is needed&nbsp; &nbsp; &nbsp; &nbsp; btnSearch.setEnabled(true);&nbsp; &nbsp; &nbsp; });&nbsp; &nbsp; });&nbsp; }如您所见,如果您在chkName事件侦听器之前创建了 Swing 组件 ( , ...) ,则您可能不会在方法中引用它们:您应该将它们创建为类的字段而不是变量。否则,您必须在事件侦听器之前创建它们。此外,虽然问题中没有讨论,但您应该重写查询,因为您正在注入 SQL:"(SELECT " + tableName + "_SID FROM " + tableName + " WHERE " + tableName + "_NM LIKE '%" + txtSearch.getText() + "%') UNION ";'%" + txtSearch.getText() + "%'应该替换为?并且您应该使用 PreparedStatement 来传递参数而不是注入它。

梦里花落0921

我不确定您是否读过这篇文章,但我会先阅读 The Java™ Tutorials on Writing Event Listeners。当我学习如何正确处理 GUI 事件时,本教程对我帮助很大。因为要处理的事件太多,所以 Java 提供了EventListener没有方法的调用的主要接口(这就是所谓的标记接口)。每个都JComponent定义了它必须处理的事件类型。例如,JButton对象关注的事件集与JFrame对象不同。你能做的最好的事情就是理解为什么需要这个 API 的基本前提。GUI 必须是事件驱动的,因为没有有效的方法可以在操作发生的那一刻捕获用户交互。例如,一个JButton对象必须至少监听“点击”事件。这对你来说应该是显而易见的。但还有一些您可能没有想到的其他事件。例如,将鼠标悬停在按钮上以显示工具提示。对于你的问题,如果侦听器使用其他对象,则必须在侦听器代码之前创建该对象......我应该为此做什么?有几种方法可以处理这个问题。我将向您展示非常简单的案例,希望您可以使用这些案例进行扩展。假设您有一个带有两个按钮的面板,OK 和 Cancel。显然,您知道这两个按钮在单击时将执行不同的功能。对于这个例子,他们将要做的工作是无关紧要的。因此,我将在单击时打印出一些消息。下面的代码片段仅显示相关部分。要处理按钮点击,您必须ActionListener向每个按钮添加 。public class MyActionListener implements ActionListener {&nbsp; &nbsp; public void actionPerformed(ActionEvent e) {&nbsp; &nbsp; &nbsp; &nbsp; JButton button = (JButton)e.getSource();&nbsp; &nbsp; &nbsp; &nbsp; String name = button.getName(); // Assuming you set "OK" and "Cancel" as the names&nbsp; &nbsp; &nbsp; &nbsp; if (name.equals("OK")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; System.out.println("I will comply with your command!");&nbsp; &nbsp; &nbsp; &nbsp; else&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; System.out.println("You cancelled your request.");&nbsp; &nbsp; }}然后,您可以像这样向您的按钮添加一个侦听器......MyActionListener listener = new MyActionListener();cancelBtn.addActionListener(listener);okBtn.addActionListener(listener);该解决方案应该可以正常工作,但扩展性不是很好。如果您要向您的应用程序添加更多按钮,那么只有一个这样的侦听器是不好的,因为您的侦听器会变得过度工作。稍微好一点的解决方案是为每个实例提供自己的侦听器。您可以利用匿名类来做到这一点。这是如何做:cancelBtn.addActionListener(new MyActionListener(){&nbsp; &nbsp; public void actionPerformed(ActionEvent e) {&nbsp; &nbsp; &nbsp; &nbsp; System.out.println("I will comply with your command!");&nbsp; &nbsp; }});okBtn.addActionListener(new MyActionListener(){&nbsp; &nbsp; public void actionPerformed(ActionEvent e) {&nbsp; &nbsp; &nbsp; &nbsp; System.out.println("You cancelled your request.");&nbsp; &nbsp; }});有些人不太喜欢匿名类,因为它会影响代码的可读性。我碰巧喜欢这样一个事实,即每个对象的实例都有自己的个性化侦听器,它可以准确地完成对象实例在操作发生时需要完成的工作。我认为这种方法应该适用于您的情况。还有其他方法,但我认为您应该开始使用这种简单的方法,直到您获得更多关于如何处理事件的知识。让我知道你的想法。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java