4

I am writing a custom theme which is an extension of NimbusLookAndFeel. I want to redesign the table theme like

enter image description here

My Table theme code

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GradientPaint;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.RenderingHints;
import java.awt.geom.RoundRectangle2D;

import javax.swing.Painter;

import infotrax.nimbus.NimbusBaseUI;

public class TableTheme {

    protected int strokeSize = 2; // changed to 2 from 1 to fill the gap in corners 
    protected Color shadowColor = new Color(128, 128, 128, 140);
    protected boolean shady = true;
    protected boolean highQuality = false;
    /** Double values for Horizontal and Vertical radius of corner arcs */
    protected Dimension arcs = new Dimension(10, 10);
    /** Distance between shadow border and opaque panel border */
    protected int shadowGap = 1;
    /** The offset of shadow. */
    protected int shadowOffset = 1; // width of the shadow
    /** The transparency value of shadow. ( 0 - 255) */
    protected int shadowAlpha = 130;

    public TableTheme(NimbusBaseUI nimbusUI) {

        Insets ins = new Insets(2,2,2,2);
        nimbusUI.getDefaults().put("Table.contentMargins",ins
                );


        nimbusUI.getDefaults().put("Table.background",
                new Color(255, 255, 255)); // Modified to set background color of table to be white 01/08/2016




        nimbusUI.getDefaults().put(
                "Table.borderPainter",
                new TableBorderPaintGradient(new Color(255, 255, 255), new Color(255,
                        255, 255)));

        nimbusUI.getDefaults().put(
                "Table[Enabled].borderPainter",
                new TableBorderPaintGradient(new Color(255, 255, 255), new Color(255,
                        255, 255)));

        nimbusUI.getDefaults().put(
                "Table[Enabled+Selected].borderPainter",
                new TableBorderPaintGradient(new Color(255, 255, 255), new Color(255,
                        255, 255)));

        nimbusUI.getDefaults().put(
                "Table[Selected].borderPainter",
                new TableBorderPaintGradient(new Color(255, 255, 255), new Color(255,
                        255, 255)));

        nimbusUI.getDefaults().put(
                "Table[Focused].borderPainter",
                new TableBorderPaintGradient(new Color(255, 255, 255), new Color(255,
                        255, 255)));

        nimbusUI.getDefaults().put(
                "Table[Disabled].borderPainter",
                new TableBorderPaintGradient(new Color(255, 255, 255), new Color(255,
                        255, 255)));

        nimbusUI.getDefaults().put("TableHeader.font",
                new Font("Myriad Pro Light", Font.BOLD, 13));
        // Table Header color 
        nimbusUI.getDefaults()
                .put("TableHeader:\"TableHeader.renderer\"[MouseOver].backgroundPainter",
                        new TableheaderPainter(new Color(188,188,188),
                                new Color(188,188,188)));
        nimbusUI.getDefaults()
                .put("TableHeader:\"TableHeader.renderer\"[Enabled].backgroundPainter",
                        new TableheaderPainter(new Color(188,188,188),
                                new Color(188,188,188)));

    }

    public class TableheaderPainter implements Painter {

        private static final long serialVersionUID = 1L;
        private Color light, dark;
        private GradientPaint gradPaint;

        public TableheaderPainter(Color light, Color dark) {
            this.light = light;
            this.dark = dark;
        }

