0

Jlabels のグリッド上で画像のドラッグを設定しようとしています。正常に動作していますが、画像は「リフレッシュ」されており、マウスより遅れることがあります。

これを改善して、完全に「滑らかな」画像の動きを得る方法はありますか?

編集: さて、Andrew Thompson のアドバイスのおかげで、paint() メソッドを paintComponent() に更新しました。しかし、コンポーネントをドラッグするとコンポーネントが消えるのはなぜですか? 私はおそらくここで何かを見逃しています...

EDIT2: 次の動作はなぜですか: paint() メソッドを使用すると、コンポーネントが JLabels の上に表示されます。しかし、paintComponent() を使用すると、コンポーネントは不透明な Jlabels によってマスクされて消えますか?

import java.awt.*;  
import java.awt.event.*;  
import java.io.*;  
import java.net.*;  

import javax.imageio.ImageIO;  
import javax.swing.*;  
import javax.swing.event.*;  

public class DragNDrop {

    public static void main(String[] args)  
    {  
        JFrame f = new JFrame("Test");  
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
        f.setContentPane(new DragPanel());    
        f.pack();
        f.setLocation(200,200);  
        f.setVisible(true);  
    }  

}

class DragPanel extends JPanel {

    JLabel[][] labels;

    SelectableAction action;  
    Image image;  
    Point p;  

    public DragPanel()  
    {  

        p = new Point();  

        setOpaque(true);   
        createLabels();


        action = new SelectableAction(this);  
        addMouseListener(action);  
        addMouseMotionListener(action);  
    }  

    private void createLabels() {


            labels = new JLabel[8][8];

            Dimension dim50 = new Dimension(50,50);
            GridBagConstraints gbc = new GridBagConstraints();
            this.setLayout(new GridBagLayout());

            for (int x=0;x<8;x++){

                for (int y=0;y<8;y++){

                    labels[x][y] = new JLabel();
                    labels[x][y].setOpaque(true);
                    labels[x][y].setPreferredSize(dim50);
                    String str = new String("("+x+","+y+")");
                    labels[x][y].setText(str);

                    if ((x+y) % 2 == 0){
                        labels[x][y].setBackground(Color.lightGray);
                    } else
                    {
                        labels[x][y].setBackground(Color.white);
                    }

                    gbc.gridx = x;
                    gbc.gridy = 7-y;
                    this.add(labels[x][y],gbc);


                }
                URL url = getClass().getResource("images/50px-Knight.pgn");  
                Image img;
                try {
                    img = ImageIO.read(url);
                    labels[0][0].setIcon(new ImageIcon(img));
                } catch (IOException e) {

                    e.printStackTrace();
                }  



            }
    }

    public JLabel[][] getLabels()  
    {  
        return labels;  
    }  


    public void paintComponent(Graphics g)  
    {  
        super.paintComponent(g);  

        if(action.dragging)  
            g.drawImage(image, p.x, p.y, this); 

    }  

    public void setImage(Image i)  
    {  
        image = i;  
    }  

    public void setOrigin(Point p)  
    {  
        this.p = p;  
        repaint();  
    }  


}

/** 
 * Mouse code to enable image dragging 
 */  
class SelectableAction extends MouseInputAdapter  
{  
    DragPanel MyPanel;  
    Image selectedImage;  
    boolean dragging;  
    Rectangle r;  
    Point offset;  

    public SelectableAction(DragPanel dp)  
    {  
        MyPanel = dp;   
        dragging = false;  
        offset = new Point();  
    }  
    public void mousePressed(MouseEvent e)  
    {  
        Point p = e.getPoint();  
        JLabel[][] labels = MyPanel.getLabels();  
        for(int i = 0; i < labels.length; i++)  
        {  
            for (int j=0;j<labels[0].length;j++){

                r = labels[i][j].getBounds();  
                if(r.contains(p))  
                {  
                    if ( ((ImageIcon)labels[i][j].getIcon()).getImage() != null) {
                    selectedImage = ((ImageIcon)labels[i][j].getIcon()).getImage();  
                    MyPanel.setImage(selectedImage);  
                    labels[i][j].setIcon(null);
                    offset.x = p.x - r.x;  
                    offset.y = p.y - r.y;  
                    dragging = true;  
                    MyPanel.setOrigin(new Point(r.x, r.y));
                    break;  
                    }
                }  

            }

        }  
    }  

    public void mouseReleased(MouseEvent e)  
    {  
        Point p = e.getPoint();  
        JLabel[][] labels = MyPanel.getLabels();  
        for(int i = 0; i < labels.length; i++)  
        {  
            for (int j=0;j<labels[0].length; j++){

                r = labels[i][j].getBounds();  
                if(r.contains(p))  {

                    ImageIcon tmpIcon = new ImageIcon(selectedImage);
                    labels[i][j].setIcon(tmpIcon);
                    MyPanel.repaint();  
                    dragging = false;

                }
            }
        }

    }  

    public void mouseDragged(MouseEvent e)  
    {  
        if(dragging)  
        {  
            r.x = e.getX() - offset.x;  
            r.y = e.getY() - offset.y;  
            MyPanel.setOrigin(new Point(r.x, r.y));  
        }  
    }  
}  
4

1 に答える 1

3

AndrewThompson と GuillaumePolet のコメントに +1。特に:

上に自分自身をペイントする不透明な子コンポーネントがあるため、それは消えます。

これを克服するために、オーバーライドする必要はありません/したくないpaintComponent(..)代わりに、オーバーライドpaintChildren(..)して呼び出し、super.paintChildren(..)その後にカスタムコードを呼び出します。したがって、すべてのコンポーネントが呼び出しで描画されsuper、画像が後で描画されるため、他のすべての上に表示/可視になります。

オーバーライドさpaintComponentれたコードを以下のコードに置き換えると、機能します。

@Override
protected void paintChildren(Graphics g) {
    super.paintChildren(g);

    if (action.dragging) {
        g.drawImage(image, p.x, p.y, null);//also notice i use null and not this, unless the class you are using extends ImageObserver no need for this
    }
}
于 2012-12-12T18:10:40.413 に答える