2011-12-06 3 views
0

1024x768で表示されると思われるグラフィックスを持つアプリケーションがあります。java JFrameは、仮想描画スペースでUI表示を拡大しました

:私の試みは、以下のようにしたJFrameコンテナのpaintメソッドをオーバーライドしていることを達成するために

私はすべての描画コード、位置計算などを書き換えることなく、サイズにアプリケーションが柔軟にしたい。..

@Override 
public void paint(Graphics g) 
{ 
    BufferedImage img = new BufferedImage(this.desiredWidth, this.desiredHeight, BufferedImage.TYPE_INT_ARGB); 

    Graphics2D gi = (Graphics2D) img.getGraphics(); 
    gi.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_VRGB); 
    gi.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); 
    gi.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY); 

    super.paint(gi); 
    gi.dispose(); 

    ((Graphics2D) g).drawImage(img, screenScale, null); 

} 

screenScaleは、ターゲットサイズに応じて適切なスケーリングを行うコンストラクタで作成されたAffineTransformオブジェクトです。

問題は次のとおりです。私の子コンポーネントは描画され、拡大/縮小されますが、親JFrameの制限があります。親フレームのサイズが640x480の場合、それに追加した子レイヤーは、ペイントしている1024x768のBufferedImageの640x480の部分だけを描画できます。 子供は常にこの値を境界として持つため、JFrameの親のgetPreferredSizeを子コンポーネントが使用する場所があると思います。だから、私のスケーリング戦略は、描画のために配信されるグラフィックスオブジェクトの境界を完全に無視するため、子どものペイント動作と矛盾します。

最終的には、目標サイズが「仮想」画面サイズよりも小さい場合、私の子レイヤー(重要なのはjpanelから派生しています)が途切れることがあります。

グラフィックスの境界が無視されるという奇妙な振る舞いを回避するには、誰かがより良い解決策やヒントを提供できますか?

編集:更新されたスケーリングされていない出力を有する上記のコードの結果、expectet出力し、得られた出力

expected output resulted output

更新:このコードが動作しているいくつかの理由のために働いてテストコード

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.RenderingHints; 
import java.awt.event.MouseEvent; 
import java.awt.event.MouseListener; 
import java.awt.event.MouseMotionListener; 
import java.awt.event.MouseWheelEvent; 
import java.awt.event.MouseWheelListener; 
import java.awt.geom.AffineTransform; 
import java.awt.image.BufferedImage; 
import javax.print.attribute.standard.OrientationRequested; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.SwingUtilities; 

public class AffineTransformTest 
{ 

private static TransformingFrame canvas; 
private static JButton button; 
private static TestLayer layer; 

public static void main(String[] args) 
{ 
    canvas = new TransformingFrame(); 
    canvas.addMouseWheelListener(new ScaleHandler()); 

    layer=new TestLayer(canvas.originalSize); 
    canvas.getContentPane().add(layer); 
    layer.setVisible(true); 
    button = new JButton("asdf"); 
    canvas.setUndecorated(true); 
    button.setVisible(true); 
    canvas.getContentPane().add(button); 


    canvas.pack(); 



    canvas.setLayout(new BorderLayout()); 
    canvas.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 
    canvas.setPreferredSize(canvas.originalSize); 
    canvas.setSize(canvas.originalSize); 
    canvas.setLayout(null); 

    canvas.setVisible(true); 
    canvas.validate(); 
} 

@SuppressWarnings("serial") 
private static class TransformingFrame extends JFrame 
{ 
    private double scale; 
    private final Dimension originalSize; 
    private AffineTransform tx = new AffineTransform(); 

    TransformingFrame() 
    { 
     originalSize=new Dimension(800,600); 
     scale = 1; 
    } 

    @Override 
    public void paint(Graphics g) 
    { 
     BufferedImage offscreenBuffer=new BufferedImage(originalSize.width,originalSize.height, BufferedImage.TYPE_INT_ARGB); 
     Graphics bufferGraphics=offscreenBuffer.getGraphics(); 
     super.paint(bufferGraphics); 
     bufferGraphics.dispose(); 

     ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_VRGB); 
     ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); 
     ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY); 
     g.setColor(Color.black); 
     g.fillRect(0, 0, getWidth(), getHeight()); 
     ((Graphics2D) g).drawImage(offscreenBuffer, tx,null); 
    } 
    @Override 
    public void paintComponents(Graphics g) 
    { 
     BufferedImage offscreenBuffer=new BufferedImage(originalSize.width,originalSize.height, BufferedImage.TYPE_INT_ARGB); 
     Graphics bufferGraphics=offscreenBuffer.getGraphics(); 
     super.paintComponents(bufferGraphics); 
     bufferGraphics.dispose(); 

     ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_VRGB); 
     ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); 
     ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY); 
     g.setColor(Color.black); 
     g.fillRect(0, 0, getWidth(), getHeight()); 
     ((Graphics2D) g).drawImage(offscreenBuffer, tx,null); 

    } 
    @Override 
    public void paintAll(Graphics g) 
    { 
     BufferedImage offscreenBuffer=new BufferedImage(originalSize.width,originalSize.height, BufferedImage.TYPE_INT_ARGB); 
     Graphics bufferGraphics=offscreenBuffer.getGraphics(); 
     super.paintAll(bufferGraphics); 
     bufferGraphics.dispose(); 

     ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_VRGB); 
     ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); 
     ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY); 
     g.setColor(Color.black); 
     g.fillRect(0, 0, getWidth(), getHeight()); 
     ((Graphics2D) g).drawImage(offscreenBuffer, tx,null); 
} 

} 

