Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Swing Matte Border with Linear Gradient?

I tried the following example for applying a linear gradient: GradientPaintDemo2D.

It works well, but I wanted the gradient color to be applied into Java Swing matte border. I tried this:

javax.swing.BorderFactory.createMatteBorder(1, 50, 1, 50, color)

But that's only for applying one type of Color, not GradientPaint.

As we all know, GradientPaint contains two colors mixed altogether, as shown in the example linked above. So what's the alternative answer for this case?

like image 361
gumuruh Avatar asked Apr 09 '12 07:04

gumuruh


2 Answers

For such specific case you will need to create your own Border.
Here is an example with gradient border class:

public static class GradientBorder implements Border
{
    private Insets margin;

    public GradientBorder ( int top, int left, int bottom, int right )
    {
        super ();
        margin = new Insets ( top, left, bottom, right );
    }

    public void paintBorder ( Component c, Graphics g, int x, int y, int width, int height )
    {
        Graphics2D g2d = ( Graphics2D ) g;
        g2d.setPaint ( new GradientPaint ( x, y, Color.RED, x + width, y, Color.BLUE ) );

        Area border = new Area ( new Rectangle ( x, y, width, height ) );
        border.subtract ( new Area ( new Rectangle ( x + margin.left, y + margin.top,
                width - margin.left - margin.right, height - margin.top - margin.bottom ) ) );
        g2d.fill ( border );
    }

    public Insets getBorderInsets ( Component c )
    {
        return margin;
    }

    public boolean isBorderOpaque ()
    {
        return true;
    }
}

Ofcourse you can specify any other gradient direction, colors e.t.c. You can put their initialization into constructor aswell (if you need it). To use it you will just need to set border (in any JComponent successor):

jComponent.setBorder ( new GradientBorder ( 25, 50, 25, 50 ) );

Basically you can create any border you like this way with any coloring/animation/shapes e.t.c.

And by the way - isBorderOpaque () method should return true, if you want to create semi-transparent border (for example with semi-transparent colors, shaped with rounded corner and such), otherwise you will have to deal with component repainting problems.

like image 77
Mikle Garin Avatar answered Sep 30 '22 16:09

Mikle Garin


How about using new MatteBorder(int, int, int, int, javax.swing.Icon)

//Another example:
import java.awt.*;
import java.awt.geom.*;
import javax.swing.*;

public class GradientMatteBorderTest {
  public JComponent makeUI() {
    Icon icon = new Icon() {
      @Override public void paintIcon(Component c, Graphics g, int x, int y) {
        Graphics2D g2  = (Graphics2D)g.create();
        Point2D start  = new Point2D.Float(0f, 0f);
        Point2D end    = new Point2D.Float(99f, 0f);
        float[] dist   = {0.0f, 0.5f, 1.0f};
        Color[] colors = { Color.RED, Color.YELLOW, Color.GREEN };
        g2.setPaint(new LinearGradientPaint(start, end, dist, colors));
        g2.fillRect(x, y, 100, 10);
        g2.dispose();
      }
      @Override public int getIconWidth()  { return 100; }
      @Override public int getIconHeight() { return 10;  }
    };
    JLabel label = new JLabel("GradientMatteBorder");
    label.setBorder(BorderFactory.createMatteBorder(10,5,10,0,icon));
    JPanel p = new JPanel(new BorderLayout());
    p.setBorder(BorderFactory.createEmptyBorder(20,20,20,20));
    p.add(label, BorderLayout.NORTH);
    return p;
  }
  public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
      @Override public void run() {
        createAndShowGUI();
      }
    });
  }
  public static void createAndShowGUI() {
    JFrame f = new JFrame();
    f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    f.getContentPane().add(new GradientMatteBorderTest().makeUI());
    f.setSize(320, 240);
    f.setLocationRelativeTo(null);
    f.setVisible(true);
  }
}
like image 35
aterai Avatar answered Sep 30 '22 16:09

aterai