目录
题目:**16.11(创建表示字母出现次数的直方图)
习题思路
1.HistogramPane类
2. HistogramPaneDemo类
代码示例
结果展示
题目:**16.11(创建表示字母出现次数的直方图)
编写一个程序,从文件中读取内容并显示一个直方图,表示文件中每个字母出现的次数,如图16-40所示。从文本域中输入文件名。在文本域上按回车键从而程序开始读取并处理文件,并且显示直方图。直方图在窗体中央显示。定义一个继承自Pane的名为Histogram的类。该类包含counts属性,该属性是一个包含26个元素的数组。Counts[0]存储A的出现次数,counts[1]存储B的出现次数,依此类推。类还包含一个设置方法,用于设置一个新的counts并且为新的counts显示直方图。
-
习题思路
-
1.HistogramPane类
- 类按照题目要求继承Pane,创建属性counts[],添加get和set方法(get方法可有可无,在set方法中调用绘图方法)
- 创建两个构造函数,无参的构造函数使用new实例化属性counts,另一个构造函数传入一个int[]数组,赋值给属性counts
- 创建一个绘制直方图的方法,绘制一条固定的线表示直方图的底部,循环26次用Rectangle绘制直方图,同时添加图标
- (绘图方法详解)用Rectangle绘制图形时可以用counts中的最大数除以高作为每个字母个数+1的间距,矩形的高即为字母数量乘以这个值
- 矩形的x坐标从一个特定的值开始,每循环一次就增加一个值,y坐标为直方图的底部y坐标减去矩形的高
- 在循环内用Text添加图例,x稍大于矩形的x坐标,y稍大于直方图底部的y坐标,用ASCII码表示图例内容,从65开始一直+1,直到循环结束
-
2. HistogramPaneDemo类
- 创建一个int[] counts数组,并实例化 HistogramPane类,但不传入参数
- 创建一个HBox布局,添加Label、TextField、Button
- 创建BorderPane,把HistogramPane设置在中心,把HBox设置在底部
- 为按钮Button注册一个鼠标点击事件,事件被触发时检查TextField是否为空,不为空则以输入框内容为路径,用Scanner读取,while循环读取行,循环检查每一个字符,如果是字符,则把counts数组中的对应位置+1。while循环结束后调用HistogramPane的setCounts()方法
-
代码示例
编程练习题16_11HistogramPane.java
package chapter_16;import javafx.scene.chart.BarChart;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Line;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Text;public class 编程练习题16_11HistogramPane extends Pane{private int[] counts ;编程练习题16_11HistogramPane() {counts = new int[26];drawHistogram();}编程练习题16_11HistogramPane(int[] counts) {this.counts = counts;drawHistogram();}public int[] getCounts() {return counts;}public void setCounts(int[] counts) {this.counts = counts;getChildren().clear();drawHistogram();}public void drawHistogram() {int maxCount = 0;Line l = new Line(20, 200, 400, 200);for(int c:counts) {if(c > maxCount) {maxCount = c;}}int intervalV = 0;if(maxCount == 0) {intervalV = 0;}else intervalV = 200 / maxCount;int intervalH = 10;int x = 20; int n = 65;for(int i = 0;i < 26;i++) {int height = counts[i]*intervalV;//if(counts[i] == 0) height = 1;Rectangle r = new Rectangle(x,200-height,12,height);r.setFill(Color.TRANSPARENT);r.setStroke(Color.BLACK);Text num = new Text(x+2,212,(char)n+"");getChildren().addAll(r,num);x += intervalH+5;n++;}getChildren().addAll(l);}
}
编程练习题16_11HistogramPaneDemo.java
package chapter_16;import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;public class 编程练习题16_11HistogramPaneDemo extends Application{@Overridepublic void start(Stage primaryStage) throws Exception {int[] counts = new int[26];编程练习题16_11HistogramPane histogramPane = new 编程练习题16_11HistogramPane();HBox hBox = new HBox(10);hBox.setAlignment(Pos.CENTER);hBox.setStyle("-fx-border-color:black");TextField tfPath = new TextField();Label label = new Label("FilePath",tfPath);label.setContentDisplay(ContentDisplay.RIGHT);Button btView = new Button("View");hBox.getChildren().addAll(label, tfPath, btView);BorderPane borderPane = new BorderPane();borderPane.setCenter(histogramPane);borderPane.setBottom(hBox);btView.setOnMouseClicked(e ->{if(!tfPath.getText().isEmpty()) {try {String path = tfPath.getText();File file = new File(path);Scanner input = new Scanner(file);while(input.hasNextLine()) {String line = input.nextLine();for(char c:line.toCharArray()) {if(Character.isLetter(c)) {char c2 = Character.toUpperCase(c);if(c2 >='A'&&c2 <= 'Z') {counts[c2 - 'A']++;}}}}histogramPane.setCounts(counts);input.close();} catch (FileNotFoundException e1) {e1.printStackTrace();}}});Scene scene = new Scene(borderPane,420, 245);primaryStage.setTitle("编程练习题16_11HistogramPaneDemo");primaryStage.setScene(scene);primaryStage.show();}public static void main(String[] args) {Application.launch(args);}
}
-
结果展示
初始状态
显示结果