创建不可见组件的图像

Create image of invisible component

我正在开发一个可自定义的控件 window。这个想法类似于许多文档 editing/creation 程序中的可自定义工具栏:您有一个 "source" 区域,可以选择各种控件,还有一个 "destination" space 控件可以拖放。

我想我可以通过让 "source" 区域包含与控件呈现方式相对应的图像来实现这一点;您可以将图像拖到目标区域,此时它们成为活动控件。我不想让控件直接可拖动,因为它们可能是复杂的实体(例如,带有多个文本框或按钮),而且我不想让所有这些 "sub-controls" 不可操作当处于可拖动状态时。

不幸的是,我不知道如何制作可以在屏幕上绘制的控件的图像化版本。似乎除非我真的允许控件在屏幕上可见,否则它不会正确绘制,因此我无法从中创建图标。这是我天真的实现:

public class Demo extends JFrame {
   public static void main(String[] args) {
      new Demo();
   }

   public Demo() {
      JButton button = new JButton("Hello, world!");
      BufferedImage buf = new BufferedImage(200, 200, BufferedImage.TYPE_INT_ARGB);
      Graphics g = buf.getGraphics();
      button.paint(g);
      g.dispose();
      ImageIcon icon = new ImageIcon(buf.getSubimage(0, 0,
               button.getPreferredSize().width, button.getPreferredSize().height));
      System.out.println("Icon has size " + icon.getIconWidth() + "x" + icon.getIconHeight());
      add(new JLabel(icon));
      pack();
      setVisible(true);
   }
}

我确实从 button.getPreferredSize() 得到了合理的尺寸,但没有绘制任何东西。

这是一个标签生成延迟到按钮在屏幕上绘制之后的版本:

public class Demo extends JFrame {
   public static void main(String[] args) {
      new Demo();
   }

   private JButton button_;
   private JLabel label_ = null;
   public Demo() {
      button_ = new JButton("Hello, world!");
      button_.addActionListener(new ActionListener() {
         @Override
         public void actionPerformed(ActionEvent event) {
            updateLabel();
         }
      });
      add(button_);
      pack();
      setVisible(true);
   }

   private void updateLabel() {
      BufferedImage buf = new BufferedImage(200, 200, BufferedImage.TYPE_INT_ARGB);
      Graphics g = buf.getGraphics();
      button_.paint(g);
      g.dispose();
      ImageIcon icon = new ImageIcon(buf.getSubimage(0, 0,
               button_.getPreferredSize().width, button_.getPreferredSize().height));
      System.out.println("Icon has size " + icon.getIconWidth() + "x" + icon.getIconHeight());          
      if (label_ != null) {
         remove(label_);
      }
      label_ = new JLabel(icon);
      label_.setPreferredSize(new Dimension(icon.getIconWidth(), icon.getIconHeight()));
      add(label_);
      pack();
   }
} 

这确实有效(诚然,您必须调整 window 的大小才能看到绘制的标签)。但是,这有点没用,因为我必须先让实际组件可见,然后才能创建该组件的图像。

如何生成组件的图像,就像它们在屏幕上可见时绘制的那样,而不实际使它们在屏幕上可见?

提前致谢!

查看 Screen Image class。

即使组件在屏幕上不可见,它也允许您创建组件的图像。

基本上,为了绘制组件,您需要:

  1. 给组件一个尺寸
  2. 在面板上布置组件。