简体   繁体   English

JAVA:对正确的for循环迭代感到困惑吗?

[英]JAVA: Confusion with correct for-loop iteration?

Background Information: 背景资料:

I am writing a program where I am supposed to graph a data set, which is stored in the following file ( input file ), called "names.txt", using the class DrawingPanel . 我正在编写一个程序,该程序应该在其中绘制数据集的图形,该数据集使用DrawingPanel类存储在以下文件( 输入文件 )中,称为“ names.txt”。

This java file allows you to create a panel of a given size, and draw shapes and lines in this panel. 该Java文件允许您创建给定尺寸的面板,并在该面板中绘制形状和线条。 The problems I am encountering with my program are unrelated to the specifications and understandings of the class methods. 我的程序遇到的问题与类方法的规范和理解无关。

The data set that I am supposed to graph using this java file is configured in the following way: 我应该使用以下java文件绘制的数据集是通过以下方式配置的:

[name] [gender] [ranking] [ranking] [ranking] [ranking]....etc for a total of 14 rankings. [名称] [性别] [排名] [排名] [排名] [排名] .... etc,共14个排名。

Example: 例:

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

General goal of program: The user is supposed to input the name and gender they would like to see graphed. 程序的总体目标:用户应该输入他们希望看到的姓名和性别。 The data is then graphed, rankings representing the y axis and time representing the x axis. 然后将数据绘制成图表,等级代表y轴,时间代表x轴。

My main problem is drawing the lines that compose the graph. 我的主要问题是绘制构成图形的线。 The lines of these graphs are drawn with the method: 这些图的线使用以下方法绘制:

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

with g representing a Graphics object. 其中g代表Graphics对象。 Two points are necessary as two endpoints are necessary to create a line. 需要两个点,因为创建线需要两个端点。

This for loop is responsible for printing the lines. 此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);
            }            
    }

SUMMARY OF PROBLEM: The for loop above is the cause of the bugs in my program. 问题摘要:上面的for循环是我程序中错误的原因。 The problem is the incorrect printing of the lines that compose the graph. 问题是组成图形的线的打印不正确。 This is caused by incorrect for loop iterations and conditions, which are complicated by the awkward location of the for loop and the fact that two calls of everything are necessary to correctly run the program. 这是由于不正确的for循环迭代和条件引起的,而这些又由于for循环的尴尬位置以及必须正确调用程序而必须两次调用所有函数这一事实而变得复杂。 Despite guessing-and-checking for several hours, I cannot figure out how to manipulate the loops to make it work. 尽管经过了数小时的猜测和检查,我仍无法弄清楚如何操纵循环以使其正常工作。

It is complicated because the drawString method is dependent on the drawLine method variables. 这很复杂,因为drawString方法依赖于drawLine方法变量。

I've tried implementing this into my code but it hasn't worked. 我尝试将其实现到我的代码中,但没有成功。

Specific Requirements and Additional Information on DrawingPanel.java: 有关DrawingPanel.java的特定要求和其他信息:

Please see this ( Specification ) for specifications on what the graph should look like and other requirements. 请参阅此( 规范 )以获取有关图形外观和其他要求的规范。

An image of what the graph should look like is also provided below. 下面还提供了图形外观的图像。

    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);
    }

}

Image of graph produced: 产生的图形图像: DrawingPanel图形

Expected graph: 预期图形: 预期的DrawingPanel图形

Please feel free to comment if my explanation is unclear. 如果我的解释不清楚,请随时发表评论。 Here is where the DrawingPanel class is located, for compilation purposes, if necessary. 如果需要,这里是DrawingPanel类的位置,出于编译目的。 DrawingPanel.java DrawingPanel.java

Here is an API for the methods: 这是方法的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)

Your general idea, that you have to read the ranks in pairs, is wrong. 您必须成对读取等级的一般想法是错误的。 What you have to do is draw a line from the last rank's coordinates to the current rank's coordinates. 您要做的是从最后一个等级的坐标到当前等级的坐标画一条线。 Here is my version of your method (mind you, I don't have your whole environment so I can't actually test this): 这是我的方法版本(请注意,我没有您的整个环境,因此我无法进行实际测试):

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);
    }

}

So at first you read the name and gender, and then you read the first rank, to give you initial coordinates. 因此,首先阅读名称和性别,然后阅读第一个等级,以得到初始坐标。

Then, in every iteration of the loop, you read just one rank. 然后,在循环的每次迭代中,您仅读取一个等级。 You draw the line from your previous rank to your new rank. 您从先前的等级到新的等级画了一条线。 You draw the label that belongs to the previous rank at the previous rank's coordinates. 您在前一等级的坐标处绘制属于前一等级的标签。 And then you save your current x , y and rank to the lastX , lastY and lastRank respectively, so that you can rely on them in the next iteration. 然后将当前的xyrank分别保存到lastXlastYlastRank ,以便可以在下一次迭代中使用它们。

After the loop is done, you still have one label you haven't drawn so you draw that, and then you go on to draw the black lines (I haven't looked into the correctess of your code there, just left it as is). 循环完成后,您仍然有一个未绘制的标签,因此可以绘制它,然后继续绘制黑线(我没有在这里查看代码的正确性,只是照原样保留了它) )。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM