1

PNG画像から個人のJFrameを作成しようとしています。ただし、Mac OSX10.8とWindows7では動作が異なります(JDK 6を使用する必要があります)

これが私のコードです:

[...]

public Fenetre()
{

    this.setLocationRelativeTo(null);
    this.setUndecorated(true);
    this.setBackground(new Color(0,0,0,0));

    try {
        image = ImageIO.read(this.getClass().getResource("/Images/frame.png"));     
    } catch (IOException e) {
        e.printStackTrace();
    }

    this.setSize(image.getWidth(),image.getHeight());                
    this.setLayout(null);


    panel = new JPanel();
    JButton quit = new JButton("Quitter");
    panel.add(quit);
    Dimension size = panel.getPreferredSize();
    panel.setBounds(67, 45, size.width, size.height);

    this.add(panel);

    this.addMouseListener(this);
    this.addMouseMotionListener(this);
    this.setVisible(true);      

}

public void paint(Graphics g) {

    Graphics2D g2 =(Graphics2D) g;
    g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC)); // SRC_ATOP > Windows
    g2.drawImage(image, 0, 0, this);
    panel.update(panel.getGraphics());

}

[...]

Mac OSX 10.8(AlphaComposite = SRC)での結果:

http://imageshack.us/photo/my-images/15/maczr.png/

次に、Windows 7(AlphaComposite = SRC_ATOP)では、起動時と移動時に次のように表示されます。

http://imageshack.us/photo/my-images/16/windowsqu.jpg/

どのようにそれをしますか?

4

2 に答える 2

5

あなたのコードは不完全ですが、JFrame の paint() メソッドをオーバーライドしているように思えます。これを行うべきではありません (自分が何をしているのかを理解していて、super.paint(..) を呼び出す場合を除きます)!

フレームに画像を表示する場合は、次のいずれかを行います。

a) イメージを含む JLabel をフレームに追加する
b) または、paintComponent() メソッドをオーバーライドして JPanel でカスタム ペイントを実行してから、パネルをフレームに追加します。

于 2013-02-04T00:15:30.490 に答える
4

ペイントチェーンを尊重していません

public void paint(Graphics g) {
    // You must call super.paint somewhere here...

    Graphics2D g2 =(Graphics2D) g;
    g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC)); // SRC_ATOP > Windows
    g2.drawImage(image, 0, 0, this);
    panel.update(panel.getGraphics());

}

絶対に電話しないでくださいComponent#update

    panel.update(panel.getGraphics());

これは、 を呼び出す再描画マネージャーによってユーザーに代わって呼び出されますpaint

paintを呼び出しpaintComponent、ペイント チェーンを無視するということは、これらのメソッドが呼び出されておらず、非常に重要であることを意味しますpaintBorderpaintChildren

camickr が指摘したpaintように、JFrame.

代わりに、ペイントを実行できるカスタム コンポーネントを作成し、それをフレーム コンテンツ ペインとして設定します...

this.setLocationRelativeTo(null);
this.setUndecorated(true);
this.setBackground(new Color(0,0,0,0));

setContentPane(new FancyPaintPane());

pack();

そしてそのFancyPaintPane

public class FancyPaintPane extends JPanel {

    private BufferedImage image;

    public FancyPaintPane() {
        try {
            image = ImageIO.read(this.getClass().getResource("/Images/frame.png"));
        } catch (IOException e) {
            e.printStackTrace();
        }

        setOpaque(false);
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(image.getWidth(), image.getHeight());
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g); //To change body of generated methods, choose Tools | Templates.
        Graphics2D g2 = (Graphics2D) g.create();
        g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC)); // SRC_ATOP > Windows
        g2.drawImage(image, 0, 0, this);
        g2.dispose();
    }
}

Graphicsまた、元に戻さずにコンテキストを変更しないでください。これらは、同じ最上位コンテナ内のすべてのコンポーネントで共有されるリソースです。より良いアプローチは、完了したら操作して破棄できるコピーを作成することです...

また、最初にコンポーネントを透明としてマークせずに、透明な要素を持つコンポーネントを表示しようとしています。これにより、厄介なペイント アーティファクトが生成される可能性があります。JComponent#setOpaque値を渡すことを呼び出す必要がありfalseます。

nullまた、レイアウトを使用しないことを強くお勧めします。彼らは戻ってきてあなたを噛むという厄介な習慣を持っています.

簡単な例で更新

ここに画像の説明を入力

public class CirclePaneTest {

    public static void main(String[] args) {
        new CirclePaneTest();
    }

    public CirclePaneTest() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (Exception ex) {
                }

                CirclePane circlePane = new CirclePane();
                circlePane.setLayout(new BorderLayout());
                circlePane.addMouseListener(new MouseAdapter() {
                    @Override
                    public void mouseClicked(MouseEvent e) {
                        if (e.getClickCount() == 2) {
                            System.exit(0);
                        }
                    }
                });

                JLabel label = new JLabel("Look Ma, I'm a circle");
                label.setHorizontalAlignment(JLabel.CENTER);
                label.setVerticalAlignment(JLabel.CENTER);

                JFrame frame = new JFrame("Test");
                frame.setUndecorated(true);
                frame.setBackground(new Color(0, 0, 0, 0));
                frame.setContentPane(circlePane);
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(label);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class CirclePane extends JPanel {

        public CirclePane() {
            setOpaque(false);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        protected int getRadius() {
            return Math.min(getWidth(), getHeight()) - 1;
        }

        @Override
        public Insets getInsets() {

            int radius = getRadius();
            int xOffset = (getWidth() - radius) / 2;
            int yOffset = (getHeight() - radius) / 2;
            Insets insets = new Insets(
                    radius / 6,
                    radius / 6,
                    radius / 6,
                    radius / 6);

            return insets;
        }

        @Override
        protected void paintComponent(Graphics g) {

            super.paintComponent(g);

            int radius = getRadius();
            int xOffset = (getWidth() - radius) / 2;
            int yOffset = (getHeight() - radius) / 2;

            Graphics2D g2d = (Graphics2D) g.create();
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.setColor(getBackground());
            g2d.fillOval(xOffset, yOffset, radius, radius);
            g2d.setColor(Color.GRAY);
            g2d.drawOval(xOffset, yOffset, radius, radius);
            g2d.dispose();

        }
    }
}

Java 7 のコードで更新

次のコードを使用して、フレームを Java 6 で透過的に設定する必要があります。

JFrame frame = new JFrame("Test");
frame.setAlwaysOnTop(true);
frame.setUndecorated(true);
try {
    Class<?> awtUtilsClass = Class.forName("com.sun.awt.AWTUtilities");
    if (awtUtilsClass != null) {

        Method method = awtUtilsClass.getMethod("setWindowOpaque", Window.class, boolean.class);
        method.invoke(null, frame, false);
    }

} catch (Exception exp) {
}
//frame.setBackground(new Color(0, 0, 0, 0));
frame.setContentPane(circlePane);
于 2013-02-04T00:28:15.507 に答える