0

I've given up and seeking help from the community on this problem (would like to stop banging my head against this code (and my laptop).

I am trying to create a gradient background for my JTable - I've checked across this site & multiple forums for ways to create gradient background for various components. Most forums suggest overriding the paintComponent() method and setting the component transparent JTable.setOpaque(false). I've tried this in multiple configurations with no success.

Using help GradientViewport from this link here, I was able to set a gradient background for the scrollpane but not the table itself. Below is some sample code I've been working on to solve this:

import java.awt.*;
import java.util.Random;

import javax.swing.*;
import javax.swing.table.*;

public class GradientTest
{
    private static final Color C1 = new Color(255, 200, 200);
    private static final Color C2 = new Color(200, 200, 255);
    
    private GradientViewport viewport;

    private JTable testTbl;
    
    private JPanel mainPanel = new JPanel();
    private JFrame frame = new JFrame();

    private String[] answer = {"Yes", "No"};
    private String[] first = {"Jack", "Kelly", "Mike", "Lisa"};
    private String[] last = {"Donovan", "Marshall", "Jones", "Kinder"};
    
    public GradientTest()
    {
        String [] colNames = {"First Name", "Last Name", "Eligible"};
        DefaultTableModel model = new DefaultTableModel(colNames, 0);
        
        testTbl = new JTable(model);
//      {
//          @Override
//          protected void paintComponent(Graphics g)
//          {
//              super.paintComponent(g);
//              GradientPaint gp = new GradientPaint(0, 0, C1, getWidth(), getHeight(), C2, false);
//              Graphics2D g2d = (Graphics2D) g;
//              g2d.setPaint(gp);
//              g2d.fillRect(0, 0, getWidth(), getHeight());
//          }
//      };
        
        for(int x=0; x<10; x++) {
            
            String fName = first[new Random().nextInt(first.length)];
            String lName = last[new Random().nextInt(last.length)];
            String areaMonitor = answer[new Random().nextInt(answer.length)];
            
            model.addRow(new Object[] {fName, lName, areaMonitor});
        }
        
        testTbl.setOpaque(false);
        
        JScrollPane scrollPane = new JScrollPane();
        viewport = new GradientViewport(C1, C2);
        viewport.setView(testTbl);
        
        scrollPane.setBorder(BorderFactory.createEmptyBorder());
        scrollPane.setViewportBorder(null); //removes border from table
        scrollPane.setViewport(viewport);
        
        mainPanel.add(scrollPane);
        
        frame.add(mainPanel);
        frame.pack();
        
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
    
    public static void main(String[] args) {
        new GradientTest();
    }       
}

If I uncomment out the paintComponent() method and rerun, the gradient covers the entire table so that the underlying data cannot be viewed. I know there's a similar question/answer in the post I linked above but I'm looking for a gradient similar to what shows in the scrollpane.

Thanks in advance to anyone who can help - if there's not really a way of doing this, I'll stick with what I have.

Community
  • 1
  • 1
Probius
  • 79
  • 10
  • This is some what more complicated then it might seem, as the `JTable`'s `paintComponent` method actually paints the contents of the table ... so calling `super.paintComponent` followed by filling it will, well, not result in the effect you are after. – MadProgrammer Apr 25 '19 at 02:12
  • 1
    While in the normal cause of work, you should always call `super.paintComponent`, in this case, you don't want to do that. Instead, you kind of want to dance around it and call the UI delegate's paint method directly, for [example](https://stackoverflow.com/questions/43010330/jtable-autocreaterowsorter-causes-swing-to-paint-the-table-wrong/43010876#43010876). This allows you to paint the background as you want and then paint the content over the top. – MadProgrammer Apr 25 '19 at 02:12
  • Another solution might be to make the table transparent and the paint the background yourself before calling `super.paintComponent`, this is kind of expensive, as Swing will then try and paint all the components behind the table regardless – MadProgrammer Apr 25 '19 at 02:13
  • 1
    The renderers also need to be transparent. Here is a link to some old Sun files that allow you to do gradient painting (and more): http://www.jcomeau.com/src/java/com/sun/WatermarkDemo/. – camickr Apr 25 '19 at 02:52
  • Thanks for the suggestions. I found what I was looking for with the answer comment from @camickr. Just wondering, though - what is the downvote for? If it's for the code above, that's a sample I put together to test since I didn't want to bog the question with my actual code (which is a bit more lengthy). – Probius Apr 25 '19 at 17:39
  • Don't know what the down vote is for. I agree it is frustrating when people down vote for no (stated) reason. The code you posted is what we want. We only want minimal code that demonstrates the stated problem, which your code does. I just up voted, since you did post a proper [mcve]. – camickr Apr 25 '19 at 18:22

1 Answers1

1

So going off the comments there were only a few lines I needed to add to the code:

DefaultTableCellRenderer rend = new DefaultTableCellRenderer();
rend.setOpaque(false);
testTbl.setDefaultRenderer(Object.class, rend);
I also added some of the code from @MadProgrammer's link to fix the issue with my headers too. Thanks again for the help.
Probius
  • 79
  • 10