6

マウスをドラッグすると線を描画し、マウスを押す(離す)とドットを描画する単純なクラスがあります。

アプリケーションを最小化して復元すると、最後のドット (ピクセル) を除いてウィンドウの内容が消えます。super.paint(g)ウィンドウが変わるたびに背景を再描画する方法は理解していますが、使用しても使用しなくても結果は同じようです。それらの 2 つの違いは、それを使用しない場合、ウィンドウに 1 ピクセル以上がペイントされますが、すべてのペインティングではないことです。どうすればこれを修正できますか?

これがクラスです。

package painting;

import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import javax.swing.JFrame;
import javax.swing.JPanel;

class CustomCanvas extends Canvas{   
    Point oldLocation= new Point(10, 10);
    Point location= new Point(10, 10);
    Dimension dimension = new Dimension(2, 2);     
    CustomCanvas(Dimension dimension){  
        this.dimension = dimension;   
        this.init();
        addListeners();
    }    
    private void init(){                     
        oldLocation= new Point(0, 0);
        location= new Point(0, 0);
    }
    public void paintLine(){
        if ((location.x!=oldLocation.x) || (location.y!=oldLocation.y)) {         
            repaint(location.x,location.y,1,1);                                   
        } 
    }
    private void addListeners(){
        addMouseListener(new MouseAdapter(){
            @Override
            public void mousePressed(MouseEvent me){                   
                oldLocation = location;
                location = new Point(me.getX(), me.getY());
                paintLine();
            }
            @Override
            public void mouseReleased(MouseEvent me){                
                oldLocation = location;
                location = new Point(me.getX(), me.getY());
                paintLine();
            }
        });
        addMouseMotionListener(new MouseMotionAdapter() {
            @Override
            public void mouseDragged(MouseEvent me){                
                oldLocation = location;
                location = new Point(me.getX(), me.getY());
                paintLine();
            }
        });
    }
    @Override
    public void paint(Graphics g){  
        super.paint(g);
        g.setColor(Color.red);       
        g.drawLine(location.x, location.y, oldLocation.x, oldLocation.y);                
    }
    @Override
    public Dimension getMinimumSize() {
        return dimension; 
    }
    @Override
    public Dimension getPreferredSize() {
        return dimension;
    }

}
class CustomFrame extends JPanel {
    JPanel displayPanel = new JPanel(new BorderLayout());
    CustomCanvas canvas = new CustomCanvas(new Dimension(200, 200));        
    public CustomFrame(String titlu) {            
        canvas.setBackground(Color.white);
        displayPanel.add(canvas, BorderLayout.CENTER);            
        this.add(displayPanel);
    }   
}
public class CustomCanvasFrame {
    public static void main(String args[]) {
        CustomFrame panel = new CustomFrame("Test Paint");
        JFrame f = new JFrame();
        f.add(panel);
        f.pack();
        SwingConsole.run(f, 700, 700);
    }
}
4

4 に答える 4

5

マウスを押したりドラッグしたりするたびに、(1 つではなく) すべてのポイントを描画するということではありませんか?

はい。ただし、@Dave のアプローチは、数千のノードに対して完全に満足のいくものですGraphPanelさらに、レンダラーで使用され、ここに示されているフライウェイト パターンを検討してください。JTable

補遺: あなたの質問に焦点を当てると、以下のバリエーションは、システムによってトリガーされるペイントとアプリによってトリガーされるペイントAWTPaintingの違いを示している可能性があります。マウスがドラッグされると、が呼び出され、 ;が呼び出されます。これはアプリによってトリガーされます。ウィンドウのサイズを変更すると、 のみが呼び出されます (赤い数字は描画されません)。これはシステムによってトリガーされます。サイズ変更後にマウスを離すと、ちらつきが発生することに注意してください。repaint()update()paint()paint()

ちらつきは通常、コンポーネント全体の背景がクリアされて再描画されるときに発生します。

 4. コンポーネントがをオーバーライドしなかっupdate()た場合、 のデフォルトの実装がupdate()コンポーネントの背景をクリアし (軽量コンポーネントでない場合)、単に を呼び出しますpaint()

AWTペインティング

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Panel;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.List;

public class AWTPainting {

