Puis-je créer une BufferedImage à partir d’un JPanel sans rendu dans un JFrame?

Est-il possible de créer une BufferedImage à partir d’un JPanel sans d’abord la restituer dans un JFrame? J’ai cherché partout où je pouvais penser et je ne pouvais pas trouver de réponse. Quelqu’un peut-il aider?

Voici un exemple de code. Si je ne commente pas le code JFrame, mon image BufferedImage est vide.

test(){ // JFrame frame = new JFrame(); JPanel panel = new JPanel(); Dimension dim = new Dimension(50,50); panel.setMinimumSize(dim); panel.setMaximumSize(dim); panel.setPreferredSize(dim); JLabel label = new JLabel("hello"); panel.add(label); // frame.add(panel); // frame.pack(); BufferedImage bi = getScreenShot(panel); //...code that saves bi to a jpg } private BufferedImage getScreenShot(JPanel panel){ BufferedImage bi = new BufferedImage(panel.getWidth(), panel.getHeight(), BufferedImage.TYPE_INT_ARGB); panel.paint(bi.getGraphics()); return bi; } 

Voir cette réponse à Swing: Obtenir l’image de JFrame et pourquoi l’en-tête JTable n’apparaît pas dans l’image? pour obtenir des conseils sur les composants de peinture qui n’ont pas encore été rendus. Je pense que la solution à votre problème est indiquée dans l’étiquette de LabelRenderTest.java .

 JLabel textLabel = new JLabel(title); textLabel.setSize(textLabel.getPreferredSize()); 

Mettre à jour

 Dimension dim = new Dimension(50,50); panel.setSize(dim); // very important! panel.setMinimumSize(dim); panel.setMaximumSize(dim); panel.setPreferredSize(dim); // ... 

Ou voici la source complète. La taille de l’étiquette doit également être définie.

 import java.awt.Color; import java.awt.Dimension; import java.awt.image.BufferedImage; import javax.swing.*; public class RenderTest { RenderTest() { JPanel panel = new JPanel(); panel.setBackground(Color.RED); Dimension dim = new Dimension(50,50); panel.setSize(dim); panel.setMinimumSize(dim); panel.setMaximumSize(dim); panel.setPreferredSize(dim); JLabel label = new JLabel("hello"); label.setSize(label.getPreferredSize()); panel.add(label); BufferedImage bi = getScreenShot(panel); JOptionPane.showMessageDialog(null, new JLabel(new ImageIcon(bi))); } private BufferedImage getScreenShot(JPanel panel){ BufferedImage bi = new BufferedImage( panel.getWidth(), panel.getHeight(), BufferedImage.TYPE_INT_ARGB); panel.paint(bi.getGraphics()); return bi; } public static void main(Ssortingng[] args) { new RenderTest(); } } 

EDIT2: En gros, Andrew Thompson a raison dans sa réponse, un cadre n’est pas nécessaire. En même temps, il peut être pratique d’en avoir un, car un appel à pack () fera fonctionner les gestionnaires de disposition. J’ai supprimé la première partie de ma réponse d’origine, à gauche la partie relative à la mémoire. Notez que l’appel de disposer sur les graphiques est toujours nécessaire même sans cadre.

À propos de votre manque d’espace disque lors de l’utilisation de frameworks: cela ne devrait pas arriver. Vous n’avez probablement besoin d’appeler dispose () que sur les frameworks lorsque vous avez terminé. Si cela ne vous aide pas, je suggérerais de le poser dans une question distincte. De la docs dispose:

Libère toutes les ressources d’écran natives utilisées par cette fenêtre, ses sous-composants et tous ses enfants. En d’autres termes, les ressources de ces composants seront détruites, toute mémoire utilisée sera restituée au système d’exploitation, et elles seront marquées comme non affichables. (…) Remarque: Lorsque la dernière fenêtre affichable de la machine virtuelle Java (VM) est supprimée, celle-ci peut se terminer.

EDIT: encore quelques reflections:

  • La réutilisation du même object JFrame devrait également fonctionner. Ajouter un panneau, appeler un pack, créer une image, supprimer un panneau, répéter
  • n’oubliez pas d’appeler également () sur les objects graphiques que vous avez créés
  • Dans le pire des cas, vous pouvez redémarrer la machine virtuelle à partir d’un script de temps en temps.