【问题标题】:Force paintAll() to draw an invisible JPanel and its components?强制paintAll() 绘制一个不可见的JPanel 及其组件?
【发布时间】:2012-12-22 08:56:34
【问题描述】:

我正在将一系列 JPanel 打印到 Printable,这是基本打印界面,它提供了一个图形对象,您可以绘制您想要打印的内容。如果我有一个“实时”的 JPanel,它在 UI 的某个地方,一切都很好。

但是,如果我创建一个 JPanel 并且从未将其添加到 UI 中,那么 printAll() 似乎什么都不做。将代码简化为 SSCCE:

import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class SSCCEPaintInvisible
{
    public static void main(String[] args)
    {
        /* Create an JPanel with a JLabel */
        JPanel panel = new JPanel();
        //panel.setLayout(new FlowLayout());
        JLabel label = new JLabel("Hello World");
        panel.add(label);
        //label.invalidate();
        //panel.invalidate();

        /* Record a picture of the panel */
        BufferedImage image = new BufferedImage(100, 100, BufferedImage.TYPE_4BYTE_ABGR);
        Graphics g = image.getGraphics();

        /* Draw something to ensure we're drawing */
        g.setColor(Color.BLACK);
        g.drawLine(0, 0, 100, 100);

        /* Attempt to draw the panel we created earlier */ 
        panel.paintAll(g);  // DOES NOTHING. :(

        /* Display a frame to test if the graphics was captured */
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JLabel label2 = new JLabel( new ImageIcon(image) );
        frame.add(label2);
        frame.pack();

        frame.setVisible(true);
            // shows ONLY the black line we drew in the Graphics
    }
}

如果我为面板创建 JFrame 并将面板添加到 JFrame 并在调用 paintAll() 之前使 JFrame 可见,则代码会按预期将 UI 捕获到 Graphic。当然,这会在您的屏幕上闪烁一个 JFrame 来打印它。

有没有什么方法可以将一个从未添加到 UI 中的 JPanel 渲染成一个 Graphics 对象?谢谢!

【问题讨论】:

  • “但是,如果我创建了一个 JPanel 并且从未将它添加到 UI 中,printAll() 似乎什么都不做” 请查看 this thread 以获取有关绘制未实现组件的提示。
  • +1 到 SSCCE。虽然当您创建一个 SSCCE 时,请务必遵守使用 Event Dispatch Thread 的 Swing 编程最佳实践,而不是将所有内容都放在 main 方法上。
  • 顺便说一句 - 除了从左上角到 100,100 的黑线之外,您希望在图像中看到什么?
  • @AndrewThompson,JPanel 中 JLabel 的“Hello World”。
  • 哦,对了,请原谅我的愚蠢。 :P

标签: java swing graphics printing bufferedimage


【解决方案1】:

来自@Kleopatra 答案的提示。

import java.awt.*;
import java.awt.image.BufferedImage;
import javax.swing.*;

public class SSCCEPaintInvisible
{
    public static void main(String[] args)
    {
        /* Create an JPanel with a JLabel */
        JPanel panel = new JPanel();

        JLabel label = new JLabel("Hello World");
        panel.add(label);
        // Next 3 are very important!
        panel.setSize(panel.getPreferredSize());
        panel.addNotify();
        panel.doLayout();

        /* Record a picture of the panel */
        BufferedImage image = new BufferedImage(100, 100, BufferedImage.TYPE_4BYTE_ABGR);
        Graphics g = image.getGraphics();

        /* Draw something to ensure we're drawing */
        g.setColor(Color.BLACK);
        g.drawLine(0, 0, 100, 100);

        /* Attempt to draw the panel we created earlier */
        panel.paintAll(g);  // DOES NOTHING. :(

        /* Display a frame to test if the graphics was captured */
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JLabel label2 = new JLabel( new ImageIcon(image) );
        frame.add(label2);
        frame.pack();

        frame.setVisible(true);
            // shows ONLY the black line we drew in the Graphics
    }
}

正如@GagandeepBali 所指出的,这个 GUI 不是在 EDT 上创建的。如果未在 EDT 上完成对 GUI 的更改,结果将是不可预测的。有关更多详细信息,请参阅 Concurrency in Swing 和特别是 Initial Threads

【讨论】:

  • 希望有朝一日我能掌握这些知识,从而真正否决您的帖子 :-),但更怀疑这一天即将到来。但希望我每天都能学到新东西:-)
  • @GagandeepBali “对你的帖子投反对票”(轻笑)你会惊讶于我发布的一些内容显然“在你的雷达之下”。获取糟糕的代码,修复一两行代码并将其原样转储(有时是我的理念)。对于 OP - 不要混淆,您的代码并不“可怕” - 但这里发布的大部分代码都是问题 is.
  • @GagandeepBali(和 utopianheaven)见最后一段。 :)
猜你喜欢
  • 1970-01-01
  • 2013-08-21
  • 2023-03-07
  • 2013-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-16
  • 1970-01-01
相关资源
最近更新 更多