aterai / java-swing-tips

Java Swing example.
https://ateraimemo.com/Swing.html
MIT License
564 stars 160 forks source link

Change selectedItem on DropdownTableComboBox project #15

Closed adarmawan117 closed 2 years ago

adarmawan117 commented 2 years ago

How can dinamically selectedItem or selectedIndex in DropdownTableComboBox project from outside class.? Thank you in advance

adarmawan117 commented 2 years ago

I change your code like in the bottom

adarmawan117 commented 2 years ago

package method.combobox;

import java.awt.; import java.awt.event.ItemEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.ArrayList; import java.util.List; import java.util.Objects; import javax.swing.; import javax.swing.plaf.basic.BasicComboPopup; import javax.swing.plaf.basic.ComboPopup; import javax.swing.plaf.metal.MetalComboBoxUI; import javax.swing.table.DefaultTableModel; import javax.swing.table.TableCellRenderer; import method.MyColor;

public class MyComboBoxTable extends JPanel {

private static String [] listData;

public String[] getListData() {
    return listData;
}

public void setSelectedIndex(int idx) {
    combo.setSelectedIndex(idx);
}

public void setSelectedItem(String id, int idxItem) {
    int idx = 0;
    for(List<Object> list : aseries) {

        if(list.get(idxItem).equals(id)) {
            setSelectedIndex(idx);
            return;
        }
        idx++;
    }

    setSelectedIndex(0);
}

int[] listCellWidth;
private DropdownTableComboBox<List<Object>> combo;
private List<List<Object>> aseries;

private void init(String[] columns, List<List<Object>> aseries) {

    DefaultTableModel model = new DefaultTableModel(null, columns) {
        @Override
        public boolean isCellEditable(int row, int column) {
            return false;
        }
    };

    this.aseries = aseries;

    int banyakData = columns.length;
    String[] temp1 = new String[banyakData];

    int idx = 0;
    for(Object data : aseries.get(0)) {
        temp1[idx++] = data.toString();
    }
    listData = temp1;

    combo = new DropdownTableComboBox<>(aseries, model);
    combo.addItemListener(e -> {
        if (e.getStateChange() == ItemEvent.SELECTED) {
            List<Object> rowData = combo.getSelectedRow();

            String[] temp = new String[banyakData];
            for(int i = 0; i < banyakData; i++) {
                temp[i] = Objects.toString(rowData.get(i));
            }
            listData = temp;

        }
    });

    if(listCellWidth != null) {
        combo.setTableWidth(listCellWidth);
    }

    ListCellRenderer<? super List<Object>> renderer = combo.getRenderer();
    combo.setRenderer((list, value, index, isSelected, cellHasFocus) -> {
        JLabel c = (JLabel) renderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
        c.setOpaque(true);
        if (isSelected) {
            c.setBackground(list.getSelectionBackground());
            c.setForeground(list.getSelectionForeground());
        } else {
            c.setBackground(list.getBackground());
            c.setForeground(list.getForeground());
        }
        c.setText(Objects.toString(value.get(2), ""));
        return c;
    });

    EventQueue.invokeLater(() -> combo.setSelectedIndex(0));

    Box box = Box.createHorizontalBox();
    box.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
    box.add(combo);

    add(box, BorderLayout.NORTH);
    setPreferredSize(new Dimension(320, 240));
}

public MyComboBoxTable() {
    super(new BorderLayout());
}

public MyComboBoxTable(String[] columns, List<List<Object>> aseries, int[] listCellWidth) { 
    super(new BorderLayout());

    this.listCellWidth = listCellWidth;

    init(columns, aseries);
}

}

