JDK-8258567 : Swing JTable row borders goes away after applying Nimbus LookAndFeel
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 8,11,14,15,16
  • Priority: P3
  • Status: Open
  • Resolution: Unresolved
  • OS: generic
  • CPU: x86_64
  • Submitted: 2020-12-12
  • Updated: 2022-01-06
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
tbdUnresolved
Description
ADDITIONAL SYSTEM INFORMATION :
Win 10, JDK 11.0.9

A DESCRIPTION OF THE PROBLEM :
Swing JTable row borders goes away after applying Nimbus LookAndFeel

I have raised this with example in stackoverflow.  Please check. 
 https://stackoverflow.com/questions/65257222/swing-jtable-row-borders-goes-away-after-applying-nimbus-lookandfeel


STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
I have a java 8 program in which - Parent is a JFrame that has Menu, few buttons, a text field and a JTable with fixed number of non-editable rows. Number of rows and data cannot be changed dynamically.
Menu has list of UIManager.getInstalledLookAndFeels()
Initially JTable rows border are visible
If LookAndFeel change to [Nimbus javax.swing.plaf.nimbus.NimbusLookAndFeel], and then try any other LookAndFeel, rows border goes away.
I am using SwingUtilities.updateComponentTreeUI(parentFrame) to apply LnF. LnF is applying on all components including JTable, but once Nimbus LnF applied and after that choosing any other LnF, rows border went off.
As a option repaint() is not making any difference

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Border should come back for rows of JTable
ACTUAL -
Border does not come back for rows of JTable once apply Nimbus LnF and then after changing to any other LookAndFeel 

---------- BEGIN SOURCE ----------
package com.sv.runcmd;

import com.sv.core.logger.MyLogger;
import com.sv.swingui.component.AppExitButton;

import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.LineBorder;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import static com.sv.core.Constants.SP_DASH_SP;
import static com.sv.swingui.UIConstants.EMPTY_BORDER;

public class LnFExample extends JFrame {

    public static void main(String[] args) {
        new LnFExample().initComponents();
    }

    private static final String APP_TITLE = "LnF";

    private DefaultTableModel model;
    private JTable tblCommands;

    private JMenuBar mbarSettings;

    public LnFExample() {
        super(APP_TITLE);
        SwingUtilities.invokeLater(this::initComponents);
    }

    /**
     * This method initializes the form.
     */
    private void initComponents() {

        Container parentContainer = getContentPane();
        parentContainer.setLayout(new BorderLayout());

        JButton btnExit = new AppExitButton(true);
        createTable();

        JPanel topPanel = new JPanel(new GridLayout(2, 1));
        topPanel.add(btnExit);
        topPanel.setBorder(EMPTY_BORDER);

        JPanel lowerPanel = new JPanel(new BorderLayout());
        JScrollPane jspCmds = new JScrollPane(tblCommands);
        lowerPanel.add(jspCmds);

        parentContainer.add(topPanel, BorderLayout.NORTH);
        parentContainer.add(lowerPanel, BorderLayout.CENTER);

        btnExit.addActionListener(evt -> exitForm());
        addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent evt) {
                exitForm();
            }
        });

        createAppMenu();
        setPosition();
    }

    private final MyLogger logger = MyLogger.createLogger("rc.log");

    private void createAppMenu() {
        mbarSettings = new JMenuBar();
        JMenu menuSettings = new JMenu("Settings");
        menuSettings.add(getThemesMenu());
        mbarSettings.add(menuSettings);

        setJMenuBar(mbarSettings);
    }

    public UIManager.LookAndFeelInfo[] getAvailableLAFs() {
        return UIManager.getInstalledLookAndFeels();
    }

    public JMenu getThemesMenu() {

        JMenu menu = new JMenu("Theme");

        int i = 'a';
        int x = 0;
        for (UIManager.LookAndFeelInfo l : getAvailableLAFs()) {
            JMenuItem mi = new JMenuItem((char) i + SP_DASH_SP + l.getName());
            if (i <= 'z') {
                mi.setMnemonic(i);
            }
            int finalX = x;
            mi.addActionListener(e -> applyTheme(finalX, l));
            menu.add(mi);
            i++;
            x++;
        }
        return menu;
    }

    UIManager.LookAndFeelInfo themeToApply;

    public void applyTheme(int idx, UIManager.LookAndFeelInfo lnf) {
        themeToApply = lnf;
        SwingUtilities.invokeLater(this::applyLnF);
    }

    public void applyLnF() {
        try {
            UIManager.setLookAndFeel(themeToApply.getClassName());
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e) {
            e.printStackTrace();
        }
        SwingUtilities.updateComponentTreeUI(this);
    }

    private void createTable() {
        model = new DefaultTableModel() {
            public int getColumnCount() {
                return 1;
            }

            public String getColumnName(int index) {
                return "Col";
            }
        };
        tblCommands = new JTable(model);
        createRows();
    }

    private void createRows() {
        for (int i = 0; i < 10; i++) {
            model.addRow(new String[]{"Row - " + i});
        }
    }

    private void setPosition() {
        // Setting to right most position
        pack();

        GraphicsConfiguration config = getGraphicsConfiguration();
        Rectangle bounds = config.getBounds();
        Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(config);

        int x = bounds.x + bounds.width - insets.right - getWidth();
        int y = bounds.y + insets.top + 10;

        setLocation(x, y);
        setVisible(true);
    }

    /**
     * Exit the Application
     */
    private void exitForm() {
        setVisible(false);
        dispose();
        logger.dispose();
        System.exit(0);
    }

}


---------- END SOURCE ----------

FREQUENCY : always



Comments
I can reproduce the issue on jdk16b24 on all platforms.
21-12-2020

As per the description, checked with attached testcase in reported jdk version in Windows 10, issue is reproducible Test Result ======== 8u271: Fail 8: Fail 11: Fail 11.0.9: Fail 12: Fail 15: Fail 16ea: Fail Attached screenshot for reference. More discussion : https://stackoverflow.com/questions/65257222/swing-jtable-row-borders-goes-away-after-applying-nimbus-lookandfeel
17-12-2020