JAVA:使用DrawingPanel.JAVA构建图形(提供);解析输入和正确传递变量有困难吗?

JAVA:使用DrawingPanel.JAVA构建图形(提供);解析输入和正确传递变量有困难吗?,java,file,parsing,input,graph,Java,File,Parsing,Input,Graph,这里是DrawingPanel类所在的位置,用于编译目的(如果需要)。 我正在编写一个程序,其中我应该使用类DrawingPanel绘制一个数据集,该数据集存储在以下名为“names.txt”的文件中 此java文件允许您创建给定大小的面板,并在此面板中绘制形状和线条。我在程序中遇到的问题与类方法的规范和理解无关 应该使用此java文件绘制的数据集按照以下方式配置: [姓名][性别][排名][排名][排名][排名][排名]……等共14个排名 例如: 简F 56 400 336 102 17 3

这里是DrawingPanel类所在的位置,用于编译目的(如果需要)。

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

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

应该使用此java文件绘制的数据集按照以下方式配置:

[姓名][性别][排名][排名][排名][排名][排名]……等共14个排名

例如:

简F 56 400 336 102 17 33 187 292 275 969 73 53 24 2

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

我遇到了许多问题,例如正确解析用户输入并将其与文件进行比较。
我的主要问题是画出组成图表的线条。这些图形的线条是用以下方法绘制的:

g、 抽绳(x1、y1、x2、y2)

用g表示图形对象。两个点是必要的,因为创建直线需要两个端点

从我的程序当前的配置方式来看,我有一个while循环:

    while (file.hasNextLine() && (fileContains = false)) {
        String inputLine = file.nextLine().toUpperCase();
        if ((inputLine.contains(name) && (inputLine.contains(gender)))){
            String toBeRemoved = name.toUpperCase() + " " + gender.toUpperCase();
            inputLine = inputLine.replace(toBeRemoved, " ");
            Scanner numberSplit = new Scanner(inputLine);
            rank = Integer.parseInt(numberSplit.next());
            rank2 = Integer.parseInt(numberSplit.next());
            fileContains = true;
            drawGraph(name, gender, rank, rank2);

        } 
    }
这个while循环通过文件并搜索与用户输入匹配的行。排名有两个变量,分别是rank和rank2,这是因为需要两个点来画一条线

drawGraph方法:

public static void drawGraph(String name, String gender, int rank, int rank2) {
    int yearIncrease = 0;
    DrawingPanel panel = new DrawingPanel(DECADES * SECTION_WIDTH, 550);
    Graphics g = panel.getGraphics();
    g.setColor(Color.BLACK);
    for (int i = DECADES * SECTION_WIDTH; i >= 0; i -= SECTION_WIDTH){
        //horizontal line 1st
        //these lines need to be drawn in black. however they are drawn in red.
        g.drawLine(i, 0, i, 550);
        //line between points
        //how do you pass new ranks to g.drawLine? by the while loop configuration, 
        //only two values of rank are passed to the method. however, g.drawLine is
        //dependent on drawGraph to construct it.
        g.drawLine(i, (rank/2) + 25, i + SECTION_WIDTH, (rank2/2) + 25);
        String decadeInterval = String.valueOf(STARTING_YEAR + yearIncrease);
        String intervalLabel = name + " " + gender + " " + String.valueOf(rank);
        String intervalLabel2 = name + " " + gender + " " + String.valueOf(rank2);
        yearIncrease += 10;
        g.drawString(decadeInterval, i, 550);
        //draw String at first point
        g.drawString(intervalLabel, rank, (rank/2 + 25));
        g.drawString(intervalLabel2, rank2, (rank2/2 + 25));
        drawLabels(g, rank, gender, name, i);

    }
    g.drawLine(0, 525, DECADES * SECTION_WIDTH, 525);
    g.drawLine(0, 25, DECADES * SECTION_WIDTH, 25);
}
负责绘制输入文件中列出的列组。然而,while循环只传递一次秩变量,因此它最终绘制相同的点,而不是绘制所有的点

要使用该示例,请执行以下操作:

简F 56 400 336 102 17 33 187 292 275 969 73 53 24 2