    public static void main(String args[]) {
        CustomPanel panel = new CustomPanel();
        Frame f = new Frame();
        f.addWindowListener(new WindowAdapter() {

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

class CustomPanel extends Panel {

    public CustomPanel() {
        this.add(new CustomCanvas(new Dimension(320, 240)));
    }
}

class CustomCanvas extends Canvas {

    private MouseAdapter handler = new MouseHandler();
    private List<Point> locations = new ArrayList<Point>();
    private Point sentinel = new Point();
    private Dimension dimension;

    CustomCanvas(Dimension dimension) {
        this.dimension = dimension;
        this.setBackground(Color.white);
        this.addMouseListener(handler);
        this.addMouseMotionListener(handler);
        this.locations.add(sentinel);
    }

    @Override
    public void paint(Graphics g) {
        g.setColor(Color.blue);
        Point p1 = locations.get(0);
        for (Point p2 : locations.subList(1, locations.size())) {
            g.drawLine(p1.x, p1.y, p2.x, p2.y);
            p1 = p2;
        }
    }

    @Override
    public void update(Graphics g) {
        paint(g);
        g.clearRect(0, getHeight() - 24, 50, 20); // to background
        g.setColor(Color.red);
        g.drawString(String.valueOf(locations.size()), 8, getHeight() - 8);
    }

    private class MouseHandler extends MouseAdapter {

        @Override
        public void mousePressed(MouseEvent e) {
            if (locations.get(0) == sentinel) { // reference identity
                locations.set(0, new Point(e.getX(), e.getY()));
            }
        }

        @Override
        public void mouseDragged(MouseEvent e) {
            locations.add(new Point(e.getX(), e.getY()));
            repaint();
        }
    }

    @Override
    public Dimension getPreferredSize() {
        return dimension;
    }
}
于 2012-04-11T18:58:03.877 に答える
5

描画しているポイントの状態を保存していません。パネルが再描画されると、最後に描画されたポイントの情報のみが表示されます。


コメントへの返信:

たとえば、ポイントのコレクションが必要です。ArrayList<Point> location = new ArrayList<Point>();

次に、リスナーで次のようにします。location.add(new Point(me.getX(), me.getY()));

最後に、paintLine() で:

for (Point location : locations) {
  repaint(location.x,location.y,1,1); 
}

コレクションlocationsは通常、表示リストと呼ばれます。ほとんどのグラフィックス プログラムはそれらを使用します。


コメントへの返信:

はい、そう思います。出発点を提供するために、あなたのコードに基づいたアイデアを捨てました。私が説明したとおりに行うのは、ほとんど間違いなく悪い考えです。

于 2012-04-11T17:13:47.623 に答える
2

@Andrew、@Dave、@trashgod こんにちは、私はこれについていくつかの調査を行い、最終的に、これが私が得たものです。私が間違っている場合は、私を修正してください。paint() をオーバーライドすることはできないため、アプリでトリガーされたペイントを行う必要があるたびに repaint() を呼び出します。Repaint() は update() を呼び出しますが、デフォルトの動作は paint() を呼び出すことです。update() はインクリメンタル ペイントに使用されます。これは、paint() がすべての作業を行っていたときの画面のちらつきを説明しています。これは、実際には、すべてのステップで画像全体をペイントしていたことを意味します。ただし、私の質問は、更新メソッドに「locationsAdded = 0」を追加すると、マウスをドラッグするたびに (ペイントのように) 画像全体をペイントすることを意味するので、以前のように点滅しないのはなぜですか? また、swing でのペイントについて何か読んだことがありますが、swing で update() が呼び出されない理由がわかりませんでした。理由を説明していただけますか?

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

class CustomCanvas extends Canvas{ 
    ArrayList<Point> locations;        
    int locationsAdded;    
    Point oldLocation;
    Point location;
    Dimension dimension;
    CustomCanvas(Dimension dimension){  
        locations = new ArrayList<>();        
        this.dimension = dimension;   
        this.init();
        addListeners();
    }    
    private void init(){                          
        oldLocation= new Point(0, 0);
        location= new Point(0, 0);
    }
    public void paintLine(Graphics g, int x){
        Point p1 = (Point)locations.get(x);
        Point p2 = (Point)locations.get(x+1);
        g.drawLine(p1.x, p1.y, p2.x, p2.y);
        locationsAdded++;
    }
    @Override
    public void paint(Graphics g){          
        locationsAdded = 0;        
        g.setColor(Color.red);                  
        for(int i = locationsAdded; i < locations.size()-1; i++){
            paintLine(g, i);
        }             
    }
    public void update(Graphics g) {        
    //locationsAdded = 0;
        for (int i = locationsAdded; i < locations.size()-1; i++) {            
            paintLine(g, i);
        }
    }
    private void addListeners(){
        addMouseMotionListener(new MouseMotionAdapter() {
            @Override
            public void mouseDragged(MouseEvent me){                                   
                oldLocation = location;
                location = new Point(me.getX(), me.getY());
                locations.add(location);
                repaint();
            }
        }); 
    }

    @Override
    public Dimension getMinimumSize() {
        return dimension; 
    }
    @Override
    public Dimension getPreferredSize() {
        return dimension;
    }
}
class CustomFrame extends Panel {
    Panel displayPanel = new Panel(new BorderLayout());
    CustomCanvas canvas = new CustomCanvas(new Dimension(700, 700));        
    public CustomFrame(String titlu) {            
        canvas.setBackground(Color.white);
        displayPanel.add(canvas, BorderLayout.CENTER);            
        this.add(displayPanel);
    }  
}
public class AWTPainting {
    public static void main(String args[]) {
        CustomFrame panel = new CustomFrame("Test Paint");
        Frame f = new Frame();
        f.add(panel);
        f.pack();        
        f.setSize(700,700);                    
        f.show();                
    }
}
于 2012-04-13T21:55:38.510 に答える