希望您能为我的drawString中的问题提供帮助。

我在Factory类中进行一些绘制,并返回带有String的BufferedImage。

public class Factory {

   public BufferedImage create() {
       TempPanel tempPanel = new TempPanel(new Dimension(100, 100));
       return tempPanel.createImage();
   }

   private class TempPanel extends JPanel {

       public TempPanel(Dimension d) {
           this.setVisible(true);
           this.setSize(d);
       }

       public BufferedImage createImage() {
           BufferedImage bi = new BufferedImage(this.getSize().getWidth(), this.getSize().getHeight(), BufferedImage.TRANSLUCENT);
           this.paintComponent(bi.createGraphics());
           return bi;
       }

       @Override
       public void paintComponent(Graphics g) {
           super.paintComponents(g);
           // General setup
           Graphics2D g2 = (Graphics2D) g;
           g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

           // Transparent Background
           g2.setComposite(AlphaComposite.Clear);
           g2.fillRect(0, 0, graphicalObject.width, graphicalObject.height);
           g2.setComposite(AlphaComposite.Src);

           // Different settings for a certain graphical object
           g2.setFont(new Font("TimesRoman", Font.PLAIN, 12);

           // Actual drawing
           g2.drawString("Test", 0, 0);
       }
    }
}


然后我还有一个JPanel,应该在其中绘制此图像:

public class Label extends JPanel {
   // ...
   @Override
   public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        Factory factory = new Factory();
        BufferedImage img = factory.create();
        g2.drawImage(img, 0, 0, null);
   }
}


问题在于,只有在我最小化并还原窗口后,文本才会出现,但是一旦我开始在窗口内移动鼠标,文本就会再次消失。
当我调用drawRect()而不是drawString()时,一切正常吗?

有人可以告诉我为什么吗?

谢谢!

最佳答案

有很多事情让我“奇怪” ...

首先,您正在创建一个新的Graphics上下文,但是您没有对其进行处理。这可能会使资源保持开放状态,并可能实际上阻止了在某些操作系统上呈现内容...

所以代替...

BufferedImage bi = new BufferedImage(this.getSize().getWidth(), this.getSize().getHeight(), BufferedImage.TRANSLUCENT);
this.paintComponent(bi.createGraphics());


你应该做些更像...

BufferedImage bi = new BufferedImage(getWidth(), getHeight(), BufferedImage.TRANSLUCENT);
Graphics2D g2d = bi.createGraphics();
this.paintComponent(g2d);
g2d.dispose();


其次,文本的渲染方式与大多数其他元素不同,也就是说,文本不是从x / y开始并向下/向右渲染,在大多数情况下,它是从x / y开始并稍稍向上/向右渲染。实际坐标基于Font s FontMetrics getAscent值...

所以,而不是...

            g2.setFont(new Font("TimesRoman", Font.PLAIN, 12));
            // Actual drawing
            g2.drawString("Test", 0, 0);


你应该做些更像...

            g2.setFont(new Font("TimesRoman", Font.PLAIN, 12));
            FontMetrics fm = g2.getFontMetrics();
            // Actual drawing
            g2.drawString("Test", 0, fm.getAscent());


请参阅Working with Text APIs或更多详细信息...

第三,JComponent以及从其扩展而来的所有内容都是ImageObsever,这一点很重要,因为并非已绘制的所有内容都可以立即显示,因此有时需要进一步处理,而不必处理让自己烦恼的是,您可以委派责任,所以不用...

g2.drawImage(img, 0, 0, null);


你应该做些更像...

g2.drawImage(img, 0, 0, this);


这使组件可以侦听基础图像并响应可能发生在图像数据上的任何更改并更新自身。

……

private class TempPanel extends JPanel {

   public TempPanel(Dimension d) {
       this.setVisible(true);
       this.setSize(d);
   }

   public BufferedImage createImage() {
       BufferedImage bi = new BufferedImage(this.getSize().getWidth(), this.getSize().getHeight(), BufferedImage.TRANSLUCENT);
       this.paintComponent(bi.createGraphics());
       return bi;
   }

   @Override
   public void paintComponent(Graphics g) {
       super.paintComponents(g);
       // General setup
       Graphics2D g2 = (Graphics2D) g;
       g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

       // Transparent Background
       g2.setComposite(AlphaComposite.Clear);
       g2.fillRect(0, 0, graphicalObject.width, graphicalObject.height);
       g2.setComposite(AlphaComposite.Src);

       // Different settings for a certain graphical object
       g2.setFont(new Font("TimesRoman", Font.PLAIN, 12);

       // Actual drawing
       g2.drawString("Test", 0, 0);
   }
}


令我惊讶的是... Swing组件是要附加到渲染它们的本机同位体上的,它们还经过了优化,不会在无法显示时进行绘制,这可能会放弃渲染...

实际上,您可以使用...

public static class Factory {

    private static Renderer renderer;

    public BufferedImage create() {

        if (renderer == null) {
            renderer = new Renderer(new Dimension(100, 100));
        }

        return renderer.createImage();
    }

    private class Renderer {

        private Dimension size;

        public Renderer(Dimension size) {
            this.size = size;
        }

        public BufferedImage createImage() {
            BufferedImage bi = new BufferedImage(size.width, size.height, BufferedImage.TRANSLUCENT);
            Graphics2D g2 = bi.createGraphics();
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

            // Transparent Background
            g2.setComposite(AlphaComposite.Clear);
            g2.fillRect(0, 0, graphicalObject.width, graphicalObject.height);
            g2.setComposite(AlphaComposite.Src);
            // Different settings for a certain graphical object
            g2.setFont(new Font("TimesRoman", Font.PLAIN, 12));
            FontMetrics fm = g2.getFontMetrics();

            // Actual drawing
            g2.drawString("Test", 0, fm.getAscent());
            g2.dispose();
            return bi;
        }

    }
}


它将使实际绘画与其他任何东西脱离,并为您提供对其的控制...

10-07 23:06