1

First of all, apologies for the amount of questions about borders. I'm now having trouble getting the border for the JComboBox to leave.

The solution offered in response to the question Remove border from JComboBox did not work.

And explicitly removing the border before passing the JComboBox to the DefaultCellEditor also didn't work.

Test class:

public class TableStackOf extends javax.swing.JFrame {

    public TableStackOf() {
        initComponents();
        JComboBox editableCombobox = new JComboBox(new String[]{"Hello", "World"});
        editableCombobox.setEditable(true);
        editableCombobox.setBorder(BorderFactory.createEmptyBorder());
        table.getColumnModel().getColumn(0).setCellEditor(new DefaultCellEditor(editableCombobox));
    }

    private void initComponents() {

        jScrollPane1 = new javax.swing.JScrollPane();
        table = new javax.swing.JTable();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        getContentPane().setLayout(new javax.swing.BoxLayout(getContentPane(), javax.swing.BoxLayout.LINE_AXIS));

        table.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {null, null},
                {null, null}
            },
            new String [] {
                "Title 1", "Title 2"
            }
        ));
        table.setGridColor(new java.awt.Color(218, 218, 218));
        table.setRowHeight(20);
        table.setSelectionBackground(new java.awt.Color(210, 225, 237));
        table.setSelectionForeground(new java.awt.Color(0, 0, 0));
        jScrollPane1.setViewportView(table);

        getContentPane().add(jScrollPane1);

        pack();
    }                     

    public static void main(String args[]) {            
        try {
            javax.swing.UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
        }
        java.awt.EventQueue.invokeLater(() -> {
            new TableStackOf().setVisible(true);
        });
    }

    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTable table;          
}

Also tried a PropertyChangeListener but it didn't work:

PropertyChangeListener changeListener = (evt) -> {
    JTable source = (JTable) evt.getSource();
    if ("tableCellEditor".equals(evt.getPropertyName())) {
        if (source.isEditing()) {
            Component component = ((DefaultCellEditor) source.getCellEditor()).getComponent();
            if (component instanceof JComboBox) {
                JComboBox combobox = (JComboBox) component;
                combobox.setBorder(BorderFactory.createEmptyBorder());
            }
        }
    }
};

What's odd is that setting the border to editableCombobox.setBorder(BorderFactory.createLineBorder(Color.WHITE)); does work, but if I set the border to EmptyBorder, it goes back to the default 1px grey border for some reason.

It's also worth nothing that I'm using the Windows LaF.

Morgan
  • 907
  • 1
  • 13
  • 35
  • 1
    1. Posted code should use standard JDK classes. JXTable is not a standard class. 2. Did you try it with the default LAF? If it works with the default, then it is a LAF issue so you need to look at the LAF code to see what it is doing. – camickr Nov 22 '17 at 03:41
  • My bad about that. Changed code to JTable now. I just tried several LaFs and I guess it's a problem with the Windows one. LaFs in which removing border works [Windows Classic, Motif]. LaFs in which removing borders doesn't work [Nimbus, Modern Windows] – Morgan Nov 22 '17 at 04:04

1 Answers1

1

It's also worth nothing that I'm using the Windows LaF.

  • You might be able to use a combo box editor that always uses BasicLookAndFeel.
    • I am running JDK 1.8.0_152 on Windows 10

screenshot

import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;

