Creating a JLabel with a gradient

I am new to Java and I am trying to create a header using JLabel and fill it with a gradient. I cannot get it to work and I have been trying for a while. I'm grabbing bits and pieces from here and other websites and can't seem to make this work, and don't understand that other people have more complex code that actually works. Here are my two classes:

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EtchedBorder;
public class Test {
    public static void main(String[] args) {
        new Test().setupGUI();
    }
    public void setupGUI() {
        //set up frames and buttons etc.
            JFrame theFrame = new JFrame ("Crystal Ball");
            theFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            JPanel background = new JPanel();
            background.setBackground(Color.BLUE);
            background.setLayout(new BoxLayout(background, BoxLayout.PAGE_AXIS));
            theFrame.setSize(500,1000);
            DLabel heading = new DLabel("Guess a Number");
            heading.setText("GUESS A NUMBER");
            heading.setPreferredSize(new Dimension(theFrame.getWidth(),100));
            heading.setFont(new Font("Serif", Font.PLAIN, 40));
            heading.setAlignmentX(Component.CENTER_ALIGNMENT);
            //heading.setBackground(Color.YELLOW);
            heading.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.RAISED));
            background.add(heading);
            theFrame.getContentPane().add(background);
            theFrame.pack();
            theFrame.setVisible(true);
            //startGame();
        }
}

import java.awt.Color;
import java.awt.Dimension;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.BorderFactory;
import javax.swing.JLabel;

public class DLabel extends JLabel
{

    Dimension size = new Dimension(70, 80);

    public DLabel(String name)
    {
        this.setPreferredSize(size);
        this.setText(name);
        this.setBorder(BorderFactory.createBevelBorder(TOP, Color.white, Color.black));
        this.setOpaque(true);
    }

    public void paintComponent(Graphics g) {
      // super.paintComponent(g);  // *** commented
      Graphics2D g2d = (Graphics2D) g;
      Color color1 = Color.YELLOW;
      Color color2 = color1.brighter();
      int w = getWidth();
      int h = getHeight();
      GradientPaint gp = new GradientPaint(0, 0, color1, 0, h, color2);
      g2d.setPaint(gp);
      g2d.fillRect(0, 0, w, h);
      super.paintComponent(g); // *** added
    }

}

      

+3


source to share


3 answers


There is one little "trick" you can actually do by leaving the label transparent, you can draw text under the picture before you call super.paintComponent

, for example ...

Raindbow

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.LinearGradientPaint;
import java.awt.Point;
import java.awt.Rectangle;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class TestLabel101 {

    public static void main(String[] args) {
        new TestLabel101();
    }

    public TestLabel101() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JLabel {

        public TestPane() {
            setText("Happy, Happy");
            setForeground(Color.WHITE);
            setHorizontalAlignment(CENTER);
        }

        @Override
        protected void paintComponent(Graphics g) {
            Graphics2D g2d = (Graphics2D) g.create();
            LinearGradientPaint lgp = new LinearGradientPaint(
                    new Point(0, 0), 
                    new Point(0, getHeight()), 
                    new float[]{0.142f, 0.284f, 0.426f, 0.568f, 0.71f, 0.852f, 1f}, 
                    new Color[]{Color.PINK, Color.MAGENTA, Color.BLUE, Color.GREEN, Color.YELLOW, Color.ORANGE, Color.RED});
            g2d.setPaint(lgp);
            g2d.fill(new Rectangle(0, 0, getWidth(), getHeight()));
            g2d.dispose();
            super.paintComponent(g);
        }

    }

}

      

nb: I have to point out that this process is inefficient as RepaintManager

it will still draw under the component

There is one more trick, but my 2 year old daughter wants to check if Santa is here;)



Update

Another trick is understanding how the drawing process works. When you call super.paintComponent

, it calls a method update

on the element ComponentUI

(expression and expression), this is actually a method that fills the background, if the component is opaque, this method calls the call and feels the delegate paint

, which actually makes the basic picture ...

We can bypass the process a bit and instead of calling super.paintComponent

, we can directly call and feel the delegate method paint

...

public class TestPane extends JLabel {

    public TestPane() {
        setText("Happy, Happy");
        setForeground(Color.WHITE);
        setHorizontalAlignment(CENTER);
        setOpaque(true);
    }

    @Override
    protected void paintComponent(Graphics g) {
        Graphics2D g2d = (Graphics2D) g.create();
        LinearGradientPaint lgp = new LinearGradientPaint(
                new Point(0, 0), 
                new Point(0, getHeight()), 
                new float[]{0.142f, 0.284f, 0.426f, 0.568f, 0.71f, 0.852f, 1f}, 
                new Color[]{Color.PINK, Color.MAGENTA, Color.BLUE, Color.GREEN, Color.YELLOW, Color.ORANGE, Color.RED});
        g2d.setPaint(lgp);
        g2d.fill(new Rectangle(0, 0, getWidth(), getHeight()));
        g2d.dispose();
        getUI().paint(g, this);
    }

}

      

This is more efficient than the previous example as it does not require to RepaintManager

draw the area under this component, but may not work with all external and external features.

+4


source


The problem is that you made the JLabel opaque, which means it will paint the background. So calling super.paintComponent (...) above the gradient background painting. So get rid of:

//this.setOpaque(true);

      

Another problem with the code is that color1.brighter () doesn't work. Try something like:

  Color color2 = Color.RED;

      



In addition, you should not modify the Graphics object, as this is also used to draw other Swing components. Instead, you should use g.create()

to get a copy of the Graphics object. Make changes to this object, draw the drawing, and then the dispose()

object.

So the (untested) code will look something like this:

Graphics2D g2d = (Graphics2D)g.create();
...
g2d.fillRect(...);
g2d.dispose();

super.paintCompoenent(g);

      

+3


source


You have to set your gradientPaint object to your graphic and then pass that to super.paintComponent

try this:

public void paintComponent(Graphics g) {
      Graphics2D g2d = (Graphics2D) g;
      Color color1 = Color.YELLOW;
      Color color2 = color1.brighter();
      int w = getWidth();
      int h = getHeight();
      GradientPaint gp = new GradientPaint(0, 0, color1, 0, h, color2);
      g2d.setPaint(gp);
      super.paintComponent(g2d);
    }

      

+2


source







All Articles