@SuppressWarnings("serial") 
private static class TestLayer extends JPanel{ 

public TestLayer(Dimension originalSize) 
{ 
    this.setPreferredSize(originalSize); 
    this.setSize(originalSize); 
    setOpaque(false); 
    setDoubleBuffered(false); 
} 

@Override 
public void paint(Graphics g) 
{ 
    Graphics2D ourGraphics = (Graphics2D) g; 
    super.paint(ourGraphics); 
    ourGraphics.setColor(Color.green); 
    ourGraphics.fillRect(0, 0, getWidth(), getHeight()); 
    ourGraphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 
    ourGraphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); 
    ourGraphics.setColor(Color.BLACK); 

    ourGraphics.drawRect(50, 50, 50, 50); 
    ourGraphics.fillOval(100, 100, 100, 100); 
    ourGraphics.drawString("Test Affine Transform", 50, 30); 
    ourGraphics.drawString(canvas.tx.toString(), 50, 250); 
} 

} 

private static class ScaleHandler implements MouseWheelListener 
{ 
    public void mouseWheelMoved(MouseWheelEvent e) 
    { 
     if (e.getScrollType() == MouseWheelEvent.WHEEL_UNIT_SCROLL) 
     { 

      // make it a reasonable amount of zoom 
      // .1 gives a nice slow transition 
      canvas.scale += (.1 * e.getWheelRotation()); 
      // don't cross negative threshold. 
      // also, setting scale to 0 has bad effects 
      canvas.scale = Math.max(0.00001, canvas.scale); 
      canvas.tx.setTransform(new AffineTransform()); 
      canvas.tx.scale(canvas.scale, canvas.scale); 
      canvas.setPreferredSize(new Dimension((int)(canvas.originalSize.width*canvas.scale),(int)(canvas.originalSize.height*canvas.scale))); 
      canvas.setSize(new Dimension((int)(canvas.originalSize.width*canvas.scale),(int)(canvas.originalSize.height*canvas.scale))); 
      canvas.validate(); 
      canvas.repaint(); 
     } 
    } 
} 

} 

(ボタンを消す以外は)..多分私のエラーは子供の層のどこか他のところです..私はそのことを調べるつもりです

私は子供のパネルがpaint(Graphics g)メソッドで取得する描画の制限が、親のサイズ以上の描画を許可しないという結論に達しました。この例では動作しますが、完全なアプリケーションでは動作しません。デモアプリケーションではなく、アプリケーション上で動作するように設定されているようです。

答えて

2

私の親フレームは次元640×480を持っているのであれば、私はそれに追加した子レイヤは1024×768

の640×480の一部の内側に描くことができますJFrame作成 - >そこJScrollPane入れを - >JScrollPane置くために:オーバーライドpaintComponentn(Graphics g)ないpaint(Graphics g)

1)JPanelまたはJComponent UI委譲があります:2)あなたはコンポーネントがスケーリンググラフィックスコンテキストにレンダリングすることができ、観察しましたが、結果は効果的に無用であるので、次により良い方法がJLabel

+0

私はコード内にラベルを使用せず、同様にPaintComponentsとPaintAllをオーバーライドしますが、部分的に機能します。唯一の問題は、スケーリングが行われる前にJPanelに追加したレイヤの部分が途切れてしまうことです。 – anubisviech

+0

@anubisviech冗談なしで、あなたの質問を編集し、http://sscce.org/フォームにコードを投稿する必要があります。 – mKorbel

+0

ヒントのおかげで、明日コンパイル可能なサンプルを投稿しようとしています – anubisviech

1

からIconとしてBufferedImage置かれ、およそBufferedImageを書きました変更されたジオメトリの知識はありません。 @ mKorbelが示唆するように、JScrollPaneは伝統的な代替手段です。

このgameで使用されているスキームや、このscalable labelで使用されているスキームを参照してください。独自のコンポーネントを作成したい場合は、ScaledViewに示されている方法を適用することができます。

+0

すべてのレイヤーを拡大/縮小するのではなく、すべてのシーンを描画し、最終的なパスでスケーリングしたい場合は、スケーリングされたViewがソリューションになる可能性があります。 – anubisviech

0

私の問題は、これについていくつかのpplに聞いて完全に解決しました。 ソリューションでした:

setScreenScale(AffineTransform.getScaleInstance((double) width/(double) desiredWidth, (double) height/(double) desiredHeight)); 
    setContentPane(new ScaledPane(this)); 
:あなたのcontentPaneに、そのクラスのインスタンスを設定し、その後

private class ScaledPane extends JPanel 
{ 
    public ScaledPane(Window parent) 
    { 
     super(); 
     setPreferredSize(new Dimension(parent.getDesiredWidth(), parent.getDesiredHeight())); 
     setSize(this.getPreferredSize()); 
    } 

    @Override 
    public void paint(Graphics g) 
    { 
     Graphics2D g2 = (Graphics2D) g.create(0, 0, getWidth(), getHeight()); 
     g2.setTransform(screenScale); 
     g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); // 
     System.out.println(g2.getClip()); 
     super.paint(g2); 
    } 
} 

: 1. はあなたが描いて、そこに操作をすることができる新しいクラス、例を作成します。

これを実行した後、ウィンドウのコンポーネントとして、内容ペイントのペイントメソッドが、そこに設定されている新しいグラフィックスオブジェクトで描画するようになりました。

任意の子の移動式または位置を操作することなく、ウィンドウを任意のサイズに拡大縮小できます。

関連する問題