400之后的排名永远不会传递到drawGraph方法中,以便在其图表中使用。相反,它将图形化,好像输入行是:

简F 56 400 56 400 56 400 56 400 56 400 56 400 56 400 56 400 56 400

我不知道如何解决这个问题。我无法将drawLine方法移出drawGraph,因为它依赖于在该方法中创建的Graphics g对象,并依赖于for循环变量来正确放置。DrawingPanel对象不能在drawGraph方法之外构造,因为DrawingPanel只能在while循环在其文件中成功找到用户输入时构造

在这个程序中还有许多其他的问题,例如图形的标签没有正确地以正确的数量或颜色打印,但是我所描述的问题是我最关心的,而且我完全不知道如何修复

如果您需要任何其他详细信息,请随时发表评论

如有必要,有关可能限制操作的更具体要求,请参见此

汇编代码:

import java.util.*;
import java.awt.*;
import java.io.*;
public class Names {
public static final int STARTING_YEAR = 1880;
public static final int DECADES = 14;
public static final int SECTION_WIDTH = 70;
public static void main(String [] args) throws FileNotFoundException{
    Scanner input = new Scanner(System.in);
    File inputFile = new File("names2.txt");
    if(inputFile.exists()){
        System.out.println("File exists.");
    } else {
        System.out.println("File does not exist. Do something about it.");
    }
    Scanner fileScanner = new Scanner(inputFile);
    introduction();
    String userInput = introQuery(input);
    fileNameScanner(fileScanner, userInput);
} 
public static void introduction() {
    System.out.println("This program allows you to search trhough the");
    System.out.println("data from the Social Security Administration");
    System.out.println("to see how popular a particular name has been");
    System.out.println("since " + STARTING_YEAR +".");
}
public static String introQuery(Scanner input) {
    String params = "";
    System.out.print("name? ");
    params += input.next() + " ";
    System.out.print("gender (M or F)? ");
    params += input.next();
    System.out.println(params);
    // is this necessary? This complicates the parsing of the input string later with
    // multiple scanners.
    return params;      
}
public static void fileNameScanner(Scanner file, String params) {
    boolean fileContains = false;
    System.out.println("fileNameScanner ran");
    int rank = 0;
    int rank2 = 0;
    //investigate whether or not a delimiter is truly necessary. doesn't Scanner
    //already parse by whitespace?
    Scanner split = new Scanner(params).useDelimiter(" ");
    String name = split.next().toUpperCase();
    String gender = split.next().toUpperCase();

    while (file.hasNextLine() /* && (fileContains = false)*/) {
        String inputLine = file.nextLine().toUpperCase();
        if ((inputLine.contains(name) && (inputLine.contains(gender)))){
            //this removal of the first part of the inputLine does not work all this time.
            //How do I fix this? this does not work because Tommie, for example,
            //includes an M in its name.
            String toBeRemoved = name.toUpperCase() + " " + gender.toUpperCase();
            inputLine = inputLine.replace(toBeRemoved, " ");
            //TOMMIE M 
            //01234567
            //if M is 7, new string includes everything after M.
            Scanner numberSplit = new Scanner(inputLine);
            rank = Integer.parseInt(numberSplit.next());
            rank2 = Integer.parseInt(numberSplit.next());
            fileContains = true;
            drawGraph(name, gender, rank, rank2);

        }
    }
    if (fileContains = false) {
        System.out.println("name/gender combination not found");
    }

}
public static void drawGraph(String name, String gender, int rank, int rank2) {
    int yearIncrease = 0;
    DrawingPanel panel = new DrawingPanel(DECADES * SECTION_WIDTH, 550);
    Graphics g = panel.getGraphics();
    g.setColor(Color.BLACK);
    for (int i = DECADES * SECTION_WIDTH; i >= 0; i -= SECTION_WIDTH){
        //horizontal line 1st
        //these lines need to be drawn in black. however they are drawn in red.
        g.drawLine(i, 0, i, 550);
        //line between points
        //how do you pass new ranks to g.drawLine? by the while loop configuration, 
        //only two values of rank are passed to the method. however, g.drawLine is
        //dependent on drawGraph to construct it.
        g.drawLine(i, (rank/2) + 25, i + SECTION_WIDTH, (rank2/2) + 25);
        String decadeInterval = String.valueOf(STARTING_YEAR + yearIncrease);
        String intervalLabel = name + " " + gender + " " + String.valueOf(rank);
        String intervalLabel2 = name + " " + gender + " " + String.valueOf(rank2);
        yearIncrease += 10;
        g.drawString(decadeInterval, i, 550);
        //draw String at first point
        g.drawString(intervalLabel, rank, (rank/2 + 25));
        g.drawString(intervalLabel2, rank2, (rank2/2 + 25));
        drawLabels(g, rank, gender, name, i);

    }
    g.drawLine(0, 525, DECADES * SECTION_WIDTH, 525);
    g.drawLine(0, 25, DECADES * SECTION_WIDTH, 25);
}
public static void drawLabels(Graphics g, int rank1, String gender, String name, int x) {
    g.setColor(Color.RED);
    String intervalLabel = name + " " + gender + " " + String.valueOf(rank1);
    //draw String at first point
    g.drawString(intervalLabel, rank1, (rank1/2 + 25));
}

}

