JFrame没有正确绘制

4
我希望有一个简单的程序,可以通过滑块来改变矩形的宽度。但运行时,jpanel并不能正常工作,它只适合panel.width的宽度,而且无法正确地重绘。
import java.awt.*;
import javax.swing.*;

public class panel extends JPanel {

    private int width = 50;

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setColor(Color.GRAY);
        g.fillRect(20, 20, width, 25);
    }

    public void setWidth(int width) {
        this.width = (width > 0) ? width : 0;
        repaint();
    }

    public int getWidth() {
        return width;
    }
}

GUI:

import java.awt.*;

import javax.swing.*;
import javax.swing.event.*;

public class Gui extends JFrame {

    private panel p;
    private JSlider slider;

    Gui() {
        super("Draw program");
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        p = new panel();
        p.setBackground(Color.RED);
        slider = new JSlider(SwingConstants.HORIZONTAL, 0, 300, p.getWidth());
        slider.setMajorTickSpacing(50);
        slider.setPaintTicks(true);
        add(p);
        add(slider, BorderLayout.SOUTH);
        slider.addChangeListener(new ChangeListener() {
            public void stateChanged(ChangeEvent e) {
                p.setWidth(slider.getValue());
            }
        });
    }
}

请查看答案中的编辑和代码注释。 - Hovercraft Full Of Eels
1个回答

5

您的面板类覆盖了 Component 类(JPanel 继承自此类)的一个关键方法:getWidth。

这样做的问题在于 Swing 布局管理器可能会使用此方法返回的值来调整组件的大小。

解决方案:更改方法名称。

例如:

import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;

public class Gui extends JFrame {

   private MyPanel p;
   private JSlider slider;

   Gui() {
      super("Draw program");
      setDefaultCloseOperation(EXIT_ON_CLOSE);
      p = new MyPanel();
      p.setBackground(Color.RED);
      slider = new JSlider(SwingConstants.HORIZONTAL, 0, MyPanel.GRAY_MAX_LENGTH, p.getGrayWidth());
      slider.setMajorTickSpacing(50);
      slider.setPaintTicks(true);
      add(p);
      add(slider, BorderLayout.SOUTH);
      slider.addChangeListener(new ChangeListener() {
         public void stateChanged(ChangeEvent e) {
            p.setGrayWidth(slider.getValue());
         }
      });
   }

   // so we can test our code
   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            Gui gui = new Gui();
            gui.pack();
            gui.setLocationRelativeTo(null);
            gui.setVisible(true);
         }
      });
   }
}

// note that this class should not be named
// panel as class names should start with an upper-case letter
class MyPanel extends JPanel {
   // constants to avoid use of "magic" numbers
   public static final int GRAY_MAX_LENGTH = 300;
   private static final int RECT_HEIGHT = 25;
   private static final int GAP = 20;
   private static final int PREF_W = GRAY_MAX_LENGTH + 2 * GAP;
   private static final int PREF_H = RECT_HEIGHT + 2 * GAP;
   private int grayWidth = 50;

   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      g.setColor(Color.GRAY);
      g.fillRect(GAP, GAP, grayWidth, RECT_HEIGHT);
   }

   @Override // so our GUI is big enough
   public Dimension getPreferredSize() {
      if (isPreferredSizeSet()) {
         return super.getPreferredSize();
      }
      return new Dimension(PREF_W, PREF_H);
   }

   public void setGrayWidth(int width) {
      this.grayWidth = (width > 0) ? width : 0;
      repaint();
   }

   // ***** key is to change this method's name so you don't
   // override JPanel's getWidth() method
   public int getGrayWidth() {
      return grayWidth;
   }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接