重绘jlabel以获得渐变绘制的文本

j1dl9f46  于 2021-07-07  发布在  Java
关注(0)|答案(1)|浏览(354)

我正在尝试为文本创建一个从单词顶部到底部的渐变绘制,而不是从左到右。实际上,我是通过这个链接实现的。他们把文字的形状画在嵌板上。我只是编辑了他们的代码,并能够应用的影响,我正在寻找。以下是我编辑的绘制方法(其中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) 方法将形状下拉到可见位置。
我想我有两个问题。
为什么 g2.fill(s) 在由jlabel super方法绘制的文本上绘制形状?这可能是因为我的布局经理吗?
这是我应该走的路吗?有没有一个更简单的方法来应用垂直油漆梯度的文字?
下面是用于测试的最小代码:

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

yptwkmov1#

我能回答我自己的问题!我猜都是第一次。
我跟踪了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());
}

它的工作很有魅力:

相关问题