-1

Swing でカスタムまたは既製のコントロールに変換を適用することは可能ですか? 一方では変換が許可されていますが、他方では、おそらく実装にいくつかのギャップがあります。

注意問題は、変換を使用する方法ではなく、コントロールの親から変換を適用する方法に関するものです。つまり、変換は親によって発行される必要がありますが、子はそれに従う必要があります。標準の Swing コントロールを変換する方法、または PARENT 変換に従うカスタム コントロールを作成する方法を教えてください。

子を描画する前に変換を適用Graphicsし、機能しない簡単な例:

public class Tester_TransformDuringPaint_01 {

private static Logger log = LoggerFactory.getLogger(Tester_TransformDuringPaint_01.class);  
private static class JPanelEx extends JPanel {
private AffineTransform transform = new AffineTransform();

    public AffineTransform getTransform() {
        return transform;
    }

    public void setTransform(AffineTransform transform) {
        this.transform = transform;
    }       

    @Override
    public void paintComponent(Graphics g) {
        Graphics2D g2 = (Graphics2D) g;
        AffineTransform savedTransform = g2.getTransform();
        g2.transform(transform);
        super.paintComponent(g);            
        g2.drawOval(0, 0, 100, 100);            
        g2.setTransform(savedTransform);

    }

    @Override
    protected void paintChildren(Graphics g) {
        Graphics2D g2 = (Graphics2D) g;
        AffineTransform savedTransform = g2.getTransform();
        g2.transform(transform);
        super.paintChildren(g);
        g2.setTransform(savedTransform);
    }
}

public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {             
            JButton button = new JButton("Button");
            button.setBounds(0,20,100,60);              
            JPanelEx panel = new JPanelEx();
            panel.setLayout(null);
            panel.setBounds(10, 10, 640, 480);
            panel.setBackground(Color.PINK);
            panel.setTransform(AffineTransform.getScaleInstance(2, 1));
            panel.add(button);
            JFrameEx frame = new JFrameEx();
            frame.setLayout(null);
            frame.add(panel);               
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);               
            frame.setSize(0.5);
            frame.center();
            frame.setVisible(true);
        }
    });
}
}

以下を描画します。

ここに画像の説明を入力

ボタンの左半分は生きているように見え、大きな部分は死んでいるように見えます。

これは、API のさまざまな部分がさまざまなアプローチでボタンを描画するためです。

修正されたオライリー ハック 51

以下は @lbalazscs の例に基づいたコードで、「範囲内」であっても変換が機能しないことを示しています。

public class BackwardsJButton extends JButton {

public BackwardsJButton(String text) {
    super(text);
}

public void paint(Graphics g) {
    if (g instanceof Graphics2D) {
        Graphics2D g2 = (Graphics2D) g;
        AffineTransform savedTransform = g2.getTransform();
        AffineTransform flipTrans = new AffineTransform();
        double widthD = (double) getWidth();
        //flipTrans.setToTranslation(widthD, 0);
        //flipTrans.scale(-2.0, 1);
        flipTrans.scale(0.5, 1);
        g2.transform(flipTrans);
        super.paint(g);
        g2.setTransform(savedTransform);
    } else {
        super.paint(g);
    }
}

public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        @Override
        public void run() {
            buildFrame();
        }
    });
}

private static void buildFrame() {
    JFrame f = new JFrame("Test");
    f.setLayout(new FlowLayout());
    f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

    f.add(new BackwardsJButton("BackwardsJLabel"));

    f.pack();
    f.setLocationRelativeTo(null);
    f.setVisible(true);
}
}

出力は次のとおりです (Swing のバグはマウス ホバー コード内にあるため、表示するにはウィンドウのサイズを変更してマウスを移動する必要がある場合があります。

ここに画像の説明を入力

4

1 に答える 1

4

Swingを悪用する革新的なアイデアがあります:)

コンポーネントの描画中にアフィン変換を適用することは可能ですが、コンポーネントの境界内で満足している場合に限ります (たとえば、テキストをミラー化することができます)。ペイントをオーバーライドすると、コンポーネントの描画方法が変更されますが、サイズは完全に他の変数に依存するため、コンポーネントのサイズは変更されません。また、境界の外に確実に描画することはできません。

グラフィック的に成功したとしても、元の場所でマウスクリックが予想されるため、既製のコンポーネントのペイントを変換することはお勧めできません。

同じ Graphics オブジェクトが他のコンポーネントの描画に使用されるため、変換が完了したら変換をリセットする必要があることに注意してください。

AffineTransform savedTransform = g.getTransform();
g.setTransform(specialTransform);
... your drawing here
g.setTransform(savedTransform);

編集: これは、変換されたコンポーネントの完全な実行例です

import javax.swing.*;
import javax.swing.plaf.metal.MetalButtonUI;
import java.awt.*;
import java.awt.geom.AffineTransform;

public class ScaledButton extends JButton {

    public ScaledButton(String text) {
        super(text);
    }

    public void paintComponent(Graphics g) {
        Graphics2D g2 = (Graphics2D) g;
        Color savedColor = g2.getColor();
        g2.setColor(getBackground());
        g2.fill(new Rectangle(0, 0, getWidth(), getHeight()));
        g2.setColor(savedColor);

        AffineTransform backup = g2.getTransform();
        g2.scale(0.5, 1);
        super.paintComponent(g);
        g2.setTransform(backup);
    }

    @Override
    protected void paintBorder(Graphics g) {
        Graphics2D g2 = (Graphics2D) g;
        AffineTransform backup = g2.getTransform();
        g2.scale(0.5, 1);
        super.paintBorder(g);
        g2.setTransform(backup);
    }



    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                buildFrame();
            }
        });
    }

    private static void buildFrame() {
        JFrame f = new JFrame("Test");
        f.setLayout(new FlowLayout());
        f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

        f.add(new ScaledButton("ScaledButton"));

        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }
}
于 2013-02-22T22:35:43.777 に答える