【问题标题】:Redrawing a JLabel to get a Gradient Painted Text重绘 JLabel 以获得渐变绘制文本
【发布时间】:2021-03-15 01:46:17
【问题描述】:

我正在尝试为从单词顶部到底部的文本创建渐变绘制,而不是从左到右。在link here 的帮助下,我实际上能够做到这一点。他们把文字的形状,画在面板上。我只是编辑了他们的代码并能够应用我正在寻找的效果。这是我将他们的绘画方法编辑为(其中 s 是一个形状):

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

这行得通,但是这种方法覆盖了 JPanel 的 paintComponent 方法。我正在尝试通过扩展 JLabel 的新 GradientLabel 类来重新创建它。我遇到的问题是g2d.fill(s) 方法在标签上方某处绘制形状,看似遥不可及。我不明白它为什么这样做。也许它来自铸造Graphics2D g.create();?我必须添加g2.translate(x,y) 方法才能将形状拉到可见位置。

我想我有 2 个问题。

  1. 为什么g2.fill(s) 不在由 JLabel 超级方法绘制的文本上绘制形状?这可能是因为我的布局管理器吗?

  2. 这种方法甚至是我应该采用的方法吗?有没有更简单的方法将垂直绘制渐变应用于文本?

这是用于测试的最少代码:

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

【问题讨论】:

    标签: java swing gradient jlabel paintcomponent


    【解决方案1】:

    嗯,我能够回答我自己的问题!我猜的一切都是第一次。

    我将 JLabel 上的代码跟踪到它在屏幕上实际绘制的类到 BasicLabelUI 类。我研究并确定如果我可以构建一个扩展这个类的新类,我可以简单地覆盖这个类的绘画部分。在测试并确定了从文本顶部到底部完全绘制两种颜色的最佳渐变之后,这就是我想出的:

    public class SBLabelUI extends BasicLabelUI {
    
        @Override
        protected void paintEnabledText(JLabel l, Graphics g, String s, int textX, int textY) { 
            if (l instanceof GradientLabel) {
                GradientLabel gl = (GradientLabel) l;
                Graphics2D g2d = (Graphics2D) g;
                Font f = gl.getFont();
                int h = gl.getFontMetrics(f).getHeight();
    
                GradientPaint gp = new GradientPaint(textX, textY, gl.c2, textX, Math.abs(textY-h), gl.c1);
                g2d.setPaint(gp);
                g2d.drawString(s, textX, textY);
            } else {
                super.paintEnabledText(l, g, s, textX, textY);
            }
        }
    }
    

    在渐变标签的构造函数中,我只需设置 UI:

    public GradientLabel(String text) {
        setText(text);
        this.setOpaque(false);
        setUI(new SBLabelUI());
    }
    

    它的工作很迷人:

    【讨论】:

    • 干得好!并加一个用于报告。 “它工作得很好:” 是的.. 在文本边缘加上一些抗锯齿和抖动可能会更好。为此,set rendering hints 在绘图或绘图之前在图形实例中。
    猜你喜欢
    • 1970-01-01
    • 2011-11-16
    • 2013-06-24
    • 2012-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多