【问题标题】:Custom painting JPanel offsets the drawing自定义绘画JPanel偏移绘图
【发布时间】:2014-09-28 16:02:56
【问题描述】:

我在 Windows 8.1 上使用 Netbeans (JDK 1.7) 来运行一个应用程序:

  • 在paintComponent() 的400x400 JPanel 中使用Graphics 对象到draw a frog;
  • 将面板添加到JFrame 以进行显示;

当然,这应该是一项非常简单的任务,但我无法理解此应用程序中的特定行为。

问题出在:第一次显示窗口时,面板在不应该出现的偏移处显示(下图)。我试图了解为什么会发生这种情况以及如何解决它:

在键盘上按下其中一个箭头键后,绘图将向左/右/上/下移动 5 个像素。然而,当这种情况发生时,整个JPanel 似乎被移动到窗口的 (0,0) 坐标(这是我从一开始就期望的),因此移动绘图的次数比它应该的要多得多:

我在面板边缘画了一个黑色边框,以使问题更加明显。

这里是Short, Self Contained, Correct (Compilable), Example:

KAfrog.java:

import javax.swing.SwingUtilities;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

public class KAfrog
{        
    public static void main( String args[] ) 
    {                        
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        }  // end of anonymous innerclass
        ); // end of invokeLater    
    }    

    private static void createAndShowGUI() 
    {
        System.out.println("Created GUI on EDT? " + SwingUtilities.isEventDispatchThread());

        Window janela = new Window("Khan Academy Frog");        
        janela.addWindowListener( new WindowAdapter() {
            public void windowClosing(WindowEvent e) 
            {
                System.exit(0);
            } 
        }  // end of anonymous innerclass
        ); // end of addWindowListener               
    }    
}

Window.java:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.LineBorder;

class DrawingPanel extends JPanel 
{     
    private int x = 50, y = 50;

    public DrawingPanel() {
        super();
        setBorder(new LineBorder(Color.BLACK));
    }    

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

    public void setX(int x) {    
        if (x < 0 || x >= 400)
            return;

        this.x = x;        
        repaint();
    }

    public void setY(int y) {
        if (y < 0 || y >= 400)
            return;

        this.y = y;
        repaint();
    }

    public int getX() { return this.x; }

    public int getY() { return this.y; }

    public void paintComponent(Graphics g) {
        super.paintComponent(g); 
        System.out.println("DrawingPanel::paintComponent: drawing at x:" + x + " y:" + y);
        System.out.println("DrawingPanel::paintComponent: panel size " + getWidth() + "x" + getHeight());        

        // face
        Color green = new Color(30, 204, 91);
        g.setColor(green);
        g.fillOval(x, y, 200, 100);

        // mouth
        g.setColor(Color.BLACK); // g.setColor(new Color(0, 0, 0));
        g.fillOval(x+25, y+25, 150, 50);

        // left eye
        g.setColor(green); 
        g.fillOval(x+30, y-30, 45, 45); // background
        g.setColor(Color.WHITE); 
        g.fillOval(x+35, y-25, 35, 35); // white eye sockets
        g.setColor(Color.BLACK); 
        g.fillOval(x+48, y-15, 10, 10); // black eyes pretos

        // right eye
        g.setColor(green); 
        g.fillOval(x+110, y-30, 45, 45); // background
        g.setColor(Color.WHITE); 
        g.fillOval(x+115, y-25, 35, 35); // white eye sockets
        g.setColor(Color.BLACK); 
        g.fillOval(x+128, y-15, 10, 10); // black eyes                
    }
}

public class Window extends JFrame
{
    DrawingPanel frog_panel;

    public Window(String title) 
    {               
        super(title);                             
        frog_panel = new DrawingPanel();            

        addKeyListener(new KeyListener() {
            public void keyPressed(KeyEvent e) { 
                 if (e.getKeyCode() == KeyEvent.VK_LEFT)
                     frog_panel.setX(frog_panel.getX()-5);

                 if (e.getKeyCode() == KeyEvent.VK_RIGHT)
                     frog_panel.setX(frog_panel.getX()+5);

                 if (e.getKeyCode() == KeyEvent.VK_UP)
                     frog_panel.setY(frog_panel.getY()-5);

                 if (e.getKeyCode() == KeyEvent.VK_DOWN)
                     frog_panel.setY(frog_panel.getY()+5);
            }

            public void keyReleased(KeyEvent e) { }
            public void keyTyped(KeyEvent e) { }
        }
        );

        add(frog_panel);      
        pack();
        setVisible(true);          
        System.out.println("Window::Window: size is " + getWidth() + "x" + getHeight());                
    }             
}

有谁知道为什么会发生这种情况以及如何解决它?

【问题讨论】:

    标签: java jframe jpanel paint paintcomponent


    【解决方案1】:

    你从 javax.​swing.​JComponent 覆盖了 public int getX()。

    它返回组件原点的当前 x 坐标。此方法比编写 component.getBounds().x 或 component.getLocation().x 更可取,因为它不会导致任何堆分配。

    重命名您的方法 public int getX() 和 public int getY()。

    这应该可以解决问题。

    【讨论】:

      猜你喜欢
      • 2011-04-13
      • 2012-12-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-28
      • 2011-07-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多