2

I have an application that has sheep entries on a JTable. Sheep can be made children of other sheep by selecting an id from the JComboBox editor of the parent id column in the JTable. To do that, the parent id JComboBox must scan the ids of other sheep and eliminate some of them as expected and show them together in its popup.

This is not a time consuming process; but in my opinion in the future if the sheep count rises, then it may cause the GUI become unresponsive. That's why I wanted to use a SwingWorker for the scan process. It would be good if it scanS ids in doInBackground method and return these ids to done method.

So JComboBox would show any possible parent ids. Although doInBackground method works well in done method, when I add a number to JComboBox, I guess it makes popup become invisible.

Because of this whenever I click the cell of parent ıd JComboBox pupup appears and disappears quickly without showing any parent ids. But it must show parent ids. Is there any way to do that?

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package sheepfarm.tools;

import java.awt.Component;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.ArrayList;
import java.util.Vector;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.AbstractCellEditor;
import javax.swing.JComboBox;
import javax.swing.JTable;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import javax.swing.table.TableCellEditor;
import org.joda.time.Interval;
import java.util.Date;
import javax.swing.DefaultComboBoxModel;
import javax.swing.SwingWorker;

/**
 *
 * @author Personal Computer
 */
public class JParentIDCellEditor extends AbstractCellEditor implements TableCellEditor {

    private JComboBox jComboBox = new JComboBox();
    private boolean cellEditingStopped = false;

    @Override
    public Object getCellEditorValue() {
        return jComboBox.getSelectedItem();
    }

    @Override
    public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
        ArrayList<Integer> arrayList = new ArrayList<Integer>();
        arrayList.add(Integer.parseInt(value.toString()));

        jComboBox = new JComboBox();
        ParentIDCellWorker worker = new ParentIDCellWorker(table, jComboBox, row, value);
        worker.execute();

        jComboBox.addItemListener(new ItemListener() {

            @Override
            public void itemStateChanged(ItemEvent e) {
                if (e.getStateChange() == ItemEvent.SELECTED) {
                    fireEditingStopped();
                }
            }
        });
        jComboBox.addPopupMenuListener(new PopupMenuListener() {

            @Override
            public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
                cellEditingStopped = false;
            }

            @Override
            public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
                cellEditingStopped = true;
                fireEditingCanceled();

            }

            @Override
            public void popupMenuCanceled(PopupMenuEvent e) {
            }
        });
        return jComboBox;
    }

    public class ParentIDCellWorker extends SwingWorker<Vector, Vector> {

        private JTable table;
        private JComboBox jComboBox;
        private int row;
        private Object value;

        public ParentIDCellWorker(JTable table, JComboBox jComboBox, int row, Object value) {
            this.table = table;
            this.jComboBox = jComboBox;
            this.row = row;
            this.value = value;
        }

        @Override
        protected Vector doInBackground() throws Exception {
            Vector vector = new Vector();
            vector.add(0);
            for (int i = 0; i < table.getRowCount(); i++) {
                try {
                    Interval interval = new Interval(((Date) table.getValueAt(i, 2)).getTime(), new Date().getTime());
                    interval = new Interval(((Date) table.getValueAt(i, 2)).getTime(), ((Date) table.getValueAt(row, 2)).getTime());
                    String gender = table.getValueAt(i, 3).toString();
                    if (!vector.contains(table.getValueAt(i, 0)) && gender.equals("Sheep")) {
                        vector.add(table.getValueAt(i, 0));
                    }
                } catch (IllegalArgumentException exp) {
                }
            }
            String[] rowsToRemove = getChildren(Integer.parseInt(table.getValueAt(row, 0).toString()), table).split("-");
            for (int i = 0; i < rowsToRemove.length; i++) {
                vector.removeElement((Object) (Integer.parseInt(rowsToRemove[i])));
            }
            return vector;
        }

        public String getChildren(int id, JTable jTable) {
            String id_map = "";
            for (int i = 0; i < jTable.getRowCount(); i++) {
                if (Integer.parseInt(jTable.getValueAt(i, 1).toString()) == id) {
                    id_map += getChildren(Integer.parseInt(jTable.getValueAt(i, 0).toString()), jTable);
                }
            }
            return id + "-" + id_map;
        }

        @Override
        protected void done() {
            try {
                for (Object i : get()) {
                    jComboBox.addItem(i);

                }
                jComboBox.setSelectedItem(value);
            } catch (InterruptedException ex) {
                Logger.getLogger(JParentIDCellEditor.class.getName()).log(Level.SEVERE, null, ex);
            } catch (ExecutionException ex) {
                Logger.getLogger(JParentIDCellEditor.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    @Override
    public boolean stopCellEditing() {
        return cellEditingStopped;
    }
}
Catalina Island
  • 7,027
  • 2
  • 23
  • 42
MOD
  • 1,070
  • 3
  • 19
  • 41
  • @MOD are you meaning this logics in JTable http://stackoverflow.com/questions/6246005/jcombobox-change-another-jcombobox/6246655#6246655 – mKorbel Oct 18 '11 at 06:54
  • kindda. I want efected combobox make calculations in a swing worker to show effected values and when calculation is done show values in its popup. But after calculation is done when i put values into combobox the open popup closes down. So i cant show calculated values in combobox. popup should wait until all values are put into it and usere select one – MOD Oct 18 '11 at 09:34

1 Answers1

1

I'm not sure, but waiting until the user clicks on the popup may be too late. Instead, you could fire up a SwingWorker to create a List<ComboBoxModel> before getTableCellEditorComponent gets called, maybe when you construct the parent table's model. That way, your getTableCellEditorComponent method could just set the right model for that row. I guess you would have to keep the List up to date in the editor, but that seems much easier.

Catalina Island
  • 7,027
  • 2
  • 23
  • 42