Details

    • Type: Task Task
    • Status: Resolved
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 1.6
    • Fix Version/s: 1.6.5
    • Component/s: TreeTable
    • Labels:
      None
    • Environment:

      Operating System: All
      Platform: All

      Description

      When setting a solid background color on a JXTable/JXTreeTable the background
      color won't appear if the current renderer is a JRendererLabel and if a Synth
      based look and feel will be used which defines a default table background.

      The funny things is when the table opacity will be changed to false the
      background appears as it should. Tested with SyntheticaStandardLookAndFeel.

      A workaround is to use an AlternateStripingHighlighter with two equal colors.

      Some lines of code to reproduce the issue:

      JXTreeTable treeTable = new JXTreeTable(new FileSystemModel());
      //on some columns the default table background appears
      treeTable.setBackground(new Color(0xC0FFC0));

      //highlighter workaround
      //Color bg = new Color(0xC0FFC0);
      //treeTable.setHighlighters(HighlighterFactory.createAlternateStriping(bg, bg));

      JScrollPane scroller = new JScrollPane(treeTable);
      getContentPane().add(BorderLayout.CENTER, scroller);

      Another LAF independent side effect is that JXTable#setOpaque(false) doesn't
      work as expected when a background color is set.

        Activity

        wzberger created issue -
        Hide
        kleopatra added a comment -

        hmm ... can't reproduce (on the supported LAFs

        But there definitely are issues with Synth - recently I had a hard time to hack around
        Nimbus misbehaviour (the forum will turn up my rants <g>), so could well be that Synthetica
        is/must be doing something comparable. Issue 1180 has some details and links.

        Before digging deeper: what's your jdk and OS? And could you please check against HighlighterClientVisualCheck
        (in the renderer test package) - the methods I cant reproduce your problem with contain
        "SimpleStriping". If you add Synthetica to the installed LAFs, it should appear as an
        option in the SetLAF menu to choose.

        Cheers
        Jeanette

        Show
        kleopatra added a comment - hmm ... can't reproduce (on the supported LAFs But there definitely are issues with Synth - recently I had a hard time to hack around Nimbus misbehaviour (the forum will turn up my rants <g>), so could well be that Synthetica is/must be doing something comparable. Issue 1180 has some details and links. Before digging deeper: what's your jdk and OS? And could you please check against HighlighterClientVisualCheck (in the renderer test package) - the methods I cant reproduce your problem with contain "SimpleStriping". If you add Synthetica to the installed LAFs, it should appear as an option in the SetLAF menu to choose. Cheers Jeanette
        Hide
        kleopatra added a comment -

        one question I forgot: is that new to post-final swingx? Or the other way round: which
        version was the last where it worked, if ever?

        Show
        kleopatra added a comment - one question I forgot: is that new to post-final swingx? Or the other way round: which version was the last where it worked, if ever?
        Hide
        wzberger added a comment - - edited

        Please find a test case below. The specified background color (Orange) doesn't
        appear. Sorry if my previous explanation wasn't clear enough.

        public class SynthJXTableTest extends JFrame
        {
          private static String synthXml = "<synth>" +
          "  <style id=\"all\">" +
          "    <font name=\"Tahoma\" size=\"11\"/>" +
          "  </style>" +
          "  <bind style=\"all\" type=\"REGION\" key=\".*\"/>" +
          "  <style id=\"table\">" +
          "    <state>" +
          "      <color type=\"BACKGROUND\" value=\"#FFE0E0\" />" +
          "      <color type=\"FOREGROUND\" value=\"#000000\" />" +
          "    </state>" +
          "    <state value=\"SELECTED\">" +
          "      <color type=\"TEXT_BACKGROUND\" value=\"#0070C0\"/>" + 
          "    <color type=\"TEXT_FOREGROUND\" value=\"#FFFFFF\"/>" + 
          "    </state>" +   
          "  </style>" +
          "  <bind style=\"table\" type=\"region\" key=\"Table\"/>" +
          "</synth>";
          
          public static void main(String[] args)
          {
            EventQueue.invokeLater(new Runnable(){
              public void run()
              {
                try
                {
                  new SynthJXTableTest();
                }
                catch (Exception e)
                {
                  e.printStackTrace();
                }
              }
            });   
          }
        
          public SynthJXTableTest() throws Exception
          {
            InputStream is = new ByteArrayInputStream(synthXml.getBytes("UTF8"));
            SynthLookAndFeel laf = new SynthLookAndFeel();
            laf.load(is, SynthJXTableTest.class);
            UIManager.setLookAndFeel(laf);    
        
            JXTable table = new JXTable(10, 5);
            
            //Issue: background color does not appear because JLabelRenderer#isOpaque 
            //returns false - as a result the default table color appears painted by 
            //ComponentUI#update(...)
            table.setBackground(Color.ORANGE);
            
            //very hacky workaround - not recommended - see JLabelRenderer#isOpaque()
            //table.setOpaque(false);
            
            //another workaround
            //table.setUI(new BasicTableUI());
            
            add(new JScrollPane(table));
            
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            setSize(new Dimension(600, 400));
            setLocationRelativeTo(null);
            setVisible(true);  
          }  
        }  
        
        
        Show
        wzberger added a comment - - edited Please find a test case below. The specified background color (Orange) doesn't appear. Sorry if my previous explanation wasn't clear enough. public class SynthJXTableTest extends JFrame { private static String synthXml = "<synth>" + " <style id=\" all\ ">" + " <font name=\" Tahoma\ " size=\" 11\ "/>" + " </style>" + " <bind style=\" all\ " type=\" REGION\ " key=\" .*\ "/>" + " <style id=\" table\ ">" + " <state>" + " <color type=\" BACKGROUND\ " value=\" #FFE0E0\ " />" + " <color type=\" FOREGROUND\ " value=\" #000000\ " />" + " </state>" + " <state value=\" SELECTED\ ">" + " <color type=\" TEXT_BACKGROUND\ " value=\" #0070C0\ "/>" + " <color type=\" TEXT_FOREGROUND\ " value=\" #FFFFFF\ "/>" + " </state>" + " </style>" + " <bind style=\" table\ " type=\" region\ " key=\" Table\ "/>" + "</synth>" ; public static void main( String [] args) { EventQueue.invokeLater( new Runnable (){ public void run() { try { new SynthJXTableTest(); } catch (Exception e) { e.printStackTrace(); } } }); } public SynthJXTableTest() throws Exception { InputStream is = new ByteArrayInputStream(synthXml.getBytes( "UTF8" )); SynthLookAndFeel laf = new SynthLookAndFeel(); laf.load(is, SynthJXTableTest.class); UIManager.setLookAndFeel(laf); JXTable table = new JXTable(10, 5); //Issue: background color does not appear because JLabelRenderer#isOpaque //returns false - as a result the default table color appears painted by //ComponentUI#update(...) table.setBackground(Color.ORANGE); //very hacky workaround - not recommended - see JLabelRenderer#isOpaque() //table.setOpaque( false ); //another workaround //table.setUI( new BasicTableUI()); add( new JScrollPane(table)); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setSize( new Dimension(600, 400)); setLocationRelativeTo( null ); setVisible( true ); } }
        Hide
        kleopatra added a comment - - edited

        ahhh .. I see, thanks for the example.

        But looks like not entirely a SwingX problem - there's something strange in core as well:
        painting of the table background without lines isn't table background. And JXTable shows
        up correctly if it is not the focused component, harhar ... any ideas? I'm not overly
        familiar with synth just burned last time I looked into enhancing support for Nimbus

        Below is your example slightly modified to show both side-by-side

        CU
        Jeanette

        /**
         * Issue 1188-swingx: background color of JXTable incorrect for SynthLAF
         */
        public class SynthTableColors extends JFrame {
            private static String synthXml = "<synth>" + "  <style id=\"all\">"
                    + "    <font name=\"Tahoma\" size=\"11\"/>" + "  </style>"
                    + "  <bind style=\"all\" type=\"REGION\" key=\".*\"/>"
                    + "  <style id=\"table\">" + "    <state>"
                    + "      <color type=\"BACKGROUND\" value=\"#FFE0E0\" />"
                    + "      <color type=\"FOREGROUND\" value=\"#000000\" />"
                    + "    </state>" + "    <state value=\"SELECTED\">"
                    + "      <color type=\"TEXT_BACKGROUND\" value=\"#0070C0\"/>"
                    + "    <color type=\"TEXT_FOREGROUND\" value=\"#FFFFFF\"/>"
                    + "    </state>" + "  </style>"
                    + "  <bind style=\"table\" type=\"region\" key=\"Table\"/>"
                    + "</synth>";
        
            public static void main(String[] args) {
                EventQueue.invokeLater(new Runnable() {
                    public void run() {
                        try {
                            new SynthTableColors();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                });
            }
        
            public SynthTableColors() throws Exception {
                InputStream is = new ByteArrayInputStream(synthXml.getBytes("UTF8"));
                SynthLookAndFeel laf = new SynthLookAndFeel();
                laf.load(is, SynthTableColors.class);
                UIManager.setLookAndFeel(laf);
        
                JTable table = new JTable(10, 5);
                configureTable(table);
                add(new JScrollPane(table), BorderLayout.WEST);
        
                JXTable xtable = new JXTable(10, 5);
                configureTable(xtable);
                add(new JScrollPane(xtable), BorderLayout.EAST);
                setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                pack();
                setLocationRelativeTo(null);
                setVisible(true);
            }
        
            /**
             * @param table
             */
            private void configureTable(JTable table) {
                table.setFillsViewportHeight(true);
                // Issue: background color does not appear because
                // JLabelRenderer#isOpaque
                // returns false - as a result the default table color appears painted
                // by
                // ComponentUI#update(...)
                table.setBackground(Color.ORANGE);
        
                // very hacky workaround - not recommended - see
                // JLabelRenderer#isOpaque()
                // table.setOpaque(false);
        
                // another workaround
                // table.setUI(new BasicTableUI());
            }
        }  
        
        
        Show
        kleopatra added a comment - - edited ahhh .. I see, thanks for the example. But looks like not entirely a SwingX problem - there's something strange in core as well: painting of the table background without lines isn't table background. And JXTable shows up correctly if it is not the focused component, harhar ... any ideas? I'm not overly familiar with synth just burned last time I looked into enhancing support for Nimbus Below is your example slightly modified to show both side-by-side CU Jeanette /** * Issue 1188-swingx: background color of JXTable incorrect for SynthLAF */ public class SynthTableColors extends JFrame { private static String synthXml = "<synth>" + " <style id=\" all\ ">" + " <font name=\" Tahoma\ " size=\" 11\ "/>" + " </style>" + " <bind style=\" all\ " type=\" REGION\ " key=\" .*\ "/>" + " <style id=\" table\ ">" + " <state>" + " <color type=\" BACKGROUND\ " value=\" #FFE0E0\ " />" + " <color type=\" FOREGROUND\ " value=\" #000000\ " />" + " </state>" + " <state value=\" SELECTED\ ">" + " <color type=\" TEXT_BACKGROUND\ " value=\" #0070C0\ "/>" + " <color type=\" TEXT_FOREGROUND\ " value=\" #FFFFFF\ "/>" + " </state>" + " </style>" + " <bind style=\" table\ " type=\" region\ " key=\" Table\ "/>" + "</synth>" ; public static void main( String [] args) { EventQueue.invokeLater( new Runnable () { public void run() { try { new SynthTableColors(); } catch (Exception e) { e.printStackTrace(); } } }); } public SynthTableColors() throws Exception { InputStream is = new ByteArrayInputStream(synthXml.getBytes( "UTF8" )); SynthLookAndFeel laf = new SynthLookAndFeel(); laf.load(is, SynthTableColors.class); UIManager.setLookAndFeel(laf); JTable table = new JTable(10, 5); configureTable(table); add( new JScrollPane(table), BorderLayout.WEST); JXTable xtable = new JXTable(10, 5); configureTable(xtable); add( new JScrollPane(xtable), BorderLayout.EAST); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); pack(); setLocationRelativeTo( null ); setVisible( true ); } /** * @param table */ private void configureTable(JTable table) { table.setFillsViewportHeight( true ); // Issue: background color does not appear because // JLabelRenderer#isOpaque // returns false - as a result the default table color appears painted // by // ComponentUI#update(...) table.setBackground(Color.ORANGE); // very hacky workaround - not recommended - see // JLabelRenderer#isOpaque() // table.setOpaque( false ); // another workaround // table.setUI( new BasicTableUI()); } }
        Hide
        kleopatra added a comment - - edited

        more fun below

        added

        • boolean column, that is use of checkbox
        • column with a DefaultTableCellRenderer which is not under the control of synth

        hmm .... looks fine with Nimbus instead of bare synth, so where else might be the problem?
        Could it be that part of the problem of this test case is a not complete enough init?

        Anyway, one thing you might try is to change JRendererLabel isOpaque: same as DefaultTableCellRenderer
        its implementation is some (maybe not longer needed) performance (assumed? don't know)
        optimization which returns a value depending on parents color/opaqueness. If that's changed
        to return the label's opaquesness property as set, then the xtable half of the example
        looks very much the same as the table's half. If that helps in your concrete context,
        then I can try to somehow remove the cleverness from the method, at least for Synth-related
        LAFs.

        CU
        Jeanette

            /**
             * @param table
             */
            private void configureTable(JTable table) {
                // model with boolean to see a checkbox as renderer
                TableModel model = new DefaultTableModel(10, 5) {
        
                    @Override
                    public Class<?> getColumnClass(int columnIndex) {
                        if (columnIndex == 0) {
                            return Boolean.class;
                        }
                        return super.getColumnClass(columnIndex);
                    }
                    
                };
                table.setModel(model);
                // use a renderer which is not under the control of synth
                table.getColumnModel().getColumn(1).setCellRenderer(new DefaultTableCellRenderer());
                // have a portion of table not painted by renderers
                table.setFillsViewportHeight(true);
                // Issue: background color does not appear because
                // JLabelRenderer#isOpaque
                // returns false - as a result the default table color appears painted
                // by
                // ComponentUI#update(...)
                table.setBackground(Color.ORANGE);
        
                // very hacky workaround - not recommended - see
                // JLabelRenderer#isOpaque()
                // table.setOpaque(false);
        
                // another workaround
                // table.setUI(new BasicTableUI());
            }
        
        Show
        kleopatra added a comment - - edited more fun below added boolean column, that is use of checkbox column with a DefaultTableCellRenderer which is not under the control of synth hmm .... looks fine with Nimbus instead of bare synth, so where else might be the problem? Could it be that part of the problem of this test case is a not complete enough init? Anyway, one thing you might try is to change JRendererLabel isOpaque: same as DefaultTableCellRenderer its implementation is some (maybe not longer needed) performance (assumed? don't know) optimization which returns a value depending on parents color/opaqueness. If that's changed to return the label's opaquesness property as set, then the xtable half of the example looks very much the same as the table's half. If that helps in your concrete context, then I can try to somehow remove the cleverness from the method, at least for Synth-related LAFs. CU Jeanette /** * @param table */ private void configureTable(JTable table) { // model with boolean to see a checkbox as renderer TableModel model = new DefaultTableModel(10, 5) { @Override public Class <?> getColumnClass( int columnIndex) { if (columnIndex == 0) { return Boolean .class; } return super .getColumnClass(columnIndex); } }; table.setModel(model); // use a renderer which is not under the control of synth table.getColumnModel().getColumn(1).setCellRenderer( new DefaultTableCellRenderer()); // have a portion of table not painted by renderers table.setFillsViewportHeight( true ); // Issue: background color does not appear because // JLabelRenderer#isOpaque // returns false - as a result the default table color appears painted // by // ComponentUI#update(...) table.setBackground(Color.ORANGE); // very hacky workaround - not recommended - see // JLabelRenderer#isOpaque() // table.setOpaque( false ); // another workaround // table.setUI( new BasicTableUI()); }
        Hide
        wzberger added a comment -

        Here are the results of my investigations.

        Generally Synth makes use of the specified background color for a component
        state. If no background color is defined a fallback mechanism makes use of the
        component background color - Nimbus provides colors in a different way so I
        think that's why Nimbus seems to work correct.

        You can check this by remarking the default background color definition within
        the test case.

        But why does normal tables work well? SynthTableCellRenderer is opaque by
        default and #isOpaque returns the unchanged opacity. Thats why the user defined
        background color appear - even if presented by table cells.

        So IMO it would be good for compatibility with Synth to modify
        JRendererLabel#isOpaque returning the non-optimized opacity value.

        Cheers,
        Wolfgang

        Show
        wzberger added a comment - Here are the results of my investigations. Generally Synth makes use of the specified background color for a component state. If no background color is defined a fallback mechanism makes use of the component background color - Nimbus provides colors in a different way so I think that's why Nimbus seems to work correct. You can check this by remarking the default background color definition within the test case. But why does normal tables work well? SynthTableCellRenderer is opaque by default and #isOpaque returns the unchanged opacity. Thats why the user defined background color appear - even if presented by table cells. So IMO it would be good for compatibility with Synth to modify JRendererLabel#isOpaque returning the non-optimized opacity value. Cheers, Wolfgang
        Hide
        kleopatra added a comment -

        JRendererLabel behaves exactly like DefaultTableCellRenderer when it comes to opaqueness,
        so actually I can't see a defect there. SynthTableCellRenderer is ... ehem .... quite
        weird and Synth can't cope well with renderers which are not under its control, read:
        not replaced by synth.

        But the underlying defect is somewhere in SynthTableUI painting code: it does not use
        the table's background color to fill the table's background. In the example, you can
        see that in the area below the rows: with fillViewportHeight enabled (in java6, for java5
        you have to override the table's getSomeThingTracks method to return true if the table
        is smaller than the viewport height) that area is painted in the table background color
        as defined by the ui, not in the color of table as set in code - that is it's schweinchenrosa,
        not orange. Happens if focused only (jdk1.6, didn't check the no longer supported 1.5)

        On the other side of the coin, the renderer opaque implementation (both DefaultTablecellRenderer
        and JRendererLabel - simple c&p) rely on its opaque parent to paint its own background
        as expected and guaranteed. The reasoning is that if the parent is opaque and has the
        same background color as the child, then the child need not fill the background - it's
        already must be done by the parent.

        So, I'm veeery reluctant to change that implementation. Shortly before a release it's
        a high risk that I overlook side-effects, JRendererLabel by default is used as rendering
        component across all collection components. Taking that risk to cover up for core bugs
        is ... hmm ...

        I would suggest you file a bug in Sun's bug parade: you can use the left-side of the example
        with a core JTable and instead of the JXTable as the right component take anything that's
        focusable (as the error shows only on a focused table, the difference might give a hint
        where/how exactly the misbehaviour happens).

        As to your context - you distribute a tweaked version of SwingX anyway, right? - change
        the isOpaque implementation and see how far it holds, I sure can be convinced by evidence
        And by masses: start a discussion in the forum, drum up support and pressure <g>

        I tend to change this to a task - revisit the implications of changing the implementation
        to bare returning the property - and postpone to after 1.6 release.

        Thanks
        Jeanette

        Show
        kleopatra added a comment - JRendererLabel behaves exactly like DefaultTableCellRenderer when it comes to opaqueness, so actually I can't see a defect there. SynthTableCellRenderer is ... ehem .... quite weird and Synth can't cope well with renderers which are not under its control, read: not replaced by synth. But the underlying defect is somewhere in SynthTableUI painting code: it does not use the table's background color to fill the table's background. In the example, you can see that in the area below the rows: with fillViewportHeight enabled (in java6, for java5 you have to override the table's getSomeThingTracks method to return true if the table is smaller than the viewport height) that area is painted in the table background color as defined by the ui, not in the color of table as set in code - that is it's schweinchenrosa, not orange. Happens if focused only (jdk1.6, didn't check the no longer supported 1.5) On the other side of the coin, the renderer opaque implementation (both DefaultTablecellRenderer and JRendererLabel - simple c&p) rely on its opaque parent to paint its own background as expected and guaranteed. The reasoning is that if the parent is opaque and has the same background color as the child, then the child need not fill the background - it's already must be done by the parent. So, I'm veeery reluctant to change that implementation. Shortly before a release it's a high risk that I overlook side-effects, JRendererLabel by default is used as rendering component across all collection components. Taking that risk to cover up for core bugs is ... hmm ... I would suggest you file a bug in Sun's bug parade: you can use the left-side of the example with a core JTable and instead of the JXTable as the right component take anything that's focusable (as the error shows only on a focused table, the difference might give a hint where/how exactly the misbehaviour happens). As to your context - you distribute a tweaked version of SwingX anyway, right? - change the isOpaque implementation and see how far it holds, I sure can be convinced by evidence And by masses: start a discussion in the forum, drum up support and pressure <g> I tend to change this to a task - revisit the implications of changing the implementation to bare returning the property - and postpone to after 1.6 release. Thanks Jeanette
        Hide
        wzberger added a comment -

        Yes, I'm aware that it is a Synth issue. So one possibility is to modify the
        renderer for Synth based LAF's only. But as soon as this will be fixed (even if
        I'm quite sure that it won't get fixed) your renderer has to get fixed too. So I
        agree it's better to leave it as it is.

        Luckily I'm able to fix the Synth issue under the hood for Synthetica and
        everything works fine. Additionally I'll file a bug at Sun's bug database.

        Please close the issue.

        Thanks,
        Wolfgang

        Show
        wzberger added a comment - Yes, I'm aware that it is a Synth issue. So one possibility is to modify the renderer for Synth based LAF's only. But as soon as this will be fixed (even if I'm quite sure that it won't get fixed) your renderer has to get fixed too. So I agree it's better to leave it as it is. Luckily I'm able to fix the Synth issue under the hood for Synthetica and everything works fine. Additionally I'll file a bug at Sun's bug database. Please close the issue. Thanks, Wolfgang
        Hide
        kleopatra added a comment -

        changed type and target milestone - basically, I fully agree that rendering
        components shouldn't try to be too clever. So will change once I checked the
        implications for existing clients (internal and external).

        Thanks
        Jeanette

        Show
        kleopatra added a comment - changed type and target milestone - basically, I fully agree that rendering components shouldn't try to be too clever. So will change once I checked the implications for existing clients (internal and external). Thanks Jeanette
        kenaiadmin made changes -
        Field Original Value New Value
        issue.field.bugzillaimportkey 1188 85448
        Karl Schaefer made changes -
        Affects Version/s 1.6 [ 13358 ]
        Affects Version/s 1.0++ [ 13357 ]
        Karl Schaefer made changes -
        Fix Version/s post_1.x [ 13367 ]
        Hide
        kleopatra added a comment -

        fixed by completely removing the trick: it was a c&p from core (while-not-believing-in-the-performance-effect-wanno-be-on-the-safe-side Now returns its opacity property as set, which definitely is the right thingy to do.

        Still don't oversee all the implications, looking at some visual tests and the demos doesn't reveal anything obvious. On the other hand, we have to fix a blocker regarding opacity in JXPanel (Issue 1514) anyway, so could handle any upcoming side-effects in one go.

        Committed as of revision #4222

        Show
        kleopatra added a comment - fixed by completely removing the trick: it was a c&p from core (while-not-believing-in-the-performance-effect-wanno-be-on-the-safe-side Now returns its opacity property as set, which definitely is the right thingy to do. Still don't oversee all the implications, looking at some visual tests and the demos doesn't reveal anything obvious. On the other hand, we have to fix a blocker regarding opacity in JXPanel (Issue 1514) anyway, so could handle any upcoming side-effects in one go. Committed as of revision #4222
        kleopatra made changes -
        Status Open [ 1 ] Resolved [ 5 ]
        Tags jrendererlabel opacity
        Fix Version/s 1.6.5 [ 15917 ]
        Resolution Fixed [ 1 ]

          People

          • Assignee:
            kleopatra
            Reporter:
            wzberger
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: