【问题标题】:Why can't I access my panel's getWidth() and getHeight() functions?为什么我无法访问面板的 getWidth() 和 getHeight() 函数?
【发布时间】:2012-01-10 07:09:04
【问题描述】:

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

这是包含我的 Panel 类的 sn-p

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”?

感谢您的帮助

【问题讨论】:

    标签: java swing jpanel keylistener graphics2d


    【解决方案1】:

    Swing 组件在渲染之前没有宽度或高度。如果您在根容器上调用 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 来捕获您的击键。

    【讨论】:

    • 一些(承认吹毛求疵 :-) cmets:a)不需要监听器,覆盖 getPref 你可以从 getPref 的中间开始 b)如果你使用监听器,不要忘记重绘 c) 如果你使用一个只运行一次的监听器,让它自动删除而不是添加一个标志 d) +1 推荐 keyBindings
    【解决方案2】:

    我说不出原因,但是:

    避免这种情况的一种方法是覆盖您的 getPreferredSize() 函数并返回您的首选大小。

    【讨论】:

      【解决方案3】:

      在创建对象时初始化成员变量(在任何父类的构造函数之后和当前类的构造函数主体之前。Swing 在第一次创建对象时不做任何大小调整工作。因此,当您调用 @987654322 @ 和 getHeight(),尚未设置任何值。

      【讨论】:

      • 不正确。大小仅在渲染时发生,而不是在将东西放入布局管理器时发生。您需要阅读 Guy 和 Haase 的“Filthy Rich Clients”以了解更多信息。
      • @HovercratFullOfEels:我删掉了那部分。构造函数未设置这些值的观点仍然成立。由于 OP 在开始时只计算一次这些值,因此它们永远不会具有预期的值。
      猜你喜欢
      • 1970-01-01
      • 2015-05-02
      • 2020-06-20
      • 2019-04-30
      • 2011-09-02
      • 1970-01-01
      • 1970-01-01
      • 2014-03-02
      • 1970-01-01
      相关资源
      最近更新 更多