0

3x3チェックボード

JFrameに追加されたJPanelでレンダリングされた3x3チェックボードのような画像があります。次に、さらに 9 つの JPanel (各正方形の上に 1 つ) があり、クリックすると、対応する正方形に何かを描画する必要があります。私の問題は、左上の正方形でしか機能しないことです。残りの描画は、チェックボード イメージの下に描画されているようです。したがって、チェックボード イメージをロードする部分をコメント アウトし、そこにあるかのようにクリックすると、図面が正しく表示されます。階層化されたペインでも同じ結果が得られます。チェックボードの画像を削除すると、図面が本来あるべき場所に表示され、図面が正方形を超えて占有されないため、絶対配置が使用され、座標が正しいように見えます。私のコードは次のように構成されています:

「メイン」クラスはフレームを作成し、JPanel を拡張し、paintComponent(Graphics g) を使用してチェックボード イメージを描画する別のクラスのインスタンスを追加します。「メイン」クラスには、JPanel を拡張し、paintComponent(Graphics g) を使用してマウス クリックで何かを描画するクラスの 9 つのインスタンスも追加されています。各インスタンスは正方形の上に配置されます

Rectangles だけでやろうとしていたので、2 番目のクラスに Rectangles という名前を付けましたが、Java Rectangle インスタンスではなく、rectangualar JPanels であることに注意してください。

コード:

public class Main3
{
    private JFrame frame=new JFrame("");
    private Rectangles rect00=new Rectangles(0,0,129,129);
    private Rectangles rect01=new Rectangles(136,0,129,129);
    private Rectangles rect02=new Rectangles(268,0,129,129);
    private Rectangles rect10=new Rectangles(0,136,129,129);
    private Rectangles rect11=new Rectangles(134,136,129,129);
    private Rectangles rect12=new Rectangles(269,137,129,129);
    private Rectangles rect20=new Rectangles(0,270,129,129);
    private Rectangles rect21=new Rectangles(136,269,129,129);
    private Rectangles rect22=new Rectangles(269,270,129,129);
    
    public void Display()
    {
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.setLayout(null);
        frame.setSize(600,400); 
        sub inter=new sub();
        inter.setLayout(null);
        inter.setBounds(0,0,600,400);
        inter.setSize(600,400);
    
        rect00.setBounds(rect00.getX(),rect00.getY(),rect00.getWidth(),rect00.getHeight());
        rect01.setBounds(rect01.getX(),rect01.getY(),rect01.getWidth(),rect01.getHeight());
        rect02.setBounds(rect02.getX(),rect02.getY(),rect02.getWidth(),rect02.getHeight());
        rect10.setBounds(rect10.getX(),rect10.getY(),rect10.getWidth(),rect10.getHeight());
        rect11.setBounds(rect11.getX(),rect11.getY(),rect11.getWidth(),rect11.getHeight());
        rect12.setBounds(rect12.getX(),rect12.getY(),rect12.getWidth(),rect12.getHeight());
        rect20.setBounds(rect20.getX(),rect20.getY(),rect20.getWidth(),rect20.getHeight());
        rect21.setBounds(rect21.getX(),rect21.getY(),rect21.getWidth(),rect21.getHeight());
        rect22.setBounds(rect22.getX(),rect22.getY(),rect22.getWidth(),rect22.getHeight());
        rect00.setOpaque(false);
        rect01.setOpaque(false);
        rect02.setOpaque(false);
        rect10.setOpaque(false);
        rect11.setOpaque(false);
        rect12.setOpaque(false);
        rect20.setOpaque(false);
        rect21.setOpaque(false);
        rect22.setOpaque(false);
        
        inter.add(rect00);
        inter.add(rect01);
        inter.add(rect02);
        inter.add(rect10);
        inter.add(rect11);
        inter.add(rect12);
        inter.add(rect20);
        inter.add(rect21);
        inter.add(rect22);
        frame.add(inter);
        frame.setResizable(false);
        frame.setVisible(true);     
    }
    
    public static void main(String args[])
    {
        new main().Display();
    }
    
    
    private class sub extends JPanel
    {
        
        private BufferedImage image;
        
        public sub ()
        {
             
            try
            {                 
                 image=ImageIO.read(new File("image.jpg"));
                        
            }
            catch (IOException e)
            {
             
                e.printStackTrace();
            }
        }
    
        @Override
        public Dimension getPreferredSize()
        {
            return (new Dimension(600,400));
        }
        
        
        @Override
        protected void paintComponent(Graphics g)
        {
            super.paintComponent(g);
            g.drawImage(image, 0, 0, null);   
        }
        
       
    }
}