我希望这只是一个打字错误,但是:

 while (file.hasNextLine() && (fileContains = false)) {

这个循环实际上永远不会执行,因为
=
意味着赋值,因此整个表达式变为false。我猜您的意思是
=

为了解析这样简单的用户输入,JavaAPI提供了
Scanner
类。此类将字符串划分为所谓的标记。标记是一组属于一起的符号,例如一个单词或一个数字。然后您可以逐个读取标记(默认情况下,
Scanner
类忽略空格和换行符)

要分析文件,请执行以下操作:

try {
    Scanner scanner = new Scanner(inputFile);
    while (scanner.hasNext()) {
        String name = scanner.next();
        String sex = scanner.next();
        List<Integer> rankings = new ArrayList<>(14);
        while (scanner.hasNextInt()) {
            rankings.add(scanner.nextInt());
        }
        // process single line
        ...
    }
}
catch (FileNoteFoundException e) {
    ... 
}  
catch (NoSuchElementExcpeption) {
    ...
}
catch (InputMismatchException) {
    ...
}
试试看{
扫描仪=新扫描仪(输入文件);
while(scanner.hasNext()){
字符串名称=scanner.next();
字符串sex=scanner.next();
列表排名=新的ArrayList(14);
while(scanner.hasNextInt()){
add(scanner.nextInt());
}
//工艺单线
...
}
}
捕获(FileNoteFounde异常){
... 
}  
捕获(无接触激发){
...
}
捕获(输入不匹配异常){
...
}
对代码的另一个建议是:目前,通过立即绘制一条记录,然后忘记它,来处理一条记录。通常,最好先将信息解析为一些方便的内部表示,然后分别处理这些内部表示。例如,您可以添加一个类:

public class Person {
    private String name;
    private String sex;
    private ArrayList<Integer> rankings;

    // constructors and property accessors
    ...
}
公共类人物{
私有字符串名称;
私密性;
私人ArrayList排名;
//构造函数和属性访问器
...
}
然后可以创建两种方法:

public List<Person> parseFile(File inputFile) {
    ...
}

public void drawGraph(List<Person> data) {
    ...
}
公共列表解析文件(文件输入文件){
...
}
公共void绘图图(列表数据){
...
}

分别解析和绘制数据。这样,您的程序将更易于维护和调试,因为单个方法执行定义良好的操作。

不幸的是,我不允许使用对象。只能使用过程编程。我们也不能使用ArrayList。我们受限于一定数量的概念:循环、扫描程序、基本文件处理、if/else语句和静态方法。好的,如果您不能使用对象,那么我的建议将代码分解为解析和绘图方法将不起作用。既然你知道每行有多少排名,你也可以使用数组而不是
ArrayList
s。我想我不完全明白你想说什么。将代码分解为解析和绘图方法将不起作用。你有没有关于我应该怎么做的建议?另外,我不能使用数组。我只能使用我列出的概念。哦,好的。非常感谢。我没注意到。我总是犯那个错误,只是居里