【问题标题】:JAVA: Confusion with correct for-loop iteration?JAVA:对正确的 for 循环迭代感到困惑?
【发布时间】:2014-11-11 08:34:13
【问题描述】:

背景信息:

我正在编写一个程序,我应该在其中绘制一个数据集,该数据集存储在以下文件 (input file) 中,名为“names.txt”,使用类 DrawingPanel

此 java 文件允许您创建一个给定大小的面板,并在此面板中绘制形状和线条。我的程序遇到的问题与类方法的规范和理解无关。

我应该使用这个 java 文件绘制的数据集配置如下:

[姓名] [性别] [排名] [排名] [排名] [排名]....等共14个排名。

示例:

简 F 98 108 128 116 48 55 47 39 67 202 312 345 436 384

计划的总体目标: 用户应该输入他们希望在图表中看到的姓名和性别。然后将数据绘制成图表,排名代表 y 轴,时间代表 x 轴。

我的主要问题是绘制构成图表的线条。这些图的线条是用以下方法绘制的:

g.drawLine(x1, y1, x2, y2)

用 g 表示一个 Graphics 对象。需要两个点,因为创建一条线需要两个端点。

这个for循环负责打印行。

    for (int j = 0; j < SECTION_WIDTH * DECADES; j += SECTION_WIDTH){
            g.setColor(Color.BLACK);
            g.drawLine(j, yCoordinate, i + intervalIncrease, yCoordinate2);
            g.setColor(Color.RED);
            intervalIncrease += SECTION_WIDTH;
            g.drawString(intervalLabel, intervalIncrease , yCoordinate);
            }            
    }

问题摘要: 上面的 for 循环是我程序中出现错误的原因。问题是组成图形的线条打印不正确。这是由不正确的 for 循环迭代和条件引起的,由于 for 循环的尴尬位置以及正确运行程序需要两次调用所有内容的事实,这使情况变得复杂。尽管猜测和检查了几个小时,但我无法弄清楚如何操纵循环以使其工作。

这很复杂,因为drawString方法依赖于drawLine方法变量。

我尝试在我的代码中实现这一点,但没有奏效。

DrawingPanel.java 的具体要求和附加信息:

请参阅此 (Specification),了解有关图表外观的规范和其他要求。

下面还提供了图表应该是什么样子的图像。

    public static void drawRanks(String line, Graphics g){
    int yearIncrease = 0;
    int intervalIncrease = 0;
    System.out.println(line);
    Scanner lineScan = new Scanner(line);
    String name = lineScan.next();
    String gender = lineScan.next();
    for(int i = 0; i < DECADES/2; i++) {
        g.setColor(Color.RED);
        int rank = lineScan.nextInt();
        int rank2 = lineScan.nextInt();
        int yCoordinate = rank/2 + 25;
        int yCoordinate2 = rank2/2 + 25;
        String intervalLabel = name + " " + gender + " " + String.valueOf(rank);
        String intervalLabel2 = name + " " + gender + " " + String.valueOf(rank2);
        if (rank == 0){
            yCoordinate = 525;
        }
        if (rank2 == 0){
            yCoordinate2 = 525;
        }
        for (int j = 0; j < SECTION_WIDTH * DECADES; j += SECTION_WIDTH){
            g.setColor(Color.BLACK);
            g.drawLine(j, yCoordinate, i + intervalIncrease, yCoordinate2);
            g.setColor(Color.RED);
            intervalIncrease += SECTION_WIDTH;
            g.drawString(intervalLabel, intervalIncrease , yCoordinate);
            }            
    }

    for(int j = 0; j < DECADES; j++) {
        g.setColor(Color.BLACK);
        g.drawString(String.valueOf(STARTING_YEAR + yearIncrease), SECTION_WIDTH * j, 550);
        yearIncrease += 10;
    }  

    for (int k = DECADES * SECTION_WIDTH; k >= 0; k -= SECTION_WIDTH){
        g.drawLine(k, 0, k, 550);
    }

}

