5

これは Windows マシンではテストしていないので、Mac マシンでのみテストしたことに注意してください。これがWindowsマシンでも発生するかどうかはわかりません...

Java アプリケーションのサイズを変更すると、コンテンツが見えなくなります。サイズ変更に修正する方法はすでに見つけましたが、ユーザーがウィンドウのサイズを変更している間は修正できませんでした。

Swing などを使用していないのは、バイナリが非常に遅くなるためです (私の意見では)。

構造は次のようになります。

  • Frame私のメインウィンドウ
    • Containerのコンテンツ ビューmain-window
      • Container-メソッドを含む -ベースのpaint(Graphics g)サブビュー

すべてのリスナーを追加したので、ウィンドウのサイズを変更した後にコンテンツ ビューMy main-windowを再描画できるようになりました。

public void componentResized(ComponentEvent e) {
    this.contentView.paint(this.contentView.getGraphics());
}

-methodを使用することpaint(getGraphics())はこれを行うのにあまり良い方法ではないことに注意してくださいrepaint()

サイズ変更中は、ペイントされたすべてのコンテンツが非表示になります。ただし、Button-instance を myに追加してContent-viewサイズを変更するMain-windowと、ボタンが非表示になりません。

「ライブ」サイズ変更イベントを追跡できます

public void componentMoved(ComponentEvent e) {
    System.out.println("Live-resize");
}
  1. サイズ変更を開始すると、このメソッドは呼び出されません。
  2. サイズ変更中に、ウィンドウのサイズを変更するピクセルごとにログに「Live-resize」が生成されます。
  3. このメソッドが呼び出されていないサイズ変更を停止すると、componentResized-method が呼び出されます。

このように「ライブ」サイズ変更イベントに再描画メソッド (または公式の再描画メソッド) を追加すると、出力は得られますが、再描画などではありません。

public void componentMoved(ComponentEvent e) {
    System.out.println("Live-resize");
    this.contentView.paint(this.contentView.getGraphics());
}

または

public void componentMoved(ComponentEvent e) {
    System.out.println("Live-resize");
    this.contentView.repaint();
}

アプリケーションをドックに最小化し、アプリケーションを再度最大化すると、同じことが起こります。これを修正するには、同じコードが必要だと思います。

私はGraphics2D何かを使用していませんGraphics

ビューを再描画する方法を教えてください。

前もってありがとう、ティム

4

3 に答える 3

7

参考までに、Swing を使用した同じプログラムを次に示します。ダブルバッファなのでJPanel、リサイズ後にマウスを離してもちらつきません。

import java.awt.*;
import java.awt.event.*;
import java.util.Random;
import javax.swing.*;

public class SwingPaint {

    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.add(new CirclePanel());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    }

    private static class CirclePanel extends JPanel {

        private static final Random r = new Random();

        public CirclePanel() {
            this.setPreferredSize(new Dimension(320, 240));
            this.setForeground(new Color(r.nextInt()));
            this.addMouseListener(new MouseAdapter() {

                @Override
                public void mousePressed(MouseEvent e) {
                    CirclePanel.this.update();
                }
            });
        }

        public void update() {
            this.setForeground(new Color(r.nextInt()));
        }

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            Dimension size = this.getSize();
            int d = Math.min(size.width, size.height) - 10;
            int x = (size.width - d) / 2;
            int y = (size.height - d) / 2;
            g.fillOval(x, y, d, d);
            g.setColor(Color.blue);
            g.drawOval(x, y, d, d);
        }
    }
}
于 2010-08-21T17:05:57.587 に答える
5

私は Swing の方がよく知っていますが、AWT と Swing でペイントするという記事では、システム トリガーによるペイントとアプリケーション トリガーによるペイントを区別しています。paint()次の例は、ウィンドウのサイズが変更されたときにシステムが を呼び出す方法と、アプリケーションがマウス イベントに応答して をrepaint()呼び出す方法を示しています。update()動作はクロスプラットフォームです。

import java.awt.*;
import java.awt.event.*;
import java.util.Random;

public class AWTPaint {

    public static void main(String[] args) {
        Frame frame = new Frame();
        frame.add(new CirclePanel());
        frame.addWindowListener(new WindowAdapter() {

            @Override
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });
        frame.pack();
        frame.setVisible(true);
    }

    private static class CirclePanel extends Panel {

        private static final Random r = new Random();

        public CirclePanel() {
            this.setPreferredSize(new Dimension(320, 240));
            this.setForeground(new Color(r.nextInt()));
            this.addMouseListener(new MouseAdapter() {

                @Override
                public void mousePressed(MouseEvent e) {
                    CirclePanel.this.repaint();
                }
            });
        }

        @Override
        public void update(Graphics g) {
            this.setForeground(new Color(r.nextInt()));
        }

        @Override
        public void paint(Graphics g) {
            Dimension size = this.getSize();
            int d = Math.min(size.width, size.height) - 10;
            int x = (size.width - d) / 2;
            int y = (size.height - d) / 2;
            g.fillOval(x, y, d, d);
            g.setColor(Color.blue);
            g.drawOval(x, y, d, d);
        }
    }
}
于 2010-08-21T16:52:17.617 に答える
0

さて、私はついにそれを修正しました。

-メソッドで毎回再描画する代わりにpaint(Graphics g)、出力をバッファリングしてその画像のみを再描画する必要があります (Obj-C のように、Java が既にそれを行っていることを望みました)。

public BufferedImage buffer;

public void redraw() {
    buffer = new BufferedImage(
            200, // height
            300, // width
            BufferedImage.TYPE_4BYTE_ABGR); // ABGR = RGBA, 4-byte (r, g, b, a) per pixel
    Graphics g = buffer.getGraphics();
    // do your drawing here
    if (this.getGraphics()) {
        // 'this' is already shown, so it needs a redraw
        this.paint(this.getGraphics()); // little hack
    }
}

public void update(Graphics g) {
    this.paint(g);
}

public void paint(Graphics g) {
    g.drawImage(buffer, 0, 0, this);
}

これで、ウィンドウを最小化して再度最大化しても、絵画は残ります。ただ、ウィンドウが 0.1 秒ほどちらつきますが、私はあまり気にしません。

于 2010-08-22T10:25:32.533 に答える