JSwing - 从构造函数中调用子例程不会初始化数组(它应该这样做)

JSwing - calling a subroutine from within a constructor doesn't intitialise an array (which it should be doing)

我有一个 PieChart class,它扩展了我用来绘制(你相信吗)饼图的 JPanel 组件。

我有一个名为 createArcs() 的子例程,它创建用于绘制饼图的圆弧数组。必须在 class 中的其他地方访问正在创建的这些弧线(用于测试鼠标是否在它们上方)。

当我从 paintComponent() 子例程中调用 createArcs() 时,一切正常。这并不完全理想,因为这意味着每次调用 paintComponent() 时都会不必要地重新计算弧线。

当从构造函数中调用 createArcs() 时,JPanel 会弹出,但只会绘制背景。我还有其他正在测试的图形对象,它们也无法渲染除背景(纯白色)以外的任何内容。它也看起来好像数组 已经 被初始化,因为我可以从 paintComponent() 子内部访问数组中弧的属性,它只是无法绘制它们。

下面是工作代码,我想从构造函数而不是 paintComponent() 子函数中调用 createArcs()。感谢您提供的所有帮助 :).

对于任何格式错误,我深表歉意,我是新手 :^)

import java.awt.*;
import java.awt.geom.Arc2D;

import javax.swing.*;

public class PieChart extends JPanel {

public static final int xBuffer = 10;
public static final int yBuffer = 10;

public Arc2D arcs[];

private static final long serialVersionUID = 1L;

int y[];

public PieChart(int y[]) { //Constructor sets up the array
    this.y = y;
}

public void setBounds(int x, int y, int width) { //Overrides so that the panel can only ever be a square
    super.setBounds(x, y, width, width);
}

public int getSegment(int x, int y) {
    int ret = -1;
    for (int i = 0; i < arcs.length; i++) {
        if (arcs[i].contains(x, y)) {
            ret = i;
        }
    }
    return ret;
}

public void paintComponent(Graphics g) {

    //Arcs are calculated every time paintComponent is called :((
    createArcs();
    //Sets up background
    super.paintComponent(g);
    g.setColor(Color.WHITE);
    g.fillRect(0, 0, getWidth(), getHeight());

    //Create an array same size as the int array

    Graphics2D g2 = (Graphics2D) g;

    g.setColor(Util.generateColor(true));

    //Draws the arcs for the pie chart
    g.setColor(Util.generateColor(true));
    for (int i = 0; i < arcs.length; i++) {
        g2.fill(arcs[i]);
        g.setColor(Util.generateColor(false));
    }

}

public void createArcs() {
    arcs = new Arc2D[y.length];
    float normalisedY[] = new float[y.length];

    int maxY = 0;
    int total = 0;

    //Find maximum element and total of the data
    for (int i = 0; i < y.length; i++) {
        if (maxY < y[i]) {
            maxY = y[i];
        }
        total += y[i];
    }

    //Normalise the Y values in degrees
    for (int i = 0; i < y.length; i++) {
        normalisedY[i] = 360 * (((float) y[i] / (float) total));
    }

    int degreesTravelled = 0;
    //Creates arcs in a circle
    for (int i = 0; i < normalisedY.length; i++) {
        Arc2D arc = new Arc2D.Double(0, 0, getWidth(), getHeight(), degreesTravelled, Math.round(normalisedY[i]), Arc2D.PIE);
        arcs[i] = arc;
        degreesTravelled += Math.round(normalisedY[i]);
    }
}

}

这是无法运行的代码:

import java.awt.*;
import java.awt.geom.Arc2D;

import javax.swing.*;

public class PieChart extends JPanel {

public static final int xBuffer = 10;
public static final int yBuffer = 10;

public Arc2D arcs[];

private static final long serialVersionUID = 1L;

int y[];

public PieChart(int y[]) { //Constructor sets up the array
    this.y = y;
    createArcs();
}

public void setBounds(int x, int y, int width) { //Overrides so that the panel can only ever be a square
    super.setBounds(x, y, width, width);
}

public int getSegment(int x, int y) {
    int ret = -1;
    for (int i = 0; i < arcs.length; i++) {
        if (arcs[i].contains(x, y)) {
            ret = i;
        }
    }
    return ret;
}

public void paintComponent(Graphics g) {

    //Arcs are calculated every time paintComponent is called :((

    //Sets up background
    super.paintComponent(g);
    g.setColor(Color.WHITE);
    g.fillRect(0, 0, getWidth(), getHeight());

    //Create an array same size as the int array

    Graphics2D g2 = (Graphics2D) g;

    g.setColor(Util.generateColor(true));

    //Draws the arcs for the pie chart
    g.setColor(Util.generateColor(true));
    for (int i = 0; i < arcs.length; i++) {
        g2.fill(arcs[i]);
        g.setColor(Util.generateColor(false));
    }

}

public void createArcs() {
    arcs = new Arc2D[y.length];
    float normalisedY[] = new float[y.length];

    int maxY = 0;
    int total = 0;

    //Find maximum element and total of the data
    for (int i = 0; i < y.length; i++) {
        if (maxY < y[i]) {
            maxY = y[i];
        }
        total += y[i];
    }

    //Normalise the Y values in degrees
    for (int i = 0; i < y.length; i++) {
        normalisedY[i] = 360 * (((float) y[i] / (float) total));
    }

    int degreesTravelled = 0;
    //Creates arcs in a circle
    for (int i = 0; i < normalisedY.length; i++) {
        Arc2D arc = new Arc2D.Double(0, 0, getWidth(), getHeight(), degreesTravelled, Math.round(normalisedY[i]), Arc2D.PIE);
        arcs[i] = arc;
        degreesTravelled += Math.round(normalisedY[i]);
    }
}

}

Arc2D arc = new Arc2D.Double(0, 0, getWidth(), getHeight(), degreesTravelled, Math.round(normalisedY[i]), Arc2D.PIE);

看起来你有基于面板 width/height 的逻辑。

显然,在创建面板时,在框架可见之前不会有大小。

绘制方法应该只绘制组件的状态,而不是改变状态。

因此,您可能需要向面板添加一个 ComponentListener 以侦听面板大小的变化,此时您将初始化数组中的值。