So I have some code to change the background color of a button, but when I use the code, it sets the background color and border color.
Is there a way to not make this happen?
Thanks!
Code:
public void highlight(ArrayList<JButton> buttons){
for (JButton j : buttons) {
j.setBorder(new JButton().getBorder());
j.setBackground(Color.GREEN);
j.setForeground(Color.WHITE);
j.setOpaque(true);
j.setBorderPainted(false);
j.setFocusPainted(false);
j.setBorderPainted(false);
}
}
Okay, so this is a hacked version and is based on the idea that you want to maintain the current "look and feel" of the button, but want to use a different fill color
This simply applies a "highlight" color over the button...
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.RenderingHints;
import java.awt.Transparency;
import java.awt.image.BufferedImage;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import org.kaizen.core.ui.ImageUtilities;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
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 JPanel {
public TestPane() {
setLayout(new GridBagLayout());
HighlightButton btn = new HighlightButton("Help");
btn.setMargin(new Insets(20, 20, 20, 20));
btn.setHighlight(new Color(255, 0, 0, 64));
add(btn);
btn = new HighlightButton("Help");
btn.setMargin(new Insets(20, 20, 20, 20));
btn.setHighlight(new Color(0, 255, 0, 64));
add(btn);
btn = new HighlightButton("Help");
btn.setMargin(new Insets(20, 20, 20, 20));
btn.setHighlight(new Color(0, 0, 255, 64));
add(btn);
btn = new HighlightButton("Help");
btn.setMargin(new Insets(20, 20, 20, 20));
add(btn);
}
}
public class HighlightButton extends JButton {
private Color highlight;
public HighlightButton() {
setOpaque(false);
}
public HighlightButton(String text) {
super(text);
setOpaque(false);
}
public void setHighlight(Color color) {
if (color != highlight) {
Color old = highlight;
this.highlight = color;
firePropertyChange("highlight", old, highlight);
repaint();
}
}
public Color getHighlight() {
return highlight;
}
#Override
protected void paintComponent(Graphics g) {
Color highlight = getHighlight();
if (highlight != null) {
BufferedImage img = createCompatibleImage(getWidth(), getHeight(), Transparency.TRANSLUCENT);
Graphics2D g2d = img.createGraphics();
super.paintComponent(g2d);
g2d.dispose();
BufferedImage mask = generateMask(img, getHighlight(), 1f);
g.drawImage(img, 0, 0, this);
g.drawImage(mask, 0, 0, this);
} else {
super.paintComponent(g);
}
}
}
public static BufferedImage createCompatibleImage(int width, int height, int transparency) {
BufferedImage image = getGraphicsConfiguration().createCompatibleImage(width, height, transparency);
image.coerceData(true);
return image;
}
public static GraphicsConfiguration getGraphicsConfiguration() {
return GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
}
public static BufferedImage generateMask(BufferedImage imgSource, Color color, float alpha) {
int imgWidth = imgSource.getWidth();
int imgHeight = imgSource.getHeight();
BufferedImage imgMask = createCompatibleImage(imgWidth, imgHeight, Transparency.TRANSLUCENT);
Graphics2D g2 = imgMask.createGraphics();
applyQualityRenderingHints(g2);
g2.drawImage(imgSource, 0, 0, null);
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_IN, alpha));
g2.setColor(color);
g2.fillRect(0, 0, imgSource.getWidth(), imgSource.getHeight());
g2.dispose();
return imgMask;
}
public static void applyQualityRenderingHints(Graphics2D g2d) {
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
}
}
Basically, what this does, is paints a "masked" image, colored in the highlighted color OVER the top of the button. This is important to remember. The higher the alpha value of the color becomes, the less likely you are to see the text.
I've not tested this on windows, so I can't guarantee the results.
The content filling is performed by the look and feel delegate and generally ignores the color properties of the class (yeah, I know, awesome), so if you want to try and do something which was a little more robust, you'd need to define your own look and feel delegate and take over the painting process, no simple task.
Of course, you could just dispense with the content filling and borders used by the look and feel delegate and paint your own (overriding the paintComponent method), but this will not take advantage of the look and feel settings, so that's a balancing act you need to decide on
Related
I need to Override a JPanel and make it Raisd. See my Code please.
public class CustomJPanel extends JPanel {
public CustomJPanel(int size){
setForeground(Color.black); // foreground will be black
setOpaque(false);
}
#Override
protected void paintBorder(Graphics myGraphics){
myGraphics.setColor(Color.black);
myGraphics.drawRoundRect(0, 0, getWidth()-1, getHeight()-1, 20, 20);
}
}
Actually, i need to have a JPanel Raisd with rounded corners
Border
It's pretty basic, but it gets the idea across...
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.Arc2D;
import java.awt.geom.Path2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.Border;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
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 JPanel {
public TestPane() {
setBorder(new MyRoundedBorder());
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.dispose();
}
}
public static class MyRoundedBorder implements Border {
protected static final Insets DEFAULT_INSETS = new Insets(4, 4, 4, 4);
#Override
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g2d.setStroke(new BasicStroke(3, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
g2d.setColor(Color.WHITE);
Shape corner = new RoundedShape(width - 8, height - 8, 40);
g2d.translate(x + 2, y + 2);
g2d.draw(corner);
g2d.transform(AffineTransform.getRotateInstance(Math.toRadians(180), (width - 8) / 2, (height - 8) / 2));
g2d.setColor(Color.LIGHT_GRAY);
g2d.draw(corner);
g2d.dispose();
}
#Override
public Insets getBorderInsets(Component c) {
return DEFAULT_INSETS;
}
#Override
public boolean isBorderOpaque() {
return true;
}
public class RoundedShape extends Path2D.Float {
public RoundedShape(int width, int height, int size) {
moveTo(0, height - size);
append(new Arc2D.Float(0, height - size, size, size, 180, 45, Arc2D.CHORD), false);
lineTo(0, size);
curveTo(0, 0, 0, 0, size, 0);
lineTo(width - size / 2, 0);
append(new Arc2D.Float(width - size, 0, size, size, 90, -45, Arc2D.CHORD), false);
}
}
}
}
Custom Graphics
The problem with borders is you can't fill them, not really, it's kind of messy.
This leaves you with a problem with you want a non-rectangular component. Instead, you need to get a little more creative.
The following makes use of to "clipped" areas to paint a RoundRectangle2D in two different colors
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.geom.GeneralPath;
import java.awt.geom.RoundRectangle2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
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);
JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(new EmptyBorder(10, 10, 10, 10));
panel.setBackground(Color.RED);
frame.setContentPane(panel);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setOpaque(false);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
Shape border = new RoundRectangle2D.Double(0, 0, getWidth() - 1, getHeight() - 1, 20, 20);
g2d.setColor(getBackground());
g2d.fill(border);
GeneralPath upperClip = new GeneralPath();
upperClip.moveTo(0, 0);
upperClip.lineTo(getWidth() - 1, 0);
upperClip.lineTo(0, getHeight() - 1);
Graphics2D clipped = (Graphics2D) g2d.create();
clipped.setClip(upperClip);
clipped.setColor(Color.WHITE);
clipped.draw(border);
clipped.dispose();
GeneralPath lowerClip = new GeneralPath();
lowerClip.moveTo(0, getHeight());
lowerClip.lineTo(getWidth(), 0);
lowerClip.lineTo(getWidth(), getHeight());
clipped = (Graphics2D) g2d.create();
clipped.setClip(lowerClip);
clipped.setColor(Color.black);
clipped.draw(border);
clipped.dispose();
g2d.dispose();
}
}
}
LinearGradientPaint
A technique I've used in the past is to paint a RoundRectangle2D with a LinearGradientPaint, this gives a "slight" effect off shading which can produce a desirable result, if you're willing to play around with the properties
Try setting border while JPanel object is being created.
public CustomJPanel(int size){
setForeground(Color.black); // foreground will be black
setOpaque(false);
setBorder(new BevelBorder(BevelBorder.RAISED)); // Set Border Type
}
I am trying to create a simple graphing program, and I want/need the origin to be at the bottom left corner, so I am using the following custom canvas:
public class GraphingCanvas extends Canvas {
public GraphingCanvas() {
}
public void paint(Graphics g) {
((Graphics2D) g).translate(this.getWidth(), this.getHeight());
g.translate(10, 10);
g.setColor(Color.BLACK);
g.drawLine(0, 0, 10, 10);
}
}
However, when I use this canvas, like so:
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
GraphingCanvas canvas = new GraphingCanvas();
canvas.setBackground(Color.WHITE);
canvas.setBounds(10, 10, 414, 241);
frame.getContentPane().add(canvas);
}
The origin appears to remain at the default. Am I doing something wrong?
This may or may not do what you want, but basically I used scale(1, -1) to flip the orientation through the y-axis (and translated the context)
The magic basically happens in the paintComponent method using...
g2d.scale(1, -1);
g2d.translate(0, -getHeight());
Runnable example...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
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 JPanel {
private Rectangle box = new Rectangle(10, 10, 20, 20);
public TestPane() {
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
draw(g2d, Color.RED, Color.MAGENTA);
g2d.dispose();
g2d = (Graphics2D) g.create();
g2d.scale(1, -1);
g2d.translate(0, -getHeight());
draw(g2d, Color.BLUE, Color.GREEN);
g2d.dispose();
}
protected void draw(Graphics2D g2d, Color boxColor, Color lineColor) {
g2d.setColor(boxColor);
g2d.fill(box);
g2d.setColor(lineColor);
g2d.drawLine(0, 0, getWidth(), getHeight());
}
}
}
Just to be sure, I created a simple method...
protected void draw(Graphics2D g2d, Color boxColor, Color lineColor) {
g2d.setColor(boxColor);
g2d.fill(box);
g2d.setColor(lineColor);
g2d.drawLine(0, 0, getWidth(), getHeight());
}
which is called with the "normal" orientation and then called again with the transformed orientation, so it's the same code been used to paint the output, the only thing that's changed is the orientation
When I use the coordinates of (0,0) "Rectangle(0,0,100,100)" for the rectangle I get gradient. When I use:
GradientPaint gp = new GradientPaint(0, 0, c1, 0, 100, c2);
Rectangle reckt = new Rectangle(0,100,100,200);
the gradient disappears. What am I doing wrong?
public void draw( Graphics g ) {
Graphics2D g2d = (Graphics2D) g;
c1 = new Color(0, 0, 255);
c2 = new Color(0, 255, 255);
GradientPaint gp = new GradientPaint(0, 0, c1, 0, 100, c2);
g2d.setPaint(gp);
Rectangle reckt = new Rectangle(0,0,100,100);
g2d.fill(reckt);
}
The first two parameters define the x/y point at which the gradient starts and the fourth and fifth define the height and width. So basically, you're drawing your rectangle beyond the the gradient fill
You have two options, either change the x/y position if the GradientFill or use a AffineTransform and translate the Graphics context to where you want to paint and simply always paint at 0x0 for both
A AffineTransform allows you to translate (among other things) the Graphics top/left position, for example...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TestTranslate {
public static void main(String[] args) {
new TestTranslate();
}
public TestTranslate() {
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 JPanel {
public TestPane() {
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Color c1 = new Color(0, 0, 255);
Color c2 = new Color(0, 255, 255);
GradientPaint gp = new GradientPaint(0, 0, c1, 0, 100, c2);
for (int offset = 0; offset < getWidth(); offset += 50) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.setPaint(gp);
g2d.setTransform(AffineTransform.getTranslateInstance(offset, offset));
g2d.fill(new Rectangle(0, 0, 100, 100));
g2d.dispose();
}
}
}
}
I'm new to Java and I'm trying to create a heading using a JLabel and for its fill to be a gradient. I cannot get it to work and I've been trying for a while. I've been grabbing bits of come from here and other websites and cannot seem to make this work, nor make sense of other peoples more complex code that does work. Here are my two classes so far:
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
}
}
There is one little "trick" you can actually do, by leaving the label transparent, you can actually paint under the text by painting BEFORE you call super.paintComponent, for example...
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 should point out that this process is inefficient, as the RepaintManager will still want to paint under the component
There is another trick, but my two year old daughter wants to check to see if Santa is here ;)
Updated
The other trick involves understanding how the paint process actually works. When you call super.paintComponent, it calls the update method on the ComponentUI (look and feel delegate), this is actually the method that fills the background if the component is opaque, this method then calls the look and feels delegate's paint method, which actually does the base painting...
We can circumvent the process slightly and instead of calling super.paintComponent, we can call the look and feels delegate's paint method directly...
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 then the previous example, as it doesn't require the RepaintManager to paint the area underneath this component, but it might not work with all look and feels
The problem is that you made the JLabel opaque, which means it will paint the background. So the call to super.paintComponent(...) over paints the gradient background. 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;
Also, You should not change the Graphics object, since that object is also used to paint other Swing components. Instead you should use g.create() to get a copy of the Graphics object. Make your changes to that object, do the painting and then dispose() the object.
So the (untested) code would be something like:
Graphics2D g2d = (Graphics2D)g.create();
...
g2d.fillRect(...);
g2d.dispose();
super.paintCompoenent(g);
You should set your gradientPaint object to your Graphics and then pass that into 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);
}
I am using netbeans platform module to develop this desktop application. I am using drag and drop facility in netbeans in the developement.
I needed to create a toolbar which is having few buttons..I need to create a gradient color for these buttons.
I dragged and dropped JToolBar, over it I dragged and placed JButton objects.
In the properties of the button I have selected a color for which I want a shaded color. In the custom code I have modified.
jbutton = new javax.swing.Jbutton();
as below
jbutton = new javax.swing.JButton(){
#Override
protected void paintComponent(Graphics grphcs) {
Graphics2D g2d = (Graphics2D) grphcs;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
GradientPaint gp = new GradientPaint(0, 0,
getBackground().brighter().brighter().brighter(), 0, getHeight(),
getBackground().darker());
g2d.setPaint(gp);
g2d.fillRect(0, 0, getWidth(), getHeight());
super.paintComponent(grphcs);
}};
When I used the above code for a JPanel in my project it worked but it is not showing any effect when I used it for a button.
How to get a gradient color for a button placed in a toolbar?
The button has a contentAreaFilled attribute which determines if the look and feel should paint the content area of the button. When you call super.paintComponent, the look and feel delegate will paint over what you have done.
You can set this property to false and it should then work.
For example...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.RenderingHints;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class GradientButtons {
public static void main(String[] args) {
new GradientButtons();
}
public GradientButtons() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new GridBagLayout());
frame.add(new RoundButton("Click me"));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class RoundButton extends JButton {
public RoundButton(String text) {
super(text);
setBorderPainted(false);
setContentAreaFilled(false);
setFocusPainted(false);
setOpaque(false);
}
#Override
public Dimension getPreferredSize() {
Dimension size = super.getPreferredSize();
int radius = Math.max(size.width, size.height);
size.width = radius;
size.height = radius;
return size;
}
#Override
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
GradientPaint gp = new GradientPaint(0, 0,
Color.RED, 0, getHeight(),
Color.YELLOW);
g2d.setPaint(gp);
g2d.fillOval(0, 0, getWidth(), getHeight());
super.paintComponent(g);
}
}
}
You may want to check the ButtonModel's armed and/or pressed state so you can also change the way that the button is painted when clicked, as a suggestion...