在绘制另一个对象(Java)时,将一个绘制的对象保存在JPanel中

在绘制另一个对象(Java)时,将一个绘制的对象保存在JPanel中,java,swing,jframe,jpanel,Java,Swing,Jframe,Jpanel,我有一个9x9网格可以自己绘制,一个矩形可以自己绘制,还有一个构造函数可以用箭头键移动矩形。但是,我不知道如何在矩形移动的同时保持网格在屏幕上。最终,我希望矩形能够充当网格的导航,当用户按向右键时,它向右移动一个正方形,等等 据我所知,每当调用paint时,整个JPanel都会重新绘制,这意味着一种方法是每当按下一个键时重新绘制每一行,但这似乎太过分了。还有别的办法吗?实际上,绘制矩形会导致网格被绘制 import java.awt.*; import java.awt.event.*; imp

我有一个9x9网格可以自己绘制,一个矩形可以自己绘制,还有一个构造函数可以用箭头键移动矩形。但是,我不知道如何在矩形移动的同时保持网格在屏幕上。最终,我希望矩形能够充当网格的导航,当用户按向右键时,它向右移动一个正方形,等等


据我所知,每当调用paint时,整个JPanel都会重新绘制,这意味着一种方法是每当按下一个键时重新绘制每一行,但这似乎太过分了。还有别的办法吗?实际上,绘制矩形会导致网格被绘制

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


public class TestDoubleObject extends JFrame
{

    private Color ourRectColor = new Color(28,222,144);
    private int ourRectWidth = 50;
    private int ourRectHeight = 50;

    private Point ourRecLocation = new Point(150,150);


    public class Rectangle
    {
        protected void paint(Graphics2D g2d)
        {
                g2d.setColor(ourRectColor);
                g2d.fillRect(ourRecLocation.x, ourRecLocation.y, ourRectWidth, ourRectHeight);
        }

    } // Rectangle class


    public class OurRectangle extends JPanel
    {

        private Rectangle capableRectangle;

        public OurRectangle()
        {
            capableRectangle = new Rectangle();
        }

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

            capableRectangle.paint(g2d);

            g2d.dispose();
        }

    } // OurRectangle class


    public class CoreGrid
    {
        protected void paint(Graphics2D g2d)
        {

            g2d.setColor(new Color(0,0,0));

            // Draw Horizontal Lines

            for(int i=100;i<=640;i+=60)
                g2d.drawLine(100,i,640,i);


            // Draw Vertical Lines

            for(int i=100;i<=640;i+=60)
                g2d.drawLine(i,100,i,640);

        }

    } // CoreGrid class


    public class OurCoreGrid extends JPanel
    {
        private CoreGrid capableCoreGrid;

        public OurCoreGrid()
        {
            capableCoreGrid = new CoreGrid();
        }

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

            capableCoreGrid.paint(g2d);

            g2d.dispose();
        }

    } // OurCoreGrid class


    KeyStroke pressRight = KeyStroke.getKeyStroke("RIGHT");
    KeyStroke pressLeft = KeyStroke.getKeyStroke("LEFT");
    KeyStroke pressUp = KeyStroke.getKeyStroke("UP");
    KeyStroke pressDown = KeyStroke.getKeyStroke("DOWN");

    OurRectangle recToWorkWith = new OurRectangle();
    OurCoreGrid gridToWorkWith = new OurCoreGrid();


    public TestDoubleObject()
    {

        InputMap inputMap = recToWorkWith.getInputMap(JPanel.WHEN_IN_FOCUSED_WINDOW);
        ActionMap actionMap = recToWorkWith.getActionMap();


        Action rightAction = new AbstractAction()
        {
            public void actionPerformed(ActionEvent e)
            {
                ourRecLocation.x += 20;
                recToWorkWith.repaint();
            }
        };

        inputMap.put(pressRight, "rightAction");
        actionMap.put("rightAction",rightAction);


        Action leftAction = new AbstractAction()
        {
            public void actionPerformed(ActionEvent e)
            {
                ourRecLocation.x -= 20;
                recToWorkWith.repaint();
            }
        };

        inputMap.put(pressLeft, "leftAction");
        actionMap.put("leftAction",leftAction);


        Action downAction = new AbstractAction()
        {
            public void actionPerformed(ActionEvent e)
            {
                ourRecLocation.y += 20;
                recToWorkWith.repaint();
            }
        };

        inputMap.put(pressDown, "downAction");
        actionMap.put("downAction",downAction);


        Action upAction = new AbstractAction()
        {
            public void actionPerformed(ActionEvent e)
            {
                ourRecLocation.y -= 20;
                recToWorkWith.repaint();
            }
        };

        inputMap.put(pressUp, "upAction");
        actionMap.put("upAction",upAction);



        add(gridToWorkWith);

        add(recToWorkWith);



        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(800,800);
        setVisible(true);
    }

    public static void main(String[] argv)
    {
        EventQueue.invokeLater(

        new Runnable()
        {
            @Override
            public void run()
            {
                new TestDoubleObject();
            }
        });
    }
}

一种方法是,每当按下一个键时,重新绘制每一行,但这似乎太过分了

这正是绘画的工作方式。Swing是双缓冲的,所以您不会注意到绘画问题

然而,这不是你目前的问题

我不知道如何在矩形移动的同时保持网格在屏幕上

JFrame内容窗格的默认布局管理器是BorderLayout。将零部件添加到BorderLayout且未指定约束时,假定为BorderLayout.CENTER

add(gridToWorkWith);
add(recToWorkWith);
因此,使用上述代码,您将尝试向BorderLayout.CENTER添加两个组件。但是,只有添加的最后一个组件由BorderLayout管理,这意味着第一个组件的大小将为0,因此它永远不会被绘制

Swing组件具有父/子关系,因此如果希望在网格顶部绘制矩形,则需要将矩形添加到网格中,方法与将网格添加到框架中的方法相同

因此,代码可能类似于:

gridToWorkWith.setLayout( new BorderLayout() );
gridToWorkWith.add( recToWorkWith );
add(gridToWorkWith);
//add(recToWorkWith);
但是,这仍然不起作用,因为默认情况下JPanel是不透明的,因此您将看不到网格,因为矩形在其上方绘制。因此,需要使矩形不不透明:

recToWorkWith.setOpaque( false );
很高兴看到您正在使用键绑定。一个建议是创建一个带有参数的动作来控制矩形的移动。所以这两个参数就是x/y位置的变化


有关此方法的示例,请查看中MotionWithKeyBindings示例中的MotionAction。通过使用不同的参数,您的四个操作可以轻松替换为同一操作的四个实例。你甚至可以创建一个对角线运动。

据我所知,只要调用“你是对的”,整个JPanel都会重做。您应该重写JPanel的paintComponent方法。如果希望网格显示在矩形上,请先绘制矩形,然后绘制网格。为动画的每一帧重新绘制整个JPanel要容易得多。