class DropdownTableComboBox<E extends List> extends JComboBox {

private final JTable table = new JTable() {
    private transient HighlightListener mouseHandler;

    @Override
    public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
        Component c = super.prepareRenderer(renderer, row, column);
        c.setForeground(Color.BLACK);
        if (mouseHandler != null && mouseHandler.isHighlightTableRow(row)) {
            c.setBackground(new Color(0xFF_C8_C8));
        } else if (isRowSelected(row)) {
            c.setBackground(MyColor.PANEL_BACKGROUND_BLUE_COLOR);
            c.setForeground(MyColor.PANEL_BACKGROUND_WHITE_COLOR);
        } else {
            c.setBackground(MyColor.BTN_BACKGROUND_WHITE_COLOR);
            c.setForeground(MyColor.BTN_FOREGROUND_BLACK_COLOR);
        }
        return c;
    }

    @Override
    public void updateUI() {
        removeMouseListener(mouseHandler);
        removeMouseMotionListener(mouseHandler);
        super.updateUI();
        mouseHandler = new HighlightListener();
        addMouseListener(mouseHandler);
        addMouseMotionListener(mouseHandler);
        getTableHeader().setReorderingAllowed(false);
    }
};

public void setTableWidth(int listCellWidth[]) {
    int banyakData = listCellWidth.length;
    for (int i = 0; i < banyakData; i++) {
        table.getColumnModel().getColumn(i).setMinWidth(listCellWidth[i]);
        table.getColumnModel().getColumn(i).setPreferredWidth(listCellWidth[i]);
        table.getColumnModel().getColumn(i).setMaxWidth(listCellWidth[i]);
    }

}

private final List<E> list = new ArrayList<>();

protected DropdownTableComboBox(List<E> list, DefaultTableModel model) {
    super();
    this.list.addAll(list);
    table.setModel(model);
    list.forEach(this::addItem);
    list.forEach(v -> model.addRow(v.toArray(new Object[0])));
}

@Override
public void updateUI() {
    super.updateUI();
    EventQueue.invokeLater(() -> {
        setUI(new MetalComboBoxUI() {
            @Override
            protected ComboPopup createPopup() {
                return new ComboTablePopup(comboBox, table);
            }
        });
        setEditable(false);
    });
}

public List<Object> getSelectedRow() {
    return list.get(getSelectedIndex());
}

}

class ComboTablePopup extends BasicComboPopup {

private final JTable table;
private final JScrollPane scroll;

protected ComboTablePopup(JComboBox<?> combo, JTable table) {
    super(combo);
    this.table = table;

    ListSelectionModel sm = table.getSelectionModel();
    sm.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    sm.addListSelectionListener(e -> combo.setSelectedIndex(table.getSelectedRow()));

    combo.addItemListener(e -> {
        if (e.getStateChange() == ItemEvent.SELECTED) {
            setRowSelection(combo.getSelectedIndex());
        }
    });

    table.addMouseListener(new MouseAdapter() {
        @Override
        public void mousePressed(MouseEvent e) {
            combo.setSelectedIndex(table.rowAtPoint(e.getPoint()));
            setVisible(false);
        }
    });

    scroll = new JScrollPane(table);
    setBorder(BorderFactory.createEmptyBorder());
}

@Override
public void show() {
    if (isEnabled()) {
        scroll.setPreferredSize(new Dimension(320, 240));
        scroll.getVerticalScrollBar().setPreferredSize(new Dimension(3, 3));
        scroll.getHorizontalScrollBar().setPreferredSize(new Dimension(3, 3));

        super.removeAll();
        super.add(scroll);
        setRowSelection(comboBox.getSelectedIndex());
        super.show(comboBox, 0, comboBox.getBounds().height);
    }
}

private void setRowSelection(int index) {
    if (index != -1) {
        table.setRowSelectionInterval(index, index);
        table.scrollRectToVisible(table.getCellRect(index, 0, true));
    }
}

}

