将一个被画的对象保持在一个JPanel中,同时画另一个对象(Java)。

问题描述 投票:0回答:1

我有一个可以自己绘制的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();
            }
        });
    }
}

java swing jframe jpanel
1个回答
1
投票

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

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

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

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

JFrame的内容窗格的默认布局管理器是BorderLayout。当你在BorderLayout中添加一个组件,并且没有指定约束条件时,BorderLayout.CENTER被假定为。

add(gridToWorkWith);
add(recToWorkWith);

所以,在上面的代码中,你正试图将两个组件添加到 BorderLayout.CENTER. 然而只有最后添加的组件才会被BorderLayout管理,这意味着第一个组件的大小将是(0,0),所以它永远不会被绘制。

Swing组件有一个父子关系,所以如果你想让矩形画在网格上面,那么你需要把矩形添加到网格中,就像你把网格添加到框架中一样。

所以代码可能是这样的。

gridToWorkWith.setLayout( new BorderLayout() );
gridToWorkWith.add( recToWorkWith );
add(gridToWorkWith);
//add(recToWorkWith);

但是这仍然不行 因为默认情况下JPanel是不透明的 所以你看不到网格 因为矩形画在了网格上面 所以你需要把矩形做成不透明的。

recToWorkWith.setOpaque( false );

很高兴看到你使用了 "键绑定"。一个建议是创建一个带有参数的Action来控制矩形的移动。所以两个参数将是位置的xy变化。

关于这个方法的例子,请看 MotionAction 见于 MotionWithKeyBindings 例子 使用键盘的运动. 通过使用不同的参数,你的四个Action可以很容易地被替换为4个相同Action的实例。你甚至可以创建一个对角线运动。

© www.soinside.com 2019 - 2024. All rights reserved.