        @Override
        public void paint(Graphics2D paramGraphics2D, Object paramT,
                int paramInt1, int paramInt2) {
            paramGraphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                    RenderingHints.VALUE_ANTIALIAS_ON);
            gradPaint = new GradientPaint((paramInt1 / 2.0f), 0, light,
                    (paramInt1 / 2.0f), (paramInt2 / 2.0f), dark, true);
            paramGraphics2D.setPaint(gradPaint);
            paramGraphics2D.fillRoundRect(0, 0, (paramInt1 - 0),
                    (paramInt2 - 0), 0, 0);

        }
    }



    public class Tablebackground_Painter implements Painter {

        private Color light, dark;
        private GradientPaint gradPaint;
        int shadowGap = 2;

        public Tablebackground_Painter(Color light, Color dark) {
            this.light = light;
            this.dark = dark;
        }

        @Override
        public void paint(Graphics2D g, Object c, int w, int h) {

            Color shadowColorA = new Color(shadowColor.getRed(),
                    shadowColor.getGreen(), shadowColor.getBlue(), shadowAlpha);
            if (highQuality) {
                g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                        RenderingHints.VALUE_ANTIALIAS_ON);
            }
            if (shady) {
                g.setColor(shadowColorA);
                g.fillRoundRect(shadowOffset,// X position
                        shadowOffset,// Y position
                        w - strokeSize - shadowOffset, // width
                        h - strokeSize - shadowOffset, // height
                        arcs.width, arcs.height);// arc Dimension
            } else {
                shadowGap = 1;
            }
            gradPaint = new GradientPaint((w / 2.0f), 0, new Color(255, 255,
                    255), (w / 2.0f), (h / 2.0f), new Color(255, 255, 255),
                    false);
            g.setPaint(gradPaint);

            g.fillRoundRect(0, 0, w - shadowGap, h - shadowGap, arcs.width,
                    arcs.height);
            g.setColor(Color.GREEN);
            g.setStroke(new BasicStroke(strokeSize));
            g.drawRoundRect(0, 0, w - shadowGap, h - shadowGap, arcs.width,
                    arcs.height);
            g.setStroke(new BasicStroke());

        }
    }

    public class TableBorderPainter implements Painter {
        private Color light, dark;
        private GradientPaint gradPaint;

        public TableBorderPainter(Color light, Color dark) {
            this.light = light;
            this.dark = dark;
        }

        @Override
        public void paint(Graphics2D g, Object c, int w, int h) {
            g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                    RenderingHints.VALUE_ANTIALIAS_ON);
            gradPaint = new GradientPaint((w / 2.0f), 0, new Color(255, 255,
                    255), (w / 2.0f), (h / 2.0f), new Color(255, 255, 255), true); // making background of border paint to white to match the list background 
            g.setPaint(gradPaint);
            g.fillRoundRect(0, 0, (w - 0), (h - 0), 10, 10);
            RoundRectangle2D roundedRectangle = new RoundRectangle2D.Float(0,
                    0, w - 1, h - 1, 10, 10);
            g.setColor(Color.RED); // here we are making  red border color for list 
            g.draw(roundedRectangle);
        }

    }


    public class TableBorderPaintGradient implements Painter {

        private Color light, dark;
        private GradientPaint gradPaint;
        protected int strokeSize = 1;
        protected Color shadowColor = new Color(128, 128, 128, 140);
        /** Sets if it drops shadow */
        protected boolean shady = true;
        /** Sets if it has an High Quality view */
        protected boolean highQuality = false;
        /** Double values for Horizontal and Vertical radius of corner arcs */
        protected Dimension arcs = new Dimension(10, 10);
        /** Distance between shadow border and opaque panel border */
        protected int shadowGap = 1;
        /** The offset of shadow. */
        protected int shadowOffset = 1; // width of the shadow
        /** The transparency value of shadow. ( 0 - 255) */
        protected int shadowAlpha = 130;

        public TableBorderPaintGradient(Color light, Color dark) {
            this.light = light;
            this.dark = dark;
        }

        @Override
        public void paint(Graphics2D g, Object object, int w, int h) {

            Color shadowColorA = new Color(shadowColor.getRed(),
                    shadowColor.getGreen(), shadowColor.getBlue(), shadowAlpha);
            if (highQuality) {
                g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                        RenderingHints.VALUE_ANTIALIAS_ON);
            }
            if (shady) {
                g.setColor(shadowColorA);
                g.drawRoundRect(0, 0, w - shadowGap, h - shadowGap, arcs.width,
                        arcs.height);
            } else {
                shadowGap = 1;
            }
            gradPaint = new GradientPaint(0, 0, light, 0, h * .5f, dark, false);
            g.setPaint(gradPaint);
            g.drawRoundRect(shadowOffset,// X position
                    shadowOffset,// Y position
                    w - strokeSize - shadowOffset, // width
                    h - strokeSize - shadowOffset, // height
                    arcs.width, arcs.height);// arc Dimension
            g.setColor(new Color(166,166,166));
            g.setStroke(new BasicStroke(strokeSize));
            g.drawRoundRect(shadowOffset,// X position
                    shadowOffset,// Y position
                    w - strokeSize - shadowOffset, // width
                    h - strokeSize - shadowOffset, // height
                    arcs.width, arcs.height);// arc Dimension
            /* Changed to fillRoundedRect to drawRoundRect as per veryant suggestion */
            g.setStroke(new BasicStroke());

        }

    }


}

And extend the NimbusLookAndFeel and set as default to apply all my components in Java NimbusBaseUI