public class TableStackOf2 {
  private Component makeUI() {
    // TEST: UIManager.put("ComboBox.border", BorderFactory.createLineBorder(Color.RED));
    JTable table = new JTable();
    table.setModel(new DefaultTableModel(
      new Object[][] {
        {null, null},
        {null, null}
      },
      new String[] {
        "default", "BasicComboBoxUI"
      }));
    table.setGridColor(new Color(235, 235, 235));
    table.setRowHeight(20);
    table.setSelectionBackground(new Color(215, 230, 242));
    table.setSelectionForeground(new Color(0, 0, 0));

//     // @see https://stackoverflow.com/questions/38911818/remove-jcombobox-border-inside-jtable
//     // Nimbus TEST:
//     Painter<JComponent> emptyPainter = new Painter<JComponent>() {
//       @Override public void paint(Graphics2D g, JComponent c, int w, int h) {
//         /* Empty painter */
//       }
//     };
//     UIDefaults d = new UIDefaults();
//     d.put("TextField.borderPainter", emptyPainter);
//     d.put("TextField[Enabled].borderPainter", emptyPainter);
//     d.put("TextField[Focused].borderPainter", emptyPainter);
//     d.put("ComboBox:\"ComboBox.textField\"[Enabled].backgroundPainter", emptyPainter);
//     d.put("ComboBox:\"ComboBox.textField\"[Selected].backgroundPainter", emptyPainter);
//     d.put("ComboBox[Editable+Focused].backgroundPainter", emptyPainter);

    String[] model = {"Hello", "World"};

    JComboBox<String> editableCombobox = new JComboBox<String>(model) {
      // @see https://docs.oracle.com/javase/tutorial/displayCode.html?code=https://docs.oracle.com/javase/tutorial/uiswing/examples/components/TabComponentsDemoProject/src/components/ButtonTabComponent.java
      // we don't want to update UI for this combo box
      @Override public void updateUI() {
        // Nimbus TEST: super.updateUI();
        setUI(new javax.swing.plaf.basic.BasicComboBoxUI() {
          @Override protected JButton createArrowButton() {
            JButton b = new JButton(new ArrowIcon());
            b.setBackground(Color.BLACK);
            b.setContentAreaFilled(false);
            b.setFocusPainted(false);
            b.setBorder(BorderFactory.createEmptyBorder());
            return b;
          }
        });
      }
    };
    editableCombobox.setEditable(true);
    // Nimbus TEST: editableCombobox.putClientProperty("Nimbus.Overrides", d);
    editableCombobox.setBorder(BorderFactory.createEmptyBorder());

    JTextField c = (JTextField) editableCombobox.getEditor().getEditorComponent();
    // Nimbus TEST: c.putClientProperty("Nimbus.Overrides", d);
    c.setBorder(BorderFactory.createEmptyBorder());

    JComboBox<String> defaultComboBox = new JComboBox<>(model);
    defaultComboBox.setEditable(true);
    defaultComboBox.setBorder(BorderFactory.createEmptyBorder());
    ((JComponent) defaultComboBox.getEditor().getEditorComponent()).setBorder(BorderFactory.createEmptyBorder());

    table.getColumnModel().getColumn(0).setCellEditor(new DefaultCellEditor(defaultComboBox));
    table.getColumnModel().getColumn(1).setCellEditor(new DefaultCellEditor(editableCombobox));

    return new JScrollPane(table);
  }
  public static void main(String[] args) {
    try {
      UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
      // UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
      // UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");
    } catch (Exception ex) {
      ex.printStackTrace();
    }
    EventQueue.invokeLater(() -> {
      JFrame f = new JFrame();
      f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
      f.getContentPane().add(new TableStackOf2().makeUI());
      f.pack();
      f.setLocationRelativeTo(null);
      f.setVisible(true);
    });
  }
}

// @see https://ateraimemo.com/Swing/ComboBoxBorder.html
class ArrowIcon implements Icon {
  @Override public void paintIcon(Component c, Graphics g, int x, int y) {
    Graphics2D g2 = (Graphics2D) g.create();
    g2.setPaint(Color.BLACK);
    int shift = 0;
    if (c instanceof AbstractButton && ((AbstractButton) c).getModel().isPressed()) {
      shift = 1;
    }
    g2.translate(x, y + shift);
    g2.drawLine(2, 3, 6, 3);
    g2.drawLine(3, 4, 5, 4);
    g2.drawLine(4, 5, 4, 5);
    g2.dispose();
  }
  @Override public int getIconWidth() {
    return 9;
  }
  @Override public int getIconHeight() {
    return 9;
  }
}
aterai
  • 9,658
  • 4
  • 35
  • 44