これは他のクラスです

public class Rectangles extends JPanel implements MouseListener
{

    private int Posx;
    private int Posy;
    private int width;
    private int height;
    private boolean selected=false;
    public Rectangles(int Posx,int Posy,int width,int height)
    {
          this.Posx=Posx;
          this.Posy=Posy;
          this.width=width;
          this.height=height;
          this.addMouseListener(this);     
    }
        
    @Override
    protected void paintComponent(Graphics g)
    {
        if(selected==true)
        {
            Graphics2D g2 = (Graphics2D) g;
               super.paintComponent(g2);
               g2.setColor(new Color(250, 235, 215));
               g2.drawRect(Posx,Posy,width,height);
               Graphics2D g3=(Graphics2D)g;
               g2.setColor(new Color(0,0,0));
               g3.setStroke(new BasicStroke(20));
               g3.drawLine(Posx,Posy,Posx+width,Posy+height);
               g3.drawLine(Posx+width,Posy,Posx,Posy+height);
           
        }   
        
    }
    
    public int getX()
    {
        return Posx;
    }
    
    public int getY()
    {
        return Posy;
    }
    
    
    public int getWidth()
    {
        return width;
    }
    
    
    public int getHeight()
    {
        return height;
    }
    
    
    public void setSelected()
    {
        selected=true;
    }
    
    @Override
    public void mouseClicked(MouseEvent arg0)
    {
        
    }
    
    @Override
    public void mouseEntered(MouseEvent arg0) 
    {
        
    }
         
    public void mouseExited(MouseEvent arg0) 
    {
        
    }
    @Override
    public void mousePressed(MouseEvent arg0) 
    {
        
    }
         
    @Override
    public void mouseReleased(MouseEvent arg0)
    {
        selected=true;
        repaint();
        
    }
}
4

1 に答える 1

2

1) コンポーネントペイント チェーンを尊重しない。

のJavaドキュメントに従ってpaintComponent(Graphics g)

 さらに、super の実装を呼び出さない場合は、不透明なプロパティを尊重する必要があります。つまり、このコンポーネントが不透明な場合は、不透明でない色で背景を完全に塗りつぶす必要があります。opaque プロパティを尊重しないと、視覚的なアーティファクトが表示される可能性があります。

2)super.paintComponentほとんどの場合、メソッドの最初の呼び出しになります。

3) しかし、Graphics2D へのキャストを 2 回行う必要があります。

Graphics2D g2 = (Graphics2D) g;
...
Graphics2D g3=(Graphics2D)g;

すでにオブジェクトg3にキャストした必要のないものを省略しますGraphics2D

4) 別の問題がここのsubクラスにあります。メインコードでこれを行います:

inter.add(rect00);
inter.add(rect01);
...

ただし、クラスinterのインスタンスの変数名は次のとおりです。sub

@Override
protected void paintComponent(Graphics g)
{
    super.paintComponent(g);
    g.drawImage(image, 0, 0, null);   
}

したがって、追加する長方形の数に関係なく、単一の画像しか描画されません!

また 、 g2.drawLine(Posx, Posy, Posx + width, Posy + height);JPanel g2.drawLine(0, 0, Posx + width, Posy + height);が座標xyそのコンテナーに追加されているため、JPanel を描画するときに、左上、つまり 0,0 から開始したいので、値を変更すると、画像がコンテナーのさらに下に移動します。

