Reputation: 171
I'm working on a customizable control window. The idea is similar to the customizable toolbars in many document editing/creation programs: you have a "source" area with a selection of various controls, and a "destination" space into which the controls can be dragged and dropped.
I figured I would implement this by having the "source" area contain images corresponding to how the controls would render; you could drag the images into the destination area, at which point they become active controls. I don't want to make the controls directly draggable because they may be complicated entities (e.g. with multiple text boxes or buttons), and I don't want to have to deal with making all of those "sub-controls" non-operable when in the draggable state.
Unfortunately, I can't figure out how to make an image-ified version of the control that I can draw to the screen. It seems that unless I actually allow a control to be visible on-screen, it won't paint properly, and thus I can't create an icon from it. Here's my naive implementation:
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);
}
}
I do get reasonable sizes from button.getPreferredSize(), but nothing is drawn.
Here's a version where the generation of the label is delayed until after the button is drawn on-screen:
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();
}
}
This does work (though you have to resize the window to see the drawn label, admittedly). However, it's kind of useless because I have to have the actual component be visible before I can create the image of that component.
How do I generate images of components, as they would be drawn if they were visible on-screen, without actually making them visible on-screen?
Thanks in advance!
Upvotes: 3
Views: 372
Reputation: 324147
Check out the Screen Image class.
It allows you to create an image of the component even when the component is not visible on the screen.
Basically in order for the components to be painted you need to:
Upvotes: 1