使用渐变创建JLabel

时间:2014-12-24 19:54:43

标签: java swing user-interface jlabel graphics2d

我是Java新手,我尝试使用JLabel创建标题,并将其填充为渐变。我无法让它工作,我已经尝试了一段时间。我一直在抓住来自这里和其他网站的一些东西,似乎无法使这项工作成功,也无法理解其他人更复杂的代码。到目前为止,这是我的两个班级:

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 个答案:

答案 0 :(得分:4)

有一个小小的"技巧"你实际上可以做到这一点,通过让标签保持透明,你可以在调用super.paintComponent之前通过绘画实际绘制文本,例如......

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:我应该指出这个过程效率低下,因为RepaintManager仍然想要在组件下绘制

还有另外一招,但我两岁的女儿想检查圣诞老人是否在这里;)

<强>更新

另一个技巧是了解油漆过程的实际运作方式。当您调用super.paintComponent时,它会调用update上的ComponentUI方法(外观和感觉委托),这实际上是填充背景的方法,如果组件是不透明的,那么此方法称之为代理的paint方法,实际上是基础绘画...

我们可以稍微绕过这个过程而不是调用super.paintComponent,我们可以直接调用代理的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);
    }

}

这比前一个示例更有效,因为它不需要RepaintManager绘制此组件下方的区域,但它可能不适用于所有外观

答案 1 :(得分:3)

问题在于你使JLabel不透明,这意味着它将绘制背景。因此,调用super.paintComponent(...)会绘制渐变背景。所以摆脱:

//this.setOpaque(true);

代码的另一个问题是color1.brighter()不起作用。尝试类似:

  Color color2 = Color.RED;

此外,您不应更改Graphics对象,因为该对象也用于绘制其他Swing组件。相反,您应该使用g.create()来获取Graphics对象的副本。对该对象进行更改,进行绘制,然后dispose()对象。

所以(未经测试的)代码应该是这样的:

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

super.paintCompoenent(g);

答案 2 :(得分:2)

您应该将gradientPaint对象设置为Graphics,然后将其传递给super.paintComponent

试试这个:

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);
    }