ここで修正コードを参照してください:

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Test {

    private JFrame frame = new JFrame("");
    private Rectangles rect00 = new Rectangles(0, 0, 129, 129);
    private Rectangles rect01 = new Rectangles(136, 0, 129, 129);
    private Rectangles rect02 = new Rectangles(268, 0, 129, 129);
    private Rectangles rect10 = new Rectangles(0, 136, 129, 129);
    private Rectangles rect11 = new Rectangles(134, 136, 129, 129);
    private Rectangles rect12 = new Rectangles(269, 137, 129, 129);
    private Rectangles rect20 = new Rectangles(0, 270, 129, 129);
    private Rectangles rect21 = new Rectangles(136, 269, 129, 129);
    private Rectangles rect22 = new Rectangles(269, 270, 129, 129);

    public void Display() {
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.setLayout(null);
        frame.setSize(600, 400);
        sub inter = new sub();
        inter.setLayout(null);
        inter.setBounds(0, 0, 600, 400);
        inter.setSize(600, 400);

        rect00.setBounds(rect00.getX(), rect00.getY(), rect00.getWidth(), rect00.getHeight());
        rect01.setBounds(rect01.getX(), rect01.getY(), rect01.getWidth(), rect01.getHeight());
        rect02.setBounds(rect02.getX(), rect02.getY(), rect02.getWidth(), rect02.getHeight());
        rect10.setBounds(rect10.getX(), rect10.getY(), rect10.getWidth(), rect10.getHeight());
        rect11.setBounds(rect11.getX(), rect11.getY(), rect11.getWidth(), rect11.getHeight());
        rect12.setBounds(rect12.getX(), rect12.getY(), rect12.getWidth(), rect12.getHeight());
        rect20.setBounds(rect20.getX(), rect20.getY(), rect20.getWidth(), rect20.getHeight());
        rect21.setBounds(rect21.getX(), rect21.getY(), rect21.getWidth(), rect21.getHeight());
        rect22.setBounds(rect22.getX(), rect22.getY(), rect22.getWidth(), rect22.getHeight());
        rect00.setOpaque(false);
        rect01.setOpaque(false);
        rect02.setOpaque(false);
        rect10.setOpaque(false);
        rect11.setOpaque(false);
        rect12.setOpaque(false);
        rect20.setOpaque(false);
        rect21.setOpaque(false);
        rect22.setOpaque(false);

        inter.addPanel(rect00);
        inter.addPanel(rect01);
        inter.addPanel(rect02);
        inter.addPanel(rect10);
        inter.addPanel(rect11);
        inter.addPanel(rect12);
        inter.addPanel(rect20);
        inter.addPanel(rect21);
        inter.addPanel(rect22);
        frame.add(inter);
        frame.setResizable(false);
        frame.setVisible(true);
    }

    public static void main(String args[]) {
        new Test().Display();
    }

    private class sub extends JPanel {

        private BufferedImage image;
        private ArrayList<Rectangles> rects = new ArrayList<>();

        public sub() {

            try {
                image = ImageIO.read(new File("c:/image.png"));

            } catch (IOException e) {

                e.printStackTrace();
            }
        }

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

        void addPanel(Rectangles r) {
            rects.add(r);
            add(r);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            for (Rectangles r : rects) {
                g.drawImage(image, r.getX(), r.getY(), null);
            }
        }
    }
}

class Rectangles extends JPanel implements MouseListener {

    private int Posx;
    private int Posy;
    private int width;
    private int height;
    private boolean selected = false;

    public Rectangles(int Posx, int Posy, int width, int height) {
        this.Posx = Posx;
        this.Posy = Posy;
        this.width = width;
        this.height = height;
        this.addMouseListener(this);
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        if (selected == true) {
            Graphics2D g2 = (Graphics2D) g;
            g2.setColor(new Color(250, 235, 215));
            g2.drawRect(0,0, width, height);
            g2.setColor(new Color(0, 0, 0));
            g2.setStroke(new BasicStroke(20));
            g2.drawLine(0,0, width,height);
            g2.drawLine(getWidth(),0, 0, height);
        }

    }

    public int getX() {
        return Posx;
    }

    public int getY() {
        return Posy;
    }

    public int getWidth() {
        return width;
    }

    public int getHeight() {
        return height;
    }

    public void setSelected() {
        selected = true;
    }

    @Override
    public void mouseClicked(MouseEvent arg0) {
    }

    @Override
    public void mouseEntered(MouseEvent arg0) {
    }

    public void mouseExited(MouseEvent arg0) {
    }

    @Override
    public void mousePressed(MouseEvent arg0) {
    }

    @Override
    public void mouseReleased(MouseEvent arg0) {
        selected = true;
        repaint();


    }
}

その他のヒント:

  • 使用しないAbsolute/Nullレイアウトします。GridLayoutまたはあなたのGridBagLayoutニーズにうまく合うでしょう。(詳しくはこちらをご覧ください。)
  • 可視に設定する前に、 JFrame#setSize(...);CorrectLayoutManagerと call pack()on を使用しないでください。JFrame
  • インスタンスを呼び出さないsetSizeでください。パネルで行ったようにRectanglesオーバーライドするだけですか??getPreferredSizesub
  • を実装する必要はありませんMouseListener。使用するだけで、MouseAdapterすべてをオーバーライドするだけでなく、オーバーライドするメソッドを自由に選択できます。
  • Concurrency in Swing、特にEvent-Dispatch-Threadを読んでください。
于 2013-06-28T12:24:25.257 に答える