为什么我不能访问我的面板的getWidth()和getHeight()函数?

时间:2011-12-01 03:38:58

标签: java swing jpanel keylistener graphics2d

我正在编写一个简单的程序来测试基本的GUI。程序在屏幕中间打印一个字母,允许用户使用箭头键移动它。一切正常,但是当我尝试在程序开头处将字母居中时,似乎getWidthgetHeight函数没有返回正确的数字。

这是包含我的Panel类

的代码段
static class LinePanel extends JPanel{
    int xCenter = getWidth() /2;
    int yCenter = getHeight() /2;

    private int x = xCenter;
    private int y = yCenter;
    private char keyChar = 'A';

    public LinePanel(){
        addKeyListener(new KeyAdapter(){
            public void keyPressed(KeyEvent e) {
                switch (e.getKeyCode()) {
                    case KeyEvent.VK_DOWN: y += 10; break;
                    case KeyEvent.VK_UP: y -= 10; break;
                    case KeyEvent.VK_LEFT: x -= 10; break;
                    case KeyEvent.VK_RIGHT: x += 10; break;
                    default: keyChar = e.getKeyChar();
                }

                repaint();

            }
        });
    }

    protected void paintComponent(Graphics g){
        super.paintComponent(g);

        g.setFont(new Font("TimesRoman", Font.PLAIN, 24));
        g.drawString(String.valueOf(keyChar), x, y);
    }
}

为什么我的getWidthgetHeight函数返回'0'?

感谢您的帮助

3 个答案:

答案 0 :(得分:9)

摆动组件在渲染之前没有宽度或高度。如果您在根容器上调用pack()setVisible(true),则会发生这种情况。考虑将x y int初始化代码放在添加到JPanel的ComponentListener的componentResized方法中。

如,

import java.awt.event.*;
import java.awt.*;

import javax.swing.*;

public class TestLinePanel {
   private static void createAndShowGui() {
      LinePanel mainPanel = new LinePanel();

      JFrame frame = new JFrame("TestLinePanel");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }

   static class LinePanel extends JPanel {
      private static final int PREF_W = 400;
      private static final int PREF_H = PREF_W;
      private char keyChar = 'A';
      private int x;
      private int y;
      private boolean xySet = false;

      public LinePanel() {
         setFocusable(true);
         addKeyListener(new KeyAdapter() {
            public void keyPressed(KeyEvent e) {
               switch (e.getKeyCode()) {
               case KeyEvent.VK_DOWN:
                  y += 10;
                  break;
               case KeyEvent.VK_UP:
                  y -= 10;
                  break;
               case KeyEvent.VK_LEFT:
                  x -= 10;
                  break;
               case KeyEvent.VK_RIGHT:
                  x += 10;
                  break;
               default:
                  keyChar = e.getKeyChar();
               }

               repaint();

            }
         });

         addComponentListener(new ComponentAdapter() {

            @Override
            public void componentResized(ComponentEvent e) {
               if (!xySet) {
                  int xCenter = getWidth() / 2;
                  int yCenter = getHeight() / 2;

                  x = xCenter;
                  y = yCenter;

                  requestFocusInWindow();
                  xySet = true;
               }
            }

         });
      }

      @Override
      public Dimension getPreferredSize() {
         return new Dimension(PREF_W, PREF_H);
      }

      protected void paintComponent(Graphics g) {
         super.paintComponent(g);
         g.setFont(new Font("TimesRoman", Font.PLAIN, 24));
         g.drawString(String.valueOf(keyChar), x, y);
      }
   }
}

您还需要使用key bindings而不是KeyListener来捕获您的击键。

答案 1 :(得分:7)

我不能说出原因,但是:

避免这种情况的一种方法是覆盖getPreferredSize()功能并返回首选尺寸。

答案 2 :(得分:3)

成员变量在创建对象时被初始化(在任何父类的构造函数之后和当前类的构造函数体之前。当首次创建对象时,Swing不会执行任何大小调整工作。因此,当您调用{时{1}}和getWidth(),尚未设置任何值。