1

通常,我只会JLabel使用字符串作为第一个参数和JLabel.CENTER第二个参数来创建;使用将标签添加到面板BorderLayout.CENTER会导致标签中的文本在面板的中心对齐。

但是,我正在使用“RichJLabel”类来在我的文本上添加阴影。为此,它会Component.paintComponent以丢失对齐信息的方式覆盖,并且无论我做什么,标签的文本都会绘制在面板的左上角。

据我了解,解决方法是将标签封装在另一个面板内;这样,我可以在父面板内对齐面板本身,但我不确定如何做到这一点。

我的完整目标是:

  • 找出给定字符串需要什么字体大小才能填充其父 JPanel
  • 为该文本添加阴影
  • 在其 JPanel 中居中文本

这是我到目前为止所得到的:

import java.awt.*;
import javax.swing.*;
import javax.swing.border.BevelBorder;

public class RichJLabel extends JLabel {

    private int tracking;

    public RichJLabel(String text, int tracking) {
        super(text, JLabel.CENTER);
        this.tracking = tracking;
    }

    private int left_x, left_y, right_x, right_y;
    private Color left_color, right_color;

    public void setLeftShadow(int x, int y, Color color) {
        left_x = x;
        left_y = y;
        left_color = color;
    }

    public void setRightShadow(int x, int y, Color color) {
        right_x = x;
        right_y = y;
        right_color = color;
    }

    public Dimension getPreferredSize() {
         String text = getText();
         FontMetrics fm = this.getFontMetrics(getFont());

         int w = fm.stringWidth(text);
         w += (text.length()-1)*tracking;
         w += left_x + right_x;
         int h = fm.getHeight();
         h += left_y + right_y;

         return new Dimension(w,h); 
}

public void paintComponent(Graphics g) {

        ((Graphics2D)g).setRenderingHint(
            RenderingHints.KEY_TEXT_ANTIALIASING,
            RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        char[] chars = getText().toCharArray();

        FontMetrics fm = this.getFontMetrics(getFont());

        int h = fm.getAscent();
        int x = 0;

        for(int i=0; i<chars.length; i++) {
            char ch = chars[i];
            int w = fm.charWidth(ch) + tracking;

            g.setColor(left_color);
            g.drawString(""+chars[i],x-left_x,h-left_y);

            g.setColor(right_color);
            g.drawString(""+chars[i],x+right_x,h+right_y);

            g.setColor(getForeground());
            g.drawString(""+chars[i],x,h);

            x+=w;
    }

        ((Graphics2D)g).setRenderingHint(
            RenderingHints.KEY_TEXT_ANTIALIASING,
            RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT);

    } // end paintComponent()

public static void main(String[] args) {

  JPanel panel1 = new JPanel( new BorderLayout() );
  panel1.setBackground( Color.BLUE );
  panel1.setBorder( BorderFactory.createBevelBorder( BevelBorder.LOWERED ));

  JPanel interiorPanel = new JPanel( new BorderLayout() );
  panel1.add(interiorPanel, BorderLayout.CENTER);
  RichJLabel label = new RichJLabel("100", 0);
  label.setHorizontalAlignment(JLabel.CENTER);
  label.setVerticalAlignment(JLabel.CENTER);
  label.setVisible( true );
  label.setForeground( Color.YELLOW );

  interiorPanel.add(label, BorderLayout.CENTER);
  label.setFont(new Font("Arial", Font.BOLD, 140));
  label.setFont(label.getFont().deriveFont(140f));


  //resize code
  Font labelFont = label.getFont();
  String labelText = label.getText();
  int stringWidth = label.getFontMetrics(labelFont).stringWidth(labelText);
  int componentWidth = interiorPanel.getWidth();

  // Find out how much the font can grow in width.
  double widthRatio = (double)componentWidth / (double)stringWidth;
  int newFontSize = (int)(labelFont.getSize() * widthRatio);
  int componentHeight = interiorPanel.getHeight();

  // Pick a new font size so it will not be larger than the height of label.
  int fontSizeToUse = Math.min(newFontSize, componentHeight);
  // Set the label's font size to the newly determined size.
  label.setFont(new Font(labelFont.getName(), Font.BOLD, fontSizeToUse));
  label.setLeftShadow(-3,-3,Color.BLACK);     

  // drop shadow w/ highlight
  label.setRightShadow(2,3,Color.black);
  label.setForeground(Color.gray);

  JFrame frame = new JFrame("Label SSCCEE");
  frame.getContentPane().add(panel1);
  frame.pack();
  frame.setVisible(true);
 }
}

它现在所做的是:

蓝色面板内的灰色框

4

2 回答 2

3

代码过早地检查容器的大小。在显示之前,它的宽度/高度为 0。

带阴影的文字

修改后的代码

import java.awt.*;
import javax.swing.*;
import javax.swing.border.BevelBorder;

public class RichJLabel extends JLabel {

    private int tracking;

    public RichJLabel(String text, int tracking) {
        super(text, JLabel.CENTER);
        this.tracking = tracking;
    }

    private int left_x, left_y, right_x, right_y;
    private Color left_color, right_color;

    public void setLeftShadow(int x, int y, Color color) {
        left_x = x;
        left_y = y;
        left_color = color;
    }

