java - JSliderchangeListener不会更新 - Java

标签 java swing jpanel repaint jslider

我有一个分形树生成器,我试图让 slider 控制迭代次数,但我无法让它工作。此外,每当调用 repaint() 方法时,布局就会变得困惑。关于如何解决这个问题有什么想法吗?

public class FractalTree extends JPanel implements ChangeListener {

    static JSlider slider = new JSlider(0,12);

    static  int slideVal=7;
    public FractalTree()
    {
        super();
        slider.addChangeListener(this);
    }

    public void paint(Graphics g)
    {
        g.setColor(Color.green);
        drawTree(g, 400, 750, 200, Math.toRadians(-90), Math.toRadians(45), slideVal); //Don't let # of iterations exceed 12, it is useless
    }

    private void drawTree(Graphics g, int x1, int y1, double l, double t, double dt, double iterations) {
        if (iterations > 0) {
            int x2 = x1 + (int) (l * Math.cos(t));
            int y2 = y1 + (int) (l * Math.sin(t));
            g.drawLine(x1, y1, x2, y2);
            drawTree(g, x2, y2, l / 1.5, t + dt, Math.PI / 4, iterations - .5);
            drawTree(g, x2, y2, l / 1.5, t - dt, Math.PI / 4, iterations - .5);
        }
    }

    @Override
    public void stateChanged(ChangeEvent e) {
        slideVal=slider.getValue();
        repaint();
    }

    public static void main(String[] args) {
        JFrame t = new JFrame("Some swaggy fractal shit");
        FractalTree tree = new FractalTree();
        slider.setValue(slideVal);
        slider.setMinorTickSpacing(1);
        slider.setPaintTicks(true);
        slider.setPaintLabels(true);

        tree.add(slider);
        t.add(tree);
        t.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        t.setResizable(false);
        t.setLocationByPlatform(true);
        t.setSize(800, 800);
        t.setBackground(Color.black);
        t.setVisible(true);
    }
}

最佳答案

两个主要问题:

  1. 你凌驾于paint之上而不是paintComponent .
  2. 你没有调用super.paintComponent(g) (或者在您的情况下, super.paint(g) )作为您重写方法中的第一件事。

这是您需要具备的:

@Override
public void paintComponent(Graphics g) {

    super.paintComponent(g);
    g.setColor(Color.green);
    drawTree(g, 400, 750, 200, Math.toRadians(-90), Math.toRadians(45), slideVal);
}

其他需要考虑的事情:

  • 将 slider 添加到框架的位置 BorderLayout.PAGE_START而不是面板。如果将其添加到面板中,您可能会面临绘制 slider 所在位置的风险。
  • 在面板上而不是框架上设置背景颜色。
  • 无需调用super()在构造函数中,它是自动的。
  • setResizable(false)一般应避免在框架上。无需限制用户的空间。
  • 调用 pack()在框架上而不是 setSize(...) 。后者过于依赖本地显卡配置。
    • 您需要覆盖面板的 getPreferredSize方法返回正确的绘图尺寸。
  • 您的像素计算应调整为使树与面板的左上角对齐,而不是从底部的任意位置开始,这会导致您损失大量屏幕空间:<

enter image description here

回复评论

Why paintComponent should be used?

查看这些:

public void paint(Graphics g)

This method actually delegates the work of painting to three protected methods: paintComponent, paintBorder, and paintChildren. They're called in the order listed to ensure that children appear on top of component itself. [...] A subclass that just wants to specialize the UI (look and feel) delegate's paint method should just override paintComponent.

如果您覆盖paint,您就会看到这一点并将 slider 添加到面板中,您遇到了 slider 绘制问题,因为您忽略了 paintChildren .

What calling the superclass constructor does?

最好的回答是 JLS:

JLS 8.8.7. Constructor Body

If a constructor body does not begin with an explicit constructor invocation and the constructor being declared is not part of the primordial class Object, then the constructor body implicitly begins with a superclass constructor invocation "super();", an invocation of the constructor of its direct superclass that takes no arguments.

打电话super()什么都不做。

关于java - JSliderchangeListener不会更新 - Java,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30116062/

相关文章:

java - 单击java中的按钮后将(多个)表单添加到ScrollPane

java - 如何在java中的JFrame中排列按钮?

java - 使用 ArrayLists 忽略 indexOf() 的大小写

Java根据鼠标点击绘制三个形状?

java - 为什么 Joptionpane 在 JDialog 之上不是模态的

java - Swing Jcombobox 将第一个元素设置为默认选中

java - 似乎无法让 .remove 工作

java - 如何将结果集的所有行返回给客户端?

java - Android studio xml文件无法读取并且xml文件变成了文本文件

java - 如何总结对象流的数字属性?