Where should I place the event listener?

Y X :

I made many of objects such as JButton, JLabel, JCheckBox, etc. And I've added an event listener to the object. Like this. object obj = new obj(); obj.listneraddActionListener(){}; However, if listener uses other objects, that objects must be created before listener code. I'm thinking about whether I should sort object definition in advance or pull all listeners to below. What should I do for this?

Edit:: I'm sorry, I didn't post because the code was too big. the below is part of the code. I got error message from checkboxes(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);
                        rsNM = jdbc.executeQuery(conn, "SELECT " + tableName + "_NM FROM " + tableName + " WHERE " + tableName + "_SID = " + temp.TABLE_SID + ";");
                        if (rsNM.next()) {
                            temp.TABLE_NM = rsNM.getString(1);
                            behindList.add(new TableSummary(temp.TABLE_SID, temp.TABLE_NM));
                            lstSRmodel.addElement(temp.TABLE_NM);
                        }
                    }
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    });

    JCheckBox chkAll = new JCheckBox("\uC804\uCCB4");

    chkAll.setBounds(14, 75, 131, 27);
    contentPane.add(chkAll);

    JCheckBox chkName = new JCheckBox("\uC774\uB984");
    chkName.setBounds(14, 106, 131, 27);
    contentPane.add(chkName);

    JCheckBox chkAddress = new JCheckBox("\uC704\uCE58");
    chkAddress.setBounds(14, 137, 131, 27);
    contentPane.add(chkAddress);

    JCheckBox chkType = new JCheckBox("\uD0C0\uC785");
    chkType.setBounds(14, 168, 131, 27);
    contentPane.add(chkType);

    JCheckBox chkComment = new JCheckBox("\uC138\uBD80\uC0AC\uD56D");
    chkComment.setBounds(14, 199, 131, 27);
    contentPane.add(chkComment);
NoDataFound :

You should split your ActionListener and your business code: your should not execute a long running query in an ActionListener because it would freeze your application by blocking the EDT (Event Dispatch Thread).

I would preferably do the following when dealing with Swing (or other framework such as Java FX, SWT, ...):

  • Create GUI component such as field, ...
  • Configure or "init" the layout, that is add the component to their parent and so on
  • Configure any event listener

That would be (replace "init" by "configure" if you prefer):

private JCheckBox checkBox;

MyClass() { // constructor
  this.init();
}

void init() {
  initComponents();
  initEventListeners();
}

void initComponents() {
  this.checkBox = new JCheckBox("..."); // or in the constructor if you want final field.

  // layout for the parent component 
  this.add(new JLabel("Label 1"));
  this.add(checkBox);
}

void initEventListeners() {
  this.checkBox.addActionListener(System.out::println);
}

Also, event you attach to a Swing component should be kept as simple as possible if they are lambda or anonymous classes: instead, create a private method and use its reference:

  btnSearch.addActionListener(this::searchActionListener);

And the method in which I use another thread (ForkJoinPool.commonPool()) to execute long running work outside the EDT (Event Dispatch Thread). Otherwise, the interface would be frozen. The business method is done outside, in another object (called business here).

The search button should be disabled, otherwise the user (in that case) could spam the button leading to unwanted issues on the database...

private void searchActionListener(ActionEvent event) {
    btnSearch.setEnabled(false);  // user should not be able to search while it's running

    // extract Swing data before running outside the EDT
    String query = txtSearch.getText()
    boolean useName = chkName.isSelected();
    boolean useAddress = chkAddress.isSelected();
    // ... and so on

    // do work OUTSIDE the EDT
    ForkJoinPool.commonPool().execute(() -> {
      Result result = business.find(query, useName, useAddress);
      SwingUtilities.invokeLater(() -> {
        processResult(result); // do whatever is needed
        btnSearch.setEnabled(true);
      });
    });
  }

As you can see, if you created your Swing component (chkName, ...) before the event listener, you may not reference them in the method: you should create them as field to the class rather than as variable.

Otherwise, you're bound to create them before the event listener.

Also, while not discussed in the question, you should rewrite your query because your are injecting SQL:

"(SELECT " + tableName + "_SID FROM " + tableName + " WHERE " + tableName + "_NM LIKE '%" + txtSearch.getText() + "%') UNION ";

The '%" + txtSearch.getText() + "%' should be replaced by ? and you should use a PreparedStatement to pass parameter rather than injecting it.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=128880&siteId=1