    public void setRightShadow(int x, int y, Color color) {
        right_x = x;
        right_y = y;
        right_color = color;
    }

    public Dimension getPreferredSize() {
         String text = getText();
         FontMetrics fm = this.getFontMetrics(getFont());

         int w = fm.stringWidth(text);
         w += (text.length()-1)*tracking;
         w += left_x + right_x;
         int h = fm.getHeight();
         h += left_y + right_y;

         return new Dimension(w,h);
}

public void paintComponent(Graphics g) {

        ((Graphics2D)g).setRenderingHint(
            RenderingHints.KEY_TEXT_ANTIALIASING,
            RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        char[] chars = getText().toCharArray();

        FontMetrics fm = this.getFontMetrics(getFont());

        int h = fm.getAscent();
        int x = 0;

        for(int i=0; i<chars.length; i++) {
            char ch = chars[i];
            int w = fm.charWidth(ch) + tracking;

            g.setColor(left_color);
            g.drawString(""+chars[i],x-left_x,h-left_y);

            g.setColor(right_color);
            g.drawString(""+chars[i],x+right_x,h+right_y);

            g.setColor(getForeground());
            g.drawString(""+chars[i],x,h);

            x+=w;
    }

        ((Graphics2D)g).setRenderingHint(
            RenderingHints.KEY_TEXT_ANTIALIASING,
            RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT);

    } // end paintComponent()

public static void main(String[] args) {

  JPanel panel1 = new JPanel( new BorderLayout() );
  panel1.setBackground( Color.BLUE );
  panel1.setBorder( BorderFactory.createBevelBorder( BevelBorder.LOWERED ));

  JPanel interiorPanel = new JPanel( new BorderLayout() );
  panel1.add(interiorPanel, BorderLayout.CENTER);
  RichJLabel label = new RichJLabel("100", 0);
  label.setLeftShadow(-3,-3,Color.BLACK);

  // drop shadow w/ highlight
  label.setRightShadow(2,3,Color.black);

  label.setHorizontalAlignment(JLabel.CENTER);
  label.setVerticalAlignment(JLabel.CENTER);
  label.setVisible( true );
  label.setForeground( Color.YELLOW );

  interiorPanel.add(label, BorderLayout.CENTER);
  label.setFont(new Font("Arial", Font.BOLD, 140));
  label.setFont(label.getFont().deriveFont(140f));

  //resize code
  Font labelFont = label.getFont();

  JFrame frame = new JFrame("Label SSCCEE");
  frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
  frame.setContentPane(panel1);
  frame.pack();
  frame.setVisible(true);

  int componentWidth = interiorPanel.getWidth();
  String labelText = label.getText();
  int stringWidth = label.getFontMetrics(labelFont).stringWidth(labelText);
  // Find out how much the font can grow in width.
  double widthRatio = (double)componentWidth / (double)stringWidth;
  int newFontSize = (int)(labelFont.getSize() * widthRatio);
  int componentHeight = interiorPanel.getHeight();

  // Pick a new font size so it will not be larger than the height of label.
  int fontSizeToUse = Math.min(newFontSize, componentHeight);
  System.out.println("fontSizeToUse: " + fontSizeToUse);
  if (fontSizeToUse<1) {
      System.err.println("Font size less than 1!");
      System.exit(1);
  }

  // Set the label's font size to the newly determined size.
  label.setFont(new Font(labelFont.getName(), Font.BOLD, fontSizeToUse));
  label.setForeground(Color.gray);
 }
}
于 2012-05-18T22:06:04.030 回答
1

如果是这个RichJLabel,那就看看吧paintComponent。我建议制作自己的阴影标签,可能由两个阴影标签和一个前景标签组成。没想到每个角色都画了3遍。有问题的:效率低下,不能使用像阿拉伯语这样的脚本语言或组合变音符号(一个字符字母,另一个重音)。

在某些时候,到处乱砍是不值得的。如果你看过消息来源,谁知道呢。

我不确定我是否有正确的代码。它当然可能是一个非常早期的版本。


RichJLabel 有一个getPreferredSize()适合布局。JPanel.setBounds(int, int, int, int)是调整大小的唯一方法。因此,您可以在 JPanel 中使用绝对布局(空布局)。

public class EPanel2 extends JPanel {

    private RichJLabel label = new RichJLabel("", 0);
    public EPanel2(String text) {
        super(null);
        setBackground(Color.GREEN.brighter().brighter());

        label.setFont(new Font("Univers", Font.BOLD, 48));
        label.setText(text);
        label.setHorizontalAlignment(JLabel.CENTER);
        label.setVerticalAlignment(JLabel.CENTER);
        label.setForeground(Color.BLUE);
        label.setLeftShadow(2, 2, Color.RED);
        label.setRightShadow(2, 2, Color.ORANGE);
        label.setVisible(true);
        add(label);
    }

    @Override
    public void setBounds(int x, int y, int width, int height) {
        super.setBounds(x, y, width, height);
        Dimension labelSize = label.getPreferredSize();
        int labelX = (width - labelSize.width) / 2;
        int labelY = (height - labelSize.height) / 2;
        label.setBounds(labelX, labelY, labelSize.width, labelSize.height);
    }

}
于 2012-05-18T19:03:22.983 回答