I am trying to create a gradient paint for text that goes from the top of the word to the bottom, not from left to right. I was actually able to achieve this from the help of this link here. They took the shape of the text, and painted it on the panel. I simply edited their code and was able to apply the affect I am looking for. Here is what I edited their paint method to (where s is a Shape):
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.translate(100, 150);
Rectangle2D r = s.getBounds2D();
int x = (int) r.getX();
int y = (int) r.getY();
int h = (int) r.getHeight();
GradientPaint gp = new GradientPaint(x, y, Color.MAGENTA, x, h, Color.ORANGE);
g2.setPaint(gp);
g2.fill(s);
}
This worked, but this approach is overriding a paintComponent method of a JPanel. I am trying to recreate this by a new GradientLabel Class that extends JLabel. The issue I am having is that the g2d.fill(s) method is drawing the shape somewhere above the label, seemingly out of reach. I don't understand why it is doing this. Perhaps its from casting Graphics2D g.create();? I have had to add the g2.translate(x,y) method to pull the shape down into a viewable location.
I guess I have 2 questions.
Why doesn't the
g2.fill(s)draw the shape over the text that was drawn by the JLabel super method? Could this be because of my layout manager?Is this approach even the way I should go? Is there an easier way to apply a vertical paint gradient to text?
Here is the minimal code for testing:
public class test extends JFrame {
private JPanel contentPane;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
test frame = new test();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public test() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 516, 360);
contentPane = new JPanel();
contentPane.setBorder(null);
setContentPane(contentPane);
GridBagLayout gbl_contentPane = new GridBagLayout();
gbl_contentPane.columnWidths = new int[]{0, 0};
gbl_contentPane.rowHeights = new int[]{0, 100, 0};
gbl_contentPane.columnWeights = new double[]{1.0, Double.MIN_VALUE};
gbl_contentPane.rowWeights = new double[]{0.0, 0.0, Double.MIN_VALUE};
contentPane.setLayout(gbl_contentPane);
Component verticalStrut = Box.createVerticalStrut(20);
GridBagConstraints gbc_verticalStrut = new GridBagConstraints();
gbc_verticalStrut.insets = new Insets(0, 0, 5, 0);
gbc_verticalStrut.gridx = 0;
gbc_verticalStrut.gridy = 0;
contentPane.add(verticalStrut, gbc_verticalStrut);
GradientLabel lblTest = new GradientLabel("TEST");
lblTest.setHorizontalAlignment(SwingConstants.CENTER);
lblTest.setGradientColors(Color.GREEN, Color.WHITE);
lblTest.setFont(new Font("Tahoma", Font.PLAIN, 70));
GridBagConstraints gbc_lblTest = new GridBagConstraints();
gbc_lblTest.fill = GridBagConstraints.BOTH;
gbc_lblTest.gridx = 0;
gbc_lblTest.gridy = 1;
contentPane.add(lblTest, gbc_lblTest);
}
public class GradientLabel extends JLabel {
private Color c1;
private Color c2;
public GradientLabel(String text) {
setText(text);
this.setOpaque(false);
}
public void setGradientColors(Color c1, Color c2) {
this.c1 = c1;
this.c2 = c2;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Font f = getFont();
GlyphVector v = f.createGlyphVector(getFontMetrics(f).getFontRenderContext(), getText());
Shape s = v.getOutline();
Rectangle2D r = s.getBounds2D();
int x = (int) r.getX();
int y = (int) r.getY();
int h = (int) r.getHeight();
int w = (int) r.getWidth();
//without this the shape is drawn almost out of view
g2d.translate(x, h);
g2d.drawRect(x, y, w, h);
//for some reason using only h as the second y doesn't show much of the second color.
//Subtracting 60 arbitrarily showed more of the second color in the gradient.
//Bonus points for an explanation on why that happens.
GradientPaint gp = new GradientPaint(x, y, c1, x, h - 60, c2);
g2d.setPaint(gp);
g2d.fill(s);
}
}
}
