1

アプリの他の場所で使用するために、Java/Swing Cobra HTML レンダラーのコンテンツをオフスクリーンの BufferedImage にレンダリングしようとしています。

 slideViewPanel.setDocument(document, rendererContext);
 BufferedImage test = new BufferedImage(300,300,BufferedImage.TYPE_INT_RGB);
 Graphics g = test.getGraphics();
 slideViewPanel.paint(g);

g の結果の画像は、部分的にレンダリングされたページを示しています。新しいドキュメントが設定される前の HTMLFrame のコンテンツである場合もあります。場合によっては、新しいドキュメントの半分レンダリングされたバージョンです。これは、Cobra の setDocument メソッドがドキュメントの再レンダリングをスケジュールするだけであることが原因であると考えていますが、デバッガーをステップ実行していて、再レンダリングを行う 2 番目のスレッドが表示されません。ここで何が起こっているのかについての洞察を持っている人はいますか?

4

4 に答える 4

1

ページが解析されたら、コンポーネントをレイアウトする前に、すべての画像が読み込まれるまで待つ必要があります。

コンポーネントをレイアウトする前に、すべての画像の読み込みをインターセプトして、すべての画像が完全に読み込まれていることを確認します。これは、HtmlDocumentImpl.loadImageをオーバーライドすることで行いました。(DocumentBuilderImplをサブクラス化し、createDocumentをオーバーライドして機能させる必要がありました。)セマフォを使用して、image.getWItdhの結果が利用可能になるまで待機しました。

一部のスクリプトはループして戻らない可能性があるため、解析の前後にタイマーを設定する必要がありました。これを解決するより良い方法があるかどうかはわかりません。

レイアウトに関しては、カーゴカルトや実験がたくさんあり、下の切り抜きにつながるので、いくつかのものを削除してみることができます。

            htmlPanel.setVisible(true); 
    htmlPanel.setPreferredWidth(DEFAULT_PAGE_WIDTH);
    logger.info("Calculating preferred size");

    // Get the preferred heigth for the current width.
    Dimension psvz = htmlPanel.getPreferredSize();
    Dimension min = htmlPanel.getMinimumSize();

    logger.info("prf :" + psvz);
    logger.info("min :" + min);

    // Enlarge to the minimum width (with a limit)
    int width = Math.min(MAX_PAGE_WIDTH, Math.max(DEFAULT_PAGE_WIDTH,
            psvz.width));
    int height = psvz.height;

    logger.info("width :" + width);
    logger.info("heigth :" + height);

    htmlPanel.setSize(width, height);

            // actually, htmlPanel is a subclass, and this method exposes validateTree. It may work without it.
    htmlPanel.forceValidateTree(); 

    htmlPanel.doLayout();

    setImageSize(width);
    logger.info("actual size:" + htmlPanel.getSize());

JFrameがHtmlPanelを使用して、子を適切にペイントするために何をするのか理解できませんでした。子コンポーネントを使用してペイントする必要がありました。つまり、htmlPanel.getBlockRenderable()またはフレームセットのいずれかです。

画像は非同期でペイントされるため(ペイントが中止される可能性があります)、BufferedImageを使用する前に、すべての画像ペイントを完了する必要があります。

委任するgraphics2dオブジェクトを使用して、すべての画像ペイントメソッドをオーバーライドし、ペイントが完了するまで待機しました。

その後、すべての画像サイズがわかっているので、htmlが再レイアウトの恩恵を受ける可能性があることがわかりました。そのため、コンポーネントを無効にして、レイアウトとペイントを再度実行します(または、実際には、コードを2回呼び出すだけです...)

その後、BufferedImageを使用できます。たぶんもっと簡単な方法があります。

于 2010-08-19T19:32:30.340 に答える
0

電話してみるg.dispose()

于 2010-05-06T18:33:58.753 に答える
0

実際には、「component.paint(image.getGraphics());」を囲みます。次のように「SwingUtilities.invokeAndWait()」を使用します。

    try {
    SwingUtilities.invokeAndWait(new Runnable() {
        public void run() {
            component.paint(image.getGraphics());
        }
    });
    ImageIO.write(image, "png", file);
} catch (Exception e) {
    } finally {
    }
于 2010-08-27T20:49:13.960 に答える
0

画像を取得するには、コンポーネントが表示されるまで待つ必要があります。それを試してください:

   htmlPanel.setDocument(document, rendererContext);
   EventQueue.invokeLater(new Runnable() {
   public void run() {
    if (!captureImage(htmlPanel, "test.jpg")){
     EventQueue.invokeLater(this);
     System.out.println("Encolado");
    }else {
     System.out.println("capturado");
    }
   }
  });

次のようにcaptureImageを持っています:

  public static boolean captureImage(Component component, String fileName) {
  boolean captured = false;
  if (component.isVisible()) {
   Dimension size = component.getSize();
   BufferedImage image = new BufferedImage(size.width, size.height,
     BufferedImage.TYPE_INT_RGB);

   component.paint(image.getGraphics());
   captured = true;
   try {
    ImageIO.write(image, "JPEG", new File(fileName));
   } catch (IOException e) {
    e.printStackTrace();
   }
  }
  return captured;
 }
于 2010-06-09T09:30:56.943 に答える