生成的图形图像:

预期图表:

如果我的解释不清楚,请随时发表评论。 如有必要,这里是 DrawingPanel 类所在的位置,用于编译目的。 DrawingPanel.java

这是方法的 API:

DrawingPanel name = new DrawingPanel(width, height);

Graphics g - name.getGraphics();

panel.setBackground(color); -  sets panel's background color

g.setColor(color); - sets Graphics pen color (like dipping a brush in paint)

g.drawLine(x1, y2, x2, y2); - a line from points (x1, y1) to (x2, y2)

g.drawString(text, x, y); - the given text with its lower-left corner at (x, y)

【问题讨论】:

  • 我不确定我是否理解正确。您是否缺少线段?字符串是否在错误的位置绘制?你得到什么和你期望什么的图像在这里会有所帮助。
  • 你能把它分解成我可以在圣诞节前读完的东西吗?你能构建一个最小的程序来展示你的问题吗?并准确告诉我们问题出在哪里——只是“我的代码不起作用”还不够好。
  • 抱歉,用文字很难说明我的问题到底是什么。如果您查看我附在我的帖子中的规范,您可以看到一张图表的图像,说明它的外观。如果有帮助,我可以提供当前图表的图像。请再次查看我的帖子。
  • 我确实试图解释我的问题是什么,但我不知道如何解释它而不必先解释背景信息。
  • 请再次检查。我添加了生成图的图像。

标签: java loops for-loop methods iteration


【解决方案1】:

您必须成对阅读排名的一般想法是错误的。您需要做的是从最后一个等级的坐标到当前等级的坐标画一条线。这是您的方法的我的版本(请注意,我没有您的整个环境,所以我无法实际测试):

public static void drawRanks(String line, Graphics g){
    int yearIncrease = 0;
    System.out.println(line);
    Scanner lineScan = new Scanner(line);
    String name = lineScan.next();
    String gender = lineScan.next();
    int lastRank = lineScan.nextInt();
    int lastY = lastRank/2 + 25;
    if ( lastRank == 0 ) {
        lastY = 525;
    }
    int lastX = 0;

    while ( lineScan.hasNextInt() ) {
        int rank = lineScan.nextInt();

        int y = rank/2 + 25;
        if (rank == 0){
            y = 525;
        }
        int x = lastX + SECTION_WIDTH;

        String intervalLabel = name + " " + gender + " " + String.valueOf(lastRank);

        g.setColor(Color.RED);
        g.drawLine(lastX, lastY, x, y);
        g.drawString(intervalLabel,lastX,lastY);
        lastX = x;
        lastY = y;
        lastRank = rank;

    }

    g.drawString(intervalLabel,lastX,lastY);

    for(int j = 0; j < DECADES; j++) {
        g.setColor(Color.BLACK);
        g.drawString(String.valueOf(STARTING_YEAR + yearIncrease), SECTION_WIDTH * j, 550);
        yearIncrease += 10;
    }  

    for (int k = DECADES * SECTION_WIDTH; k >= 0; k -= SECTION_WIDTH){
        g.drawLine(k, 0, k, 550);
    }

}

所以首先你读名字和性别,然后你读第一排,给你初始坐标。

然后,在循环的每次迭代中,您只读取一个等级。你从以前的等级到新的等级划线。您在前一个等级的坐标处绘制属于前一个等级的标签。然后将当前的xyrank 分别保存到lastXlastYlastRank,以便在下一次迭代中依赖它们。

循环完成后,你还有一个标签没有画,所以你画了它,然后你继续画黑线(我没有检查你的代码的正确性,就离开了照原样)。

【讨论】:

  • 感谢您的详尽解释,此解决方案效果很好。
猜你喜欢
  • 2018-10-03
  • 1970-01-01
  • 2016-07-13
  • 2017-05-03
  • 2020-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多