【问题标题】:How to see if a something in Graphics2D is off the frame如何查看 Graphics2D 中的某个内容是否超出框架
【发布时间】:2013-08-07 23:08:54
【问题描述】:

我有一个paint 方法,我绘制了一个矩形并将其移动到屏幕上,当矩形离开屏幕以将其移回 JFrame 的开头时,我希望它做什么。我认为它会类似于if(rectangle.isoffthescreen){ put it back on the screen },但我不知道该怎么做。另外,我想知道你是否可以对矩形做一些事情,比如JFrame frame = new JFrame();,但显然是矩形。如果这令人困惑,我很抱歉。

@MadProgrammer 这是我目前所处的位置

public class main extends JPanel {

public static int place = -350;
public Rectangle rect;
public int xDelta;
   public main() {

       rect = new Rectangle(0, 75, 50, 50);
       xDelta = 4;
       Timer timer = new Timer(40, new ActionListener() {
           @Override
           public void actionPerformed(ActionEvent e) {
               rect.x += xDelta;
               if (rect.x + rect.width > getWidth() - 1) {
                   rect.x = getWidth() - rect.width;
                   xDelta *= -1;
               } else if (rect.x < 0) {
                   rect.x = 0;
                   xDelta *= -1;
               }
               repaint();
           }
       });
       timer.start();

   }

public void paint(Graphics g) {
    super.paint(g);
    Graphics2D g2d = (Graphics2D) g.create();
    Random r = new Random();
    int r1;

    r1 = r.nextInt(5);
    if (r1 == 0) {
        g2d.setColor(Color.WHITE);
    } else if (r1 == 1) {
        g2d.setColor(Color.BLUE);
    } else if (r1 == 2) {
        g2d.setColor(Color.RED);
    } else if (r1 == 3) {
        g2d.setColor(Color.GREEN);
    } else if (r1 == 4) {
        g2d.setColor(Color.PINK);
    } else {
        g2d.setColor(Color.CYAN);
    }

    place += 50;

    rect = new Rectangle(place, 100, 300, 200);
    g2d.draw(rect);
    g2d.fill(rect);
    g2d.dispose();

    try {
        Thread.sleep(400);
    } catch (Exception e) {
    }

    repaint();

}
}

public class frame {

public static JFrame frame;


public static void main(String args[]){
    frame = new JFrame();   
    frame.setSize(500, 500);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    //frame.setResizable(false);
    frame.setVisible(true);
    frame.setLocationRelativeTo(null);
    main m = new main();
    m.setBackground(Color.BLACK);
    frame.add(m);
}


}

我仍然无法让它工作。

