2

ここに、paintComponent を使用して mouseClicked 位置に長方形を描画するコードがあります。出力メッセージを取得できますが、グラフィックスと .draw() に関連するものはすべて機能しません。

コード:

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

public final class testclass extends JFrame {

    static JPanel p;
    Timer t;
    int x = 1;
    int y = 1;
    int xspeed = 1;
    int yspeed = 1;

    public testclass() {
        initComponents();
        this.setBounds(100, 300, 500, 500);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        t.start();
        this.add(p);
    }

    public void initComponents() {
        final ActionListener action = new ActionListener() {

            public void actionPerformed(ActionEvent evt) {
                System.out.println("Hello!");
                p.repaint();
            }
        };

        t = new Timer(50, action);
        p = new JPanel() {

            public void paintComponent(Graphics g) {
                super.paintComponent(g);
                final Graphics2D gD = (Graphics2D) g;
                moveBALL();
                gD.drawOval(x, y, 25, 25);

                p.addMouseListener(new MouseListener() {

                    @Override
                    public void mouseReleased(MouseEvent e) {
                        System.out.println("a");
                    }

                    @Override
                    public void mousePressed(MouseEvent e) {
                        System.out.println("b");
                    }

                    @Override
                    public void mouseExited(MouseEvent e) {
                        System.out.println("c");
                    }

                    @Override
                    public void mouseEntered(MouseEvent e) {
                        System.out.println("d");
                    }

                    @Override
                    public void mouseClicked(MouseEvent e) {
                        gD.drawRect(e.getX(), e.getY(), 10, 60);
                        gD.setColor(Color.green);
                        System.out.println("clicked");
                    }
                });
            }

            void moveBALL() {
                x = x + xspeed;
                y = y + yspeed;
                if (x < 0) {
                    x = 0;
                    xspeed = -xspeed;
                } else if (x > p.getWidth() - 20) {
                    x = p.getWidth() - 20;
                    xspeed = -xspeed;
                }
                if (y < 0) {
                    y = 0;
                    yspeed = -yspeed;
                } else if (y > p.getHeight() - 20) {
                    y = p.getHeight() - 20;
                    yspeed = -yspeed;
                }
            }
        };
    }

    public static void main(String args[]) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                new testclass().setVisible(true);
                p.setBackground(Color.WHITE);
            }
        });
    }
}

このプログラムで mouseListener() を実装する適切な方法は何ですか? ありがとう。

4

2 に答える 2

3

現在のコードに関するいくつかの提案:

  • クラスの命名規則testclassに注意TestClassしてくださいTest 。すべてのクラス名は大文字で始まり、その後の新しい単語はすべて大文字になります。

  • 不必要に延長しJFrameないでください。

  • 呼び出すsetBoundsのでJFrameはなく、適切なLayoutManagerおよび/またはオーバーライドgetPreferredSize()を使用JPanelして、そのコンテンツに適合するディメンションを返します。

  • pack()可視に設定する前に、常に呼び出しJFrameます (上記を考慮してください)。

  • MouseAdapter対を使用MouseListener

  • 呼び出すmoveBall()のでpaintComponentはなくTimer、画面を再描画するものを呼び出します。わずかにデザインが改善されるだけでなく、描画メソッドで長時間実行される可能性のあるタスクを実行するべきではありません。

あなたの問題に関しては、あなたの論理が少し歪んでいると思います。

1 つのアプローチでは、Rectangle(またはRectangle2D) が独自のカスタム クラスに置き換えられます (これにより、色などの属性を格納できます)。ボールには、メソッドとその属性(および 位置など) を持つ独自のクラスもあります。メソッドを呼び出してボールを移動するたびに、それ自体が、タイマーから呼び出すよりも独自のパブリック メソッドでラップすることができます。画面を再描画します。moveBall()xyrepaint()JPanelJPanelmoveBall()

上記の修正を実装したコードの例を次に示します (分析してください。質問がある場合はお知らせください)。