import javax.swing.UIManager;
import javax.swing.plaf.nimbus.NimbusLookAndFeel;
public class NimbusBaseUI extends NimbusLookAndFeel {
    public NimbusBaseUI() {
        super(); // Initialisation and installating
        try {
          new TableTheme(this);
            UIManager.setLookAndFeel(this);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void initialize() {
        // TODO Auto-generated method stub
        super.initialize();
    }

}

My Mainclass looks like this

import java.awt.FlowLayout;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.UIManager;

class NimbusBaseDemo extends JFrame {
    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    JTextField jtxt, txtDisEnabled;
    int i;

    private UIManager.LookAndFeelInfo[] lafs;

    public NimbusBaseDemo() {
        try {

            // Set nimbus look and feel. nimbusBase works only for it.
            new NimbusBaseUI();

        } catch (Exception e) {
            e.printStackTrace();
        }

        setTitle("Nimbus Base Demo");
        setSize(400, 400);
        setLayout(new FlowLayout());
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);
        String columnNames[] = { "Column 1", "Column 2", "Column 3" ,"Column 4"};
          String dataValues[][] = { { "12", "234", "67", " " },
            { "-123", "43", "853", "" }, { "93", "89.2", "109",""},
            { "279", "9033", "3092",""} };

        JTable table1 = new JTable(dataValues, columnNames);
        JScrollPane scrollPane = new JScrollPane(table1);
        add(scrollPane);



    }

    public static void main(String args[]) {

        new NimbusBaseDemo();
    }
}

Finally I got result as

enter image description here

But I am not able to change the backgroud of JTable (Non content area) to white...

Please suggest.

TT.
  • 15,774
  • 6
  • 47
  • 88
Kathi
  • 1,061
  • 1
  • 16
  • 31
  • This is because there is a parameter to use the full space with the "content area". This should be `table.setFillsViewportHeight(true);` – AxelH Nov 21 '16 at 12:10
  • As I am developing the only custom I didn't have access to table oject. It's A completely different project. Can change it from theme – Kathi Nov 21 '16 at 13:05
  • Could you tell use how you are using this theme, this could help to see the possibilities since you tell us in comment (see my answer) that this is for a Cobol GUI. – AxelH Nov 21 '16 at 13:07
  • Any clues on the API used to build those GUI ? – AxelH Nov 21 '16 at 13:24
  • @AxelH let it be simple, We have a custom compiler which internally uses JVM. so we have own syntax for our development. We can force custom compiler to pick up any Look and Feel like Nimbus etc. To look better We done some R&D and Look and Feel classes and finally decided to write our own Look and Feel which internally extend Nimbus. – Kathi Nov 21 '16 at 13:26
  • At what level is your compiler ? Is it a simple Generator + compiler ? If you can simply update this to generate the JTable like you want ... but here, this is complicated to help, only give idea – AxelH Nov 21 '16 at 13:29
  • @AxelH Finally we create an own script which is equivalent to `setFillsViewportHeight` its working great. Thank you :) – Kathi Nov 22 '16 at 09:16

1 Answers1

5

To use the full space of the JTable component with rows, you need to set the setFillsViewportHeightparameter:

table.setFillsViewportHeight(true);

This will extend the white area to the bottom of the table.

Here is the doc saying:

Sets whether or not this table is always made large enough to fill the height of an enclosing viewport. If the preferred height of the table is smaller than the viewport, then the table will be stretched to fill the viewport. In other words, this ensures the table is never smaller than the viewport. The default for this property is false.

Without this, it is just the JScrollPane that is visible (or the component where the JTable is inserted in) so it is that background that needs to be updated.

PS: this is not really a theme problem here since this is the expected behavior of JTable to use only the needed space unless you tell it to use the full space.

TT.
  • 15,774
  • 6
  • 47
  • 88
AxelH
  • 14,325
  • 2
  • 25
  • 55
  • @AxeIH Yes, I agree, its best solution in Java. But things little complex in my case. I am writing this theme for Cobol application which internally loads my theme. Unfortunately i did not find equivalent to setFillsViewportHeight() method in Cobol. – Kathi Nov 21 '16 at 12:54
  • Is there a way to apply this from a theme? because I do not have table object in my theme class – Kathi Nov 21 '16 at 12:57
  • @Kathi The question is explicitly about Java, nowhere do you mention anything about Cobol and how that ties in with your problem. – TT. Nov 21 '16 at 13:01
  • @Kathi, you should have mention Cobol from the beginning ... this is like a huge point here. A theme won't gave you that kind of management. Now, I don't how you linked Java with Cobol, but from what I know, you will be stuck here. – AxelH Nov 21 '16 at 13:04
  • @TT. thank you for the edit, my English needs to be improved ;) – AxelH Nov 21 '16 at 13:05
  • @AxelH I understand, yes it's more related to Nimbus theme rather Java. Our Cobol has its own JVM, I am not able to tell you more details on it, but If I focus main in Nimbus defaults https://docs.oracle.com/javase/tutorial/uiswing/lookandfeel/_nimbusDefaults.html Can i achieve it ? – Kathi Nov 21 '16 at 13:10
  • @Kathi Theme only gave you the access to font, color, borders and some margin. Here, the behavior came from the height of the JTable, by default as minimum. Unless you can override that behavior in the JVM used by rewriting the JTable default value. I doubt this can be done (but this is not really my field of expertise ;) ) – AxelH Nov 21 '16 at 13:18
  • @AxelH Completely agree with you. theme give us certain params to change. I thought it's a Table background so I am giving a try to do it from theme side. ` – Kathi Nov 21 '16 at 13:20
  • @Kathi Unfortunatly, the empty space is from the Pane behing the JTable, that's why if you change the background of the ScrollPane, this will work. So here, the only idea I see is to update the API used to generate the GUI. – AxelH Nov 21 '16 at 13:22
  • @AxelH Yes `ScrollPane` is working but it's affecting the all the other components. I had discussed with Cobol team they are trying to figure out. – Kathi Nov 21 '16 at 13:34
  • @AxelH Unfortunately I ended up this because of there is no scope to achieve this by theme. Thanks for your Answer. – Kathi Nov 21 '16 at 13:36
  • @Kathi Yep, this would be the solution. This is a simple parameter to add to every JTable build. You are welcome. Good luck with Cobol Team ;) – AxelH Nov 21 '16 at 13:37