【问题讨论】:

    标签: java swing graphics jframe graphics2d


    【解决方案1】:

    首先,您应该避免覆盖顶级容器的paint,而是使用从JComponent 扩展的东西(如JPanel)并覆盖它的paintComponent

    有很多原因,但在您的情况下,框架包含位于可视区域内的装饰。

    基本过程是检查边缘情况...

    if (box.x + box.width > getWidth() - 1) {
        // The boxes right edge is beyond the right edge of it's container
    } else if (box.x < 0) {
        // The boxes left edge is beyond the left edge of it's container
    }
    

    这会检查box 的右边缘是否超出容器右边缘以及box 的左边缘是否超出容器的左边缘。

    将垂直检查也包括在内是一个简单的过程。

    更新示例

    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.EventQueue;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.Rectangle;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.Timer;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    
    public class Move {
    
        public static void main(String[] args) {
            new Move();
        }
    
        public Move() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    }
    
                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setLayout(new BorderLayout());
                    frame.add(new TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        public class TestPane extends JPanel {
    
            private Rectangle box;
            private int xDelta;
    
            public TestPane() {
    
                box = new Rectangle(0, 75, 50, 50);
                xDelta = 4;
                Timer timer = new Timer(40, new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        box.x += xDelta;
                        if (box.x + box.width > getWidth() - 1) {
                            box.x = getWidth() - box.width;
                            xDelta *= -1;
                        } else if (box.x < 0) {
                            box.x = 0;
                            xDelta *= -1;
                        }
                        repaint();
                    }
                });
                timer.start();
    
            }
    
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(200, 200);
            }
    
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                Graphics2D g2d = (Graphics2D) g.create();
                g2d.setColor(Color.BLUE);
                g2d.fill(box);
                g2d.dispose();
            }
        }
    
    }
    

    从 OP 的示例代码更新

    马上,很多事情让我担心......

    1. 覆盖paint
    2. paint方法中调用Thread.sleep
    3. paint 方法中调用repaint
    4. paint 方法中创建一个新的Rectangle
    5. place变量的依赖

    查看Performing Custom Painting 了解有关在 Swing 中绘画的更多详细信息

    您不应阻塞或执行长时间运行的事件调度线程处理,这将阻止 EDT 处理(除其他外)绘制请求和新事件。通过在 paint 方法中调用 Thread.sleep,您可以阻止 Swing 更新屏幕。

    查看Concurrency in Swing了解更多详情。

    paint 方法中调用repaint(或任何可能调用repaint 的方法)肯定会消耗您的CPU 周期。

    您可能需要查看Painting in AWT and Swing 以了解有关 Swing 中绘制过程的更多详细信息

    通过在paint 方法中创建新的Rectangle,您将丢弃Timer 所做的任何更改,从而有效地阻止您的矩形有效移动...

    place 方法不是必需的。动画是随时间变化的幻觉,因此使用了TimerxDelta

    根据您的代码示例更新

    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.EventQueue;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.Rectangle;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.util.Random;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.Timer;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    
    public class Move {
    
        public static void main(String[] args) {
            new Move();
        }
    
        public Move() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    }
    
                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setLayout(new BorderLayout());
                    frame.add(new Main());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        public static class Main extends JPanel {
    
            public static int place = -350;
            public Rectangle rect;
            public int xDelta;
    
            public Main() {
    
                rect = new Rectangle(0, 75, 50, 50);
                xDelta = 4;
                Timer timer = new Timer(40, new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        rect.x += xDelta;
                        if (rect.x + rect.width > getWidth() - 1) {
                            rect.x = getWidth() - rect.width;
                            xDelta *= -1;
                        } else if (rect.x < 0) {
                            rect.x = 0;
                            xDelta *= -1;
                        }
                        repaint();
                    }
                });
                timer.start();
    
            }
    
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(200, 200);
            }
    
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                Graphics2D g2d = (Graphics2D) g.create();
                Random r = new Random();
                int r1;
    
                r1 = r.nextInt(5);
                if (r1 == 0) {
                    g2d.setColor(Color.WHITE);
                } else if (r1 == 1) {
                    g2d.setColor(Color.BLUE);
                } else if (r1 == 2) {
                    g2d.setColor(Color.RED);
                } else if (r1 == 3) {
                    g2d.setColor(Color.GREEN);
                } else if (r1 == 4) {
                    g2d.setColor(Color.PINK);
                } else {
                    g2d.setColor(Color.CYAN);
                }
    
    //            place += 50;
    
    //            rect = new Rectangle(place, 100, 300, 200);
                g2d.draw(rect);
                g2d.fill(rect);
                g2d.dispose();
    
            }
        }
    }
    

    【讨论】:

    • 由于某种原因,当我使用paintComponent时它不起作用,只有paint。用paint不好吗。
    • 在 if 语句中,我实际上在其中放入了什么来将矩形移回?
    • @DilanHanrahan 那是因为顶级容器没有paintComponent 方法。顶级容器也不是双缓冲的。另外,你看到这个例子了吗?
    • @DilanHanrahan 您的代码示例中有一些基本错误。我已经更新了解释和示例
    猜你喜欢
    • 2021-12-19
    • 1970-01-01
    • 2013-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-25
    • 1970-01-01
    相关资源
    最近更新 更多