ここに画像の説明を入力

import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import javax.swing.*;

public class Test {

    private MyPanel p;
    private Timer t;

    public Test() {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        initComponents();
        frame.add(p);

        frame.pack();
        frame.setVisible(true);

        t.start();
    }

    private void initComponents() {
        final ActionListener action = new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent evt) {
                p.moveEntities();//moves ball etc
                p.repaint();
            }
        };

        t = new Timer(50, action);
        p = new MyPanel();

        p.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                p.addEntity(e.getX(), e.getY(), 10, 50, Color.GREEN);
                System.out.println("clicked");
            }
        });

        p.setBackground(Color.WHITE);
    }

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

class MyPanel extends JPanel {

    int width = 300, height = 300;
    ArrayList<MyRectangle> entities = new ArrayList<>();
    MyBall ball = new MyBall(10, 10, 25, 25, Color.RED, width, height);

    void addEntity(int x, int y, int w, int h, Color c) {
        entities.add(new MyRectangle(x, y, w, h, c));
    }

    void moveEntities() {
        ball.moveBALL();
    }

    @Override
    protected void paintComponent(Graphics grphcs) {
        super.paintComponent(grphcs);
        Graphics2D g2d = (Graphics2D) grphcs;

        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        g2d.setColor(ball.getColor());
        g2d.fillOval((int) ball.x, (int) ball.y, (int) ball.width, (int) ball.height);

        for (MyRectangle entity : entities) {
            g2d.setColor(entity.getColor());
            g2d.fillRect((int) entity.x, (int) entity.y, (int) entity.width, (int) entity.height);
        }
    }

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

class MyRectangle extends Rectangle2D.Double {

    Color color;

    public MyRectangle(double x, double y, double w, double h, Color c) {
        super(x, y, w, h);
        color = c;
    }

    public void setColor(Color color) {
        this.color = color;
    }

    public Color getColor() {
        return color;
    }
}

class MyBall extends Ellipse2D.Double {

    int xspeed = 1;
    int yspeed = 1;
    Color color;
    private final int maxWidth;
    private final int maxHeight;

    public MyBall(double x, double y, double w, double h, Color c, int maxWidth, int maxHeight) {
        super(x, y, w, h);
        color = c;
        this.width = w;//set width and height of Rectangle2D
        this.height = h;
        //set max width and height ball can move
        this.maxWidth = maxWidth;
        this.maxHeight = maxHeight;
    }

    public void setColor(Color color) {
        this.color = color;
    }

    public Color getColor() {
        return color;
    }

    void moveBALL() {
        x = x + xspeed;
        y = y + yspeed;
        if (x < 0) {
            x = 0;
            xspeed = -xspeed;
        } else if (x > maxWidth - ((int) getWidth() / 2)) {// i dont like hard coding values its not good oractice and resuaibilty is diminshed
            x = maxWidth - ((int) getWidth() / 2);
            xspeed = -xspeed;
        }
        if (y < 0) {
            y = 0;
            yspeed = -yspeed;
        } else if (y > maxHeight - ((int) getHeight() / 2)) {
            y = maxHeight - ((int) getHeight() / 2);
            yspeed = -yspeed;
        }
    }
}
于 2012-12-28T13:18:06.973 に答える
0

まず、swing がコンポーネントを再描画する必要があるたびに、ペイント コンポーネントが呼び出されます。
また、ペイントが呼び出されるたびに、マウス リスナーの新しいインスタンスをパネルに追加しています。


p.addMouseListener(new MouseListener() {...} という行
を、できればパネルの初期化後に、ペイント コンポーネントの外に移動するだけです。

デフォルトのテンプレートは

JPanel p = new JPanel(){
    @Override
    public void paintComponent(Graphics g) {
    }
};
p.addMouseListener(new MouseListener()  or new MouseAdapter()
//Your overridden methods

});

お役に立てれば。

于 2012-12-28T11:10:00.340 に答える