class HighlightListener extends MouseAdapter {

private int viewRowIdx = -1;

public boolean isHighlightTableRow(int row) {
    return this.viewRowIdx == row;
}

private void setHighlightTableCell(MouseEvent e) {
    Point pt = e.getPoint();
    Component c = e.getComponent();
    if (c instanceof JTable) {
        viewRowIdx = ((JTable) c).rowAtPoint(pt);
        c.repaint();
    }
}

@Override
public void mouseMoved(MouseEvent e) {
    setHighlightTableCell(e);
}

@Override
public void mouseDragged(MouseEvent e) {
    setHighlightTableCell(e);
}

@Override
public void mouseExited(MouseEvent e) {
    viewRowIdx = -1;
    e.getComponent().repaint();
}

}

adarmawan117 commented 2 years ago

But its not working

adarmawan117 commented 2 years ago

Sorry, this is MyColor.java class

adarmawan117 commented 2 years ago

package method;

import java.awt.Color;

public class MyColor {

/* BUTTON COLOR */
/* BACKGROUND */
public static final Color BTN_BACKGROUND_WHITE_COLOR = new Color(255, 255, 255);
public static final Color BTN_BACKGROUND_BIRU_MUDA_COLOR = new Color(183,251,255);

/* FOREGROUND/TEXT */
public static final Color BTN_FOREGROUND_WHITE_COLOR = new Color(255, 255, 255);
public static final Color BTN_FOREGROUND_BLACK_COLOR  = new Color(0,0,0);

/* END BUTTON COLOR */

/* PANEL COLOR */
public static final Color PANEL_BACKGROUND_SHADOW_COLOR = new Color(172, 185, 202);

public static final Color PANEL_BACKGROUND_WHITE_COLOR = new Color(255,255,255);
public static final Color PANEL_BACKGROUND_BLACK_COLOR = BTN_FOREGROUND_BLACK_COLOR;
public static final Color PANEL_BACKGROUND_BLUE_COLOR = new Color(65,105,225);

public static final Color PANEL_BACKGROUND_EDIT_PRIMARY_COLOR = new Color(255,255,255);
public static final Color PANEL_BACKGROUND_EDIT_SECONDARY_COLOR = new Color(209, 207, 207);

public static final Color PANEL_BACKGROUND_ORANGE_PRIMARY_COLOR = new Color(237, 125, 49);
public static final Color PANEL_BACKGROUND_ORANGE_SECONDARY_COLOR = new Color(207, 104, 33);

public static final Color PANEL_BACKGROUND_KUNING_COLOR = new Color(255,255,0);
/* END PANEL COLOR */

}

aterai commented 2 years ago

I have not compiled and checked MyComboBoxTable.java yet, but if I copy the setSelectedItem(...) method, etc., and run it as follows, it seems to works fine.

int itemIdx = 0;
EventQueue.invokeLater(() -> setSelectedItem("A5", itemIdx));
JButton button = new JButton("setSelectedItem");
button.addActionListener(e -> setSelectedItem("A4", itemIdx));
adarmawan117 commented 2 years ago

DropdownTableComboBoxProject.zip

Sorry, this is the new project.. I have added some comment in it..

Thank you bro..

aterai commented 2 years ago

DropdownTableComboBoxProject.zip

Thank you. I was able to compile and run your code.

DropdownTableComboBoxProject/src/mainpackage/MyComboBoxTable.java

If I understand your requirement, You might be able to use the EventQueue.invokeLater(...) as follows to execute the setSelectedItem(...) method in the event dispatch thread.

// DropdownTableComboBoxProject/src/mainpackage/MyComboBoxTable.java
// this is the default value when this class created
this.aseries = aseries;
// ...
// EventQueue.invokeLater(() -> combo.setSelectedIndex(0));
int itemIdx = 0;
EventQueue.invokeLater(() -> setSelectedItem("CD-002", itemIdx));
JButton button = new JButton("setSelectedItem");
button.addActionListener(e -> setSelectedItem("CD-003", itemIdx));

Box box = Box.createHorizontalBox();
box.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
box.add(combo);

add(box, BorderLayout.NORTH);
add(button, BorderLayout.SOUTH);