目录
题目:**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) {
System.out.println(c);
if(c > maxCount) {
maxCount = c;
}
}
System.out.println("max:"+maxCount);
double intervalV = 0.0;
if(maxCount == 0) {
intervalV = 0.0;
}else intervalV = 200.0 / maxCount;
double intervalH = 10.0;
int x = 20;
int n = 65;
for(int i = 0;i < 26;i++) {
double height = counts[i]*intervalV;
System.out.println("height:"+height);
//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{
@Override
public void start(Stage primaryStage) throws Exception {
int[] counts = new int[26];
编程练习题16_11HistogramPane histogramPane = new 编程练习题16_11HistogramPane(counts);
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.setOnMousePressed(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);
}
}
-
结果展示
初始状态
显示结果