一.实验要求
二.设计界面
1.主界面Notepad.fxml
2.查找与替换界面Find.fxml
3.字体界面Font.fxml
三.主要功能
1.文件操作
1.1新建文件
//文件新建
@FXML
void OnActionNew(ActionEvent event) throws FileNotFoundException, IOException, InterruptedException {
//没保存的话要保存
if(!isSaved)
RequireSave();
noteTextArea.setText(null);
}
1.2保存文件
//文件保存 获取TextArea区域的内容,打开文件存储
@FXML
void OnActionSave(ActionEvent event) throws FileNotFoundException, IOException
{
String text=noteTextArea.getText();
if(text.equals(""))
return;
FileChooser fileChooser = new FileChooser();
//文件类型过滤
FileChooser.ExtensionFilter extensionFilter = new FileChooser.ExtensionFilter("文本文档(*.txt)","*.txt");
fileChooser.getExtensionFilters().add(extensionFilter);
Stage stage=getStage();
//获取得到的文件
file = fileChooser.showOpenDialog(stage);
if(file==null)
return;
fileOperation.WriteFile(file, "UTF-8", text);
isSaved=true;
}
1.3另存为文件
//文件另存为 获取TextArea区域的内容
@FXML
void OnActionOtherSave(ActionEvent event) throws FileNotFoundException, IOException {
String text=noteTextArea.getText();
FileChooser fileChooser = new FileChooser();
//文件类型过滤
FileChooser.ExtensionFilter extensionFilter = new FileChooser.ExtensionFilter("文本文档(*.txt)","*.txt");
fileChooser.getExtensionFilters().add(extensionFilter);
Stage stage=getStage();
//获取得到的文件
file=fileChooser.showSaveDialog(stage);
if(file==null)
return;
fileOperation.WriteFile(file, "UTF-8", text);
isSaved=true;
}
1.4打开文件
//文件打开 打开一个txt文件,显示在TextArea上
@FXML
void OnActionOpen(ActionEvent event) throws IOException
{
//打开资源管理器
FileChooser fileChooser = new FileChooser();
//文件类型过滤
FileChooser.ExtensionFilter extensionFilter = new FileChooser.ExtensionFilter("文本文档(*.txt)","*.txt");
fileChooser.getExtensionFilters().add(extensionFilter);
Stage stage=getStage();
//获取得到的文件
file = fileChooser.showOpenDialog(stage);
if(file==null)
return;
String text=fileOperation.ReadFile(file,"UTF-8");
noteTextArea.setText(text);
isSaved=true;
}
2.查找操作
2.1查找上一个
// 查找上一个
@FXML
void OnActionLast(ActionEvent event)
{
String target=findTextField.getText();
String noteText=noteTextArea.getText();
if (target.isEmpty())
{
Warning("查找文本为空!");
return;
}
//查找文本不为空
if (noteText.contains(target))
{
fromIndex=noteText.lastIndexOf(target, fromIndex);
if (fromIndex == -1)
{
Warning("到第一个了");
return;
}
if (fromIndex >= 0 && fromIndex < noteText.length())
{
System.out.println("fromindex:"+fromIndex);
noteTextArea.selectRange(fromIndex, fromIndex+target.length());
fromIndex -= target.length();
}
}
else
Warning("找不到相关内容");
}
2.2查找下一个
//查找下一个
@FXML
void OnActionNext(ActionEvent event)
{
String target=findTextField.getText();
String noteText=noteTextArea.getText();
if (target.isEmpty())
{
Warning("查找文本为空!");
return;
}
//查找文本不为空
if (noteText.contains(target))
{
System.out.println(startIndex);
fromIndex=startIndex;
startIndex = noteText.indexOf(target, startIndex);
if (startIndex == -1)
{
Warning("到最后一个了");
return;
}
if (startIndex >= 0 && startIndex < noteText.length())
{
noteTextArea.selectRange(startIndex, startIndex + target.length());
startIndex += target.length();
}
}
else
Warning("找不到相关内容");
}
3.替换操作
3.1一个一个替换
//一个一个替换
@FXML
void OnActionReplace(ActionEvent event) {
String target=findTextField.getText();
String replaceText=replaceTextField.getText();
String noteText=noteTextArea.getText();
if(replaceText.isEmpty())
{
Warning("替换文本不能为空!");
return;
}
if(noteText.contains(target))
{
fromIndex=startIndex;
startIndex = noteText.indexOf(target, startIndex);
if (startIndex == -1)
{
Warning("已经替换到最后一个了");
return;
}
if (startIndex >= 0 && startIndex < noteText.length())
{
noteTextArea.selectRange(startIndex, startIndex + target.length());
startIndex += target.length();
}
noteTextArea.replaceSelection(replaceText);
}
else
Warning("找不到相关内容");
}
3.2全部替换
//一个一个替换
@FXML
void OnActionReplace(ActionEvent event) {
String target=findTextField.getText();
String replaceText=replaceTextField.getText();
String noteText=noteTextArea.getText();
if(replaceText.isEmpty())
{
Warning("替换文本不能为空!");
return;
}
if(noteText.contains(target))
{
fromIndex=startIndex;
startIndex = noteText.indexOf(target, startIndex);
if (startIndex == -1)
{
Warning("已经替换到最后一个了");
return;
}
if (startIndex >= 0 && startIndex < noteText.length())
{
noteTextArea.selectRange(startIndex, startIndex + target.length());
startIndex += target.length();
}
noteTextArea.replaceSelection(replaceText);
}
else
Warning("找不到相关内容");
}
4.字体操作
4.1改变字体
//改变字体
@FXML
void fontChange(ActionEvent event) {
FontType=fontComboBox.getValue();
font=Font.font(FontType,FontSize);
sampleTextArea.setFont(font);
}
4.2改变样式
注意这个功能不是对所有字体都适用,所以不用纠结为什么有的效果不展示
//改变风格
@FXML
void styleChange(ActionEvent event) {
switch(styleComboBox.getValue())
{
case "常规":font=Font.font(FontType,FontWeight.NORMAL,
FontPosture.REGULAR,FontSize);break;
case "粗体":font=Font.font(FontType,FontWeight.BOLD,
FontPosture.REGULAR,FontSize);break;
case "斜体":font=Font.font(FontType,FontWeight.NORMAL,
FontPosture.ITALIC,FontSize);break;
case "粗斜体":font=Font.font(FontType,FontWeight.BOLD,
FontPosture.ITALIC,FontSize);break;
}
sampleTextArea.setFont(font);
}
4.3改变大小
//改变大小
@FXML
void sizeChange(ActionEvent event) {
FontSize=Integer.parseInt(sizeComboBox.getValue());
font=Font.font(FontType,FontSize);
sampleTextArea.setFont(font);
}
四.全部代码
1.主界面
1.1FileController
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Optional;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.ButtonType;
import javafx.scene.control.Label;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TextArea;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.text.Font;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
/**
* @author xuchi
* 2022年5月15日
*/
public class FileController {
@FXML
private TextArea noteTextArea;
@FXML
private MenuItem backMenuItem;
@FXML
private MenuItem redoMenuItem;
@FXML
private MenuItem findMenuItem;
@FXML
private MenuItem replaceMenuItem;
@FXML
private Label posLabel;
@FXML
private Label scaleLabel;
File file;
FileOperation fileOperation;
public boolean isReplace=false;
public boolean isChanged=false;
public boolean isSaved=false;
// 初始化
@FXML
void initialize()
{
//把controller加到hashmap:controllers里
Main.controllers.put(this.getClass().getSimpleName(), this);
//实例化文件操作类
fileOperation=new FileOperation();
//初始化撤销重做,查找按钮
backMenuItem.setDisable(true);
redoMenuItem.setDisable(true);
findMenuItem.setDisable(true);
replaceMenuItem.setDisable(true);
//释放键盘之后,撤销键可用
noteTextArea.setOnKeyReleased(e->
{
//对于撤销重做
backMenuItem.setDisable(false);
//对于查找
if(!noteTextArea.getText().isEmpty())
{
findMenuItem.setDisable(false);
replaceMenuItem.setDisable(false);
}
else
{
findMenuItem.setDisable(true);
replaceMenuItem.setDisable(true);
}
});
//只要文本值改变了
noteTextArea.textProperty()
.addListener(new ChangeListener<String>()
{
@Override
public void changed
(ObservableValue<? extends String> observable,
String oldValue, String newValue)
{
isChanged=true;
}
});
//点击查找
findMenuItem.setOnAction(e->
{
isReplace=false;
try
{
ShowFXML("Find.fxml","查找");
} catch (IOException e1)
{
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
);
replaceMenuItem.setOnAction(e->
{
isReplace=true;
try
{
ShowFXML("Find.fxml","替换");
} catch (IOException e1)
{
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
);
//当前光标的位置
noteTextArea.caretPositionProperty().addListener((o,oldValue,newValue)->{
int num= newValue.intValue();
String textContain=noteTextArea.getText();
int line=1,col=1;
for(int i=0;i<num;i++)
{
if(textContain.charAt(i)=='\n')
{
line++;
col=1;
}
else
col++;
}
String posText=String.format("第 %d 行,第 %d 列",line,col);
posLabel.setText(posText);
});
}
public TextArea getTextArea()
{
return noteTextArea;
}
public boolean RequireSave() throws FileNotFoundException, IOException, InterruptedException {
// TODO Auto-generated method stub
if(!isChanged)
return false;
Alert alert = new Alert(AlertType.CONFIRMATION);
alert.setHeaderText("记事本");
if(isSaved&&isChanged)
alert.setContentText("是否将更改保存到"+file.getPath()+"?");
else if(!isSaved)
alert.setContentText("是否保存?");
ButtonType save = new ButtonType("保存");
ButtonType notsave = new ButtonType("不保存");
ButtonType cancel = new ButtonType("取消");
alert.getButtonTypes().setAll(save, notsave,cancel);
Optional<ButtonType> result = alert.showAndWait();
if(result.get()==notsave)
return false;
if(result.get()==cancel)
return true;
if(isSaved&&isChanged)
fileOperation.WriteFile(file, "UTF-8", noteTextArea.getText());
else if(!isSaved)
{
String text=noteTextArea.getText();
FileChooser fileChooser = new FileChooser();
//文件类型过滤
FileChooser.ExtensionFilter extensionFilter = new FileChooser.ExtensionFilter("文本文档(*.txt)","*.txt");
fileChooser.getExtensionFilters().add(extensionFilter);
Stage stage=getStage();
//获取得到的文件
file=fileChooser.showSaveDialog(stage);
//字体关闭,取消回到原位,
if(file==null)
return false;
fileOperation.WriteFile(file, "UTF-8", text);
isSaved=true;
}
return false;
}
//右键菜单->复制
@FXML
void OnActionCopy(ActionEvent event) {
noteTextArea.copy();
}
//右键菜单->粘贴
@FXML
void OnActionPaste(ActionEvent event) {
noteTextArea.paste();
}
//右键菜单->全选
@FXML
void OnActionSelectAll(ActionEvent event) {
noteTextArea.selectAll();
}
//右键菜单->剪切
@FXML
void OnActionCut(ActionEvent event) {
noteTextArea.cut();
}
//帮助
@FXML
void OnActionHelp(ActionEvent event) throws IOException {
ShowFXML("Help.fxml", "帮助");
}
//缩放->字体变大
@FXML
void OnActionBig(ActionEvent event) {
Font CurrentFont = noteTextArea.getFont();
double NewSize = CurrentFont.getSize() + 1;
Font NewFont = Font.font(CurrentFont.getName(), NewSize);
noteTextArea.setFont(NewFont);
int scale=Integer.parseInt(scaleLabel.getText());
scale+=10;
scaleLabel.setText(Integer.toString(scale));
}
//缩放->字体变小
@FXML
void OnActionSmall(ActionEvent event) {
Font CurrentFont = noteTextArea.getFont();
double NewSize = CurrentFont.getSize() - 1;
Font NewFont = Font.font(CurrentFont.getName(), NewSize);
noteTextArea.setFont(NewFont);
int scale=Integer.parseInt(scaleLabel.getText());
scale-=10;
scaleLabel.setText(Integer.toString(scale));
}
//展示查找与替换界面
private void ShowFXML(String FxmlName,String title) throws IOException
{
// 初始化fxml界面
Stage FindStage = new Stage();
Parent root = FXMLLoader.load(getClass().getResource(FxmlName));
Scene scene = new Scene(root, 350, 70);
FindStage.setScene(scene);
FindStage.setTitle(title);
FindStage.show();
// 查找
}
//自动换行
@FXML
void OnActionWrap(ActionEvent event) {
noteTextArea.wrapTextProperty().set(true);
}
//重做
@FXML
void OnActionRedo(ActionEvent event) {
noteTextArea.redo();
redoMenuItem.setDisable(true);
backMenuItem.setDisable(false);
}
//撤销一步
@FXML
void OnActionBack(ActionEvent event) {
noteTextArea.undo();
backMenuItem.setDisable(true);
redoMenuItem.setDisable(false);
}
//文件新建
@FXML
void OnActionNew(ActionEvent event) throws FileNotFoundException, IOException, InterruptedException {
//没保存的话要保存
if(!isSaved)
RequireSave();
noteTextArea.setText(null);
}
//文件另存为 获取TextArea区域的内容
@FXML
void OnActionOtherSave(ActionEvent event) throws FileNotFoundException, IOException {
String text=noteTextArea.getText();
FileChooser fileChooser = new FileChooser();
//文件类型过滤
FileChooser.ExtensionFilter extensionFilter = new FileChooser.ExtensionFilter("文本文档(*.txt)","*.txt");
fileChooser.getExtensionFilters().add(extensionFilter);
Stage stage=getStage();
//获取得到的文件
file=fileChooser.showSaveDialog(stage);
if(file==null)
return;
fileOperation.WriteFile(file, "UTF-8", text);
isSaved=true;
}
//文件保存 获取TextArea区域的内容,打开文件存储
@FXML
void OnActionSave(ActionEvent event) throws FileNotFoundException, IOException
{
String text=noteTextArea.getText();
if(text.equals(""))
return;
FileChooser fileChooser = new FileChooser();
//文件类型过滤
FileChooser.ExtensionFilter extensionFilter = new FileChooser.ExtensionFilter("文本文档(*.txt)","*.txt");
fileChooser.getExtensionFilters().add(extensionFilter);
Stage stage=getStage();
//获取得到的文件
file = fileChooser.showOpenDialog(stage);
if(file==null)
return;
fileOperation.WriteFile(file, "UTF-8", text);
isSaved=true;
}
//文件打开 打开一个txt文件,显示在TextArea上
@FXML
void OnActionOpen(ActionEvent event) throws IOException
{
//打开资源管理器
FileChooser fileChooser = new FileChooser();
//文件类型过滤
FileChooser.ExtensionFilter extensionFilter = new FileChooser.ExtensionFilter("文本文档(*.txt)","*.txt");
fileChooser.getExtensionFilters().add(extensionFilter);
Stage stage=getStage();
//获取得到的文件
file = fileChooser.showOpenDialog(stage);
if(file==null)
return;
String text=fileOperation.ReadFile(file,"UTF-8");
noteTextArea.setText(text);
isSaved=true;
}
// 获取当前stage
private Stage getStage()
{
return (Stage) noteTextArea.getScene().getWindow();
}
//进入字体界面
@FXML
void OnActionFont(ActionEvent event) throws IOException
{
// 初始化fxml界面
Stage FindStage = new Stage();
Parent root = FXMLLoader.load(getClass().getResource("Font.fxml"));
Scene scene = new Scene(root, 400, 400);
FindStage.setScene(scene);
FindStage.setTitle("字体");
FindStage.show();
}
}
1.2FileOperation
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
/**
* @author xuchi
* 2022年5月15日
*/
public class FileOperation {
//读文件
public String ReadFile(File file,String CharType) throws IOException
{
String text = "";
// 1.创建InputStreamReader对象,构造方法中传递字节输入流和指定的编码表名称
InputStreamReader isr = new InputStreamReader(new FileInputStream(file), CharType);
// 2.使用InputStreamReader对象中的方法read读取文件
int ch = 0;
while ((ch = isr.read()) != -1)
text += (char) ch;
// 3.释放资源。
isr.close();
return text;
}
//写文件
public void WriteFile(File file,String CharType,String content) throws IOException, FileNotFoundException
{
OutputStreamWriter osw=new OutputStreamWriter(new FileOutputStream(file), CharType);
osw.write(content);
osw.close();
}
}
1.3Notepad.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.FileController">
<top>
<MenuBar BorderPane.alignment="CENTER">
<menus>
<Menu mnemonicParsing="false" text="文件">
<items>
<MenuItem mnemonicParsing="false" onAction="#OnActionNew" text="新建" />
<MenuItem mnemonicParsing="false" onAction="#OnActionSave" text="保存" />
<MenuItem mnemonicParsing="false" onAction="#OnActionOtherSave" text="另存为" />
<MenuItem mnemonicParsing="false" onAction="#OnActionOpen" text="打开" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="编辑">
<items>
<MenuItem fx:id="backMenuItem" mnemonicParsing="false" onAction="#OnActionBack" text="撤销" />
<MenuItem fx:id="redoMenuItem" mnemonicParsing="false" onAction="#OnActionRedo" text="重做" />
<MenuItem fx:id="findMenuItem" mnemonicParsing="false" text="查找" />
<MenuItem fx:id="replaceMenuItem" mnemonicParsing="false" text="替换" />
<MenuItem mnemonicParsing="false" onAction="#OnActionFont" text="字体" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="查看">
<items>
<MenuItem mnemonicParsing="false" onAction="#OnActionHelp" text="帮助" />
<MenuItem mnemonicParsing="false" onAction="#OnActionWrap" text="自动换行" />
<Menu mnemonicParsing="false" text="缩放">
<items>
<MenuItem mnemonicParsing="false" onAction="#OnActionBig" text="放大" />
<MenuItem mnemonicParsing="false" onAction="#OnActionSmall" text="缩小" />
</items>
</Menu>
</items>
</Menu>
</menus>
</MenuBar>
</top>
<center>
<TextArea fx:id="noteTextArea" prefHeight="200.0" prefWidth="200.0" BorderPane.alignment="CENTER">
<contextMenu>
<ContextMenu>
<items>
<MenuItem mnemonicParsing="false" onAction="#OnActionCopy" text="复制" />
<MenuItem mnemonicParsing="false" onAction="#OnActionPaste" text="粘贴" />
<MenuItem mnemonicParsing="false" onAction="#OnActionSelectAll" text="全选" />
<MenuItem mnemonicParsing="false" onAction="#OnActionCut" text="剪切" />
</items>
</ContextMenu>
</contextMenu></TextArea>
</center>
<bottom>
<HBox prefHeight="36.0" prefWidth="600.0" BorderPane.alignment="CENTER">
<children>
<Label fx:id="posLabel" prefHeight="34.0" prefWidth="225.0" text="行1,列1" />
<Separator orientation="VERTICAL" prefHeight="36.0" prefWidth="0.0" />
<Label fx:id="scaleLabel" prefHeight="36.0" prefWidth="39.0" text="100" />
<Label prefHeight="37.0" prefWidth="51.0" text="\%" />
<Separator orientation="VERTICAL" prefHeight="200.0" />
<Label prefHeight="36.0" prefWidth="161.0" text="Windows(CRLF)" />
<Separator orientation="VERTICAL" prefHeight="200.0" />
<Label prefHeight="40.0" prefWidth="55.0" text="UTF-8" />
</children>
</HBox>
</bottom>
</BorderPane>
2.查找与替换
2.1FindController
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Alert;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.Button;
/**
* @author xuchi
* 2022年5月18日
*/
public class FindController {
@FXML
private TextField findTextField;
@FXML
public TextField replaceTextField;
@FXML
public Button replaceButton;
@FXML
public Button replaceallButton;
TextArea noteTextArea;
int startIndex=0;
int fromIndex;
//初始化,得到filecontroller
@FXML
void initialize()
{
FileController controller = (FileController) Main.controllers.get(FileController.class.getSimpleName());
noteTextArea=controller.getTextArea();
fromIndex=noteTextArea.getText().length();
if(controller.isReplace)
{
replaceallButton.setVisible(true);
replaceButton.setVisible(true);
replaceTextField.setVisible(true);
}
}
// 用于弹出警示
private void Warning(String warningInfo)
{
Alert alert = new Alert(AlertType.WARNING);
alert.setTitle("Warning Dialog");
alert.setContentText(warningInfo);
alert.showAndWait();
}
// 查找上一个
@FXML
void OnActionLast(ActionEvent event)
{
String target=findTextField.getText();
String noteText=noteTextArea.getText();
if (target.isEmpty())
{
Warning("查找文本为空!");
return;
}
//查找文本不为空
if (noteText.contains(target))
{
fromIndex=noteText.lastIndexOf(target, fromIndex);
if (fromIndex == -1)
{
Warning("到第一个了");
return;
}
if (fromIndex >= 0 && fromIndex < noteText.length())
{
System.out.println("fromindex:"+fromIndex);
noteTextArea.selectRange(fromIndex, fromIndex+target.length());
fromIndex -= target.length();
}
}
else
Warning("找不到相关内容");
}
//查找下一个
@FXML
void OnActionNext(ActionEvent event)
{
String target=findTextField.getText();
String noteText=noteTextArea.getText();
if (target.isEmpty())
{
Warning("查找文本为空!");
return;
}
//查找文本不为空
if (noteText.contains(target))
{
System.out.println(startIndex);
fromIndex=startIndex;
startIndex = noteText.indexOf(target, startIndex);
if (startIndex == -1)
{
Warning("到最后一个了");
return;
}
if (startIndex >= 0 && startIndex < noteText.length())
{
noteTextArea.selectRange(startIndex, startIndex + target.length());
startIndex += target.length();
}
}
else
Warning("找不到相关内容");
}
//一个一个替换
@FXML
void OnActionReplace(ActionEvent event) {
String target=findTextField.getText();
String replaceText=replaceTextField.getText();
String noteText=noteTextArea.getText();
if(replaceText.isEmpty())
{
Warning("替换文本不能为空!");
return;
}
if(noteText.contains(target))
{
fromIndex=startIndex;
startIndex = noteText.indexOf(target, startIndex);
if (startIndex == -1)
{
Warning("已经替换到最后一个了");
return;
}
if (startIndex >= 0 && startIndex < noteText.length())
{
noteTextArea.selectRange(startIndex, startIndex + target.length());
startIndex += target.length();
}
noteTextArea.replaceSelection(replaceText);
}
else
Warning("找不到相关内容");
}
//全部替换
@FXML
void OnActionReplaceAll(ActionEvent event) {
String target=findTextField.getText();
String replaceText=replaceTextField.getText();
String noteText=noteTextArea.getText();
noteTextArea.setText(noteText.replaceAll(target, replaceText));
}
}
2.2Find.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="187.0" prefWidth="470.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.FindController">
<children>
<GridPane layoutX="8.0" layoutY="4.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="116.0" minWidth="10.0" prefWidth="110.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="95.0" minWidth="10.0" prefWidth="90.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<TextField fx:id="findTextField" promptText="查找" />
<Button mnemonicParsing="false" onAction="#OnActionLast" text="上一条" GridPane.columnIndex="1" />
<Button mnemonicParsing="false" onAction="#OnActionNext" text="下一条" GridPane.columnIndex="2" />
<TextField fx:id="replaceTextField" promptText="替换" visible="false" GridPane.rowIndex="1" />
<Button fx:id="replaceButton" mnemonicParsing="false" onAction="#OnActionReplace" text="替换" visible="false" GridPane.columnIndex="1" GridPane.rowIndex="1" />
<Button fx:id="replaceallButton" mnemonicParsing="false" onAction="#OnActionReplaceAll" text="全部替换" visible="false" GridPane.columnIndex="2" GridPane.rowIndex="1" />
</children>
</GridPane>
</children>
</AnchorPane>
3.字体
3.1FontController
import java.util.List;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.ComboBox;
import javafx.scene.control.TextArea;
import javafx.scene.text.Font;
import javafx.scene.text.FontPosture;
import javafx.scene.text.FontWeight;
import javafx.stage.Stage;
/**
* @author xuchi
* 2022年5月18日
*/
public class FontController {
@FXML
private ComboBox<String> fontComboBox;
@FXML
private ComboBox<String> styleComboBox;
@FXML
private ComboBox<String> sizeComboBox;
@FXML
private TextArea sampleTextArea;
TextArea noteTextArea;
//用于实时记录字体,大小
private String FontType="System Regular";
private int FontSize=12;
private Font font;
//初始化文本和combobox
@FXML
void initialize()
{
//向combobox里加入字体,样式,大小
List<String> FontList=Font.getFontNames();
fontComboBox.getItems().addAll(FontList);
ObservableList<String> StyleList=
FXCollections.observableArrayList("常规","粗体","斜体","粗斜体");
styleComboBox.setItems(StyleList);
for(int i=2;i<=72;i=i+2)
sizeComboBox.getItems().add(i+"");
//初始化测试文本
sampleTextArea.setText("这是测试文本");
FileController controller = (FileController) Main.controllers.get(FileController.class.getSimpleName());
noteTextArea=controller.getTextArea();
}
//改变字体
@FXML
void fontChange(ActionEvent event) {
FontType=fontComboBox.getValue();
font=Font.font(FontType,FontSize);
sampleTextArea.setFont(font);
}
//改变风格
@FXML
void styleChange(ActionEvent event) {
switch(styleComboBox.getValue())
{
case "常规":font=Font.font(FontType,FontWeight.NORMAL,
FontPosture.REGULAR,FontSize);break;
case "粗体":font=Font.font(FontType,FontWeight.BOLD,
FontPosture.REGULAR,FontSize);break;
case "斜体":font=Font.font(FontType,FontWeight.NORMAL,
FontPosture.ITALIC,FontSize);break;
case "粗斜体":font=Font.font(FontType,FontWeight.BOLD,
FontPosture.ITALIC,FontSize);break;
}
sampleTextArea.setFont(font);
}
//改变大小
@FXML
void sizeChange(ActionEvent event) {
FontSize=Integer.parseInt(sizeComboBox.getValue());
font=Font.font(FontType,FontSize);
sampleTextArea.setFont(font);
}
//确认后自动关闭设置字体的界面
@FXML
void notepadFontChange(ActionEvent event) {
noteTextArea.setFont(font);
Stage stage=(Stage)sampleTextArea.getScene().getWindow();
stage.close();
}
}
3.2Font.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.FontController">
<children>
<GridPane layoutX="51.0" layoutY="43.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<ComboBox fx:id="fontComboBox" onAction="#fontChange" prefWidth="150.0" GridPane.rowIndex="1" />
<ComboBox fx:id="styleComboBox" onAction="#styleChange" prefWidth="150.0" GridPane.columnIndex="1" GridPane.rowIndex="1" />
<ComboBox fx:id="sizeComboBox" onAction="#sizeChange" prefWidth="150.0" GridPane.columnIndex="2" GridPane.rowIndex="1" />
<Label text="字体" />
<Label text="样式" GridPane.columnIndex="1" />
<Label text="大小" GridPane.columnIndex="2" />
</children>
</GridPane>
<TextArea fx:id="sampleTextArea" layoutX="43.0" layoutY="135.0" prefHeight="156.0" prefWidth="312.0" />
<Button layoutX="158.0" layoutY="307.0" mnemonicParsing="false" onAction="#notepadFontChange" text="确认" />
</children>
</AnchorPane>
4.帮助
4.1HelpController
import javafx.fxml.FXML;
import javafx.scene.control.Label;
/**
* @author xuchi
* 2022年5月20日
*/
public class HelpController {
@FXML
private Label helpLabel;
@FXML
void initialize()
{
helpLabel.setText("author:xuchi");
}
}
4.2Help.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.HelpController">
<children>
<Label fx:id="helpLabel" layoutX="14.0" layoutY="14.0" text="Label" />
</children>
</AnchorPane>
5.Main
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.fxml.FXMLLoader;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import javafx.scene.Parent;
import javafx.scene.Scene;
public class Main extends Application {
//创建一个Controller容器
public static Map<String, Object> controllers = new HashMap<String, Object>();
@Override
public void start(Stage primaryStage) {
try {
Parent root =FXMLLoader.load(getClass().getResource("Notepad.fxml"));
Scene scene = new Scene(root,600,400);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.setTitle("新建");
primaryStage.show();
FileController controller = (FileController) Main.controllers.get(FileController.class.getSimpleName());
primaryStage.setOnCloseRequest((EventHandler<WindowEvent>) new EventHandler<WindowEvent>() {
@Override
public void handle(WindowEvent event)
{
try
{
//监听窗口关闭,询问是否保存,点击取消时,主界面继续运行,不能关闭
if(controller.RequireSave())
event.consume();
}
catch (IOException | InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
五.实验总结
1.不同controller之间的相互通信
我在做查找与替换的功能的时候,不知道怎么在FindController里面获取到FileController里的noteTextArea,也不知道怎么在一个controller里对另一个controller里的控件进行操作
解决办法:
在FileController里的initialize函数里写
Main.controllers.put(this.getClass().getSimpleName(), this);
然后在FindController里写
FileController controller = (FileController) Main.controllers
.get(FileController.class.getSimpleName());
noteTextArea=controller.getTextArea();
2.监听窗口关闭函数
primaryStage.setOnCloseRequest((EventHandler<WindowEvent>) new EventHandler<WindowEvent>() {
@Override
public void handle(WindowEvent event)
{
//这里写监听到之后要做的
}
});
3.展示其他fxml
//展示查找与替换界面
private void ShowFXML(String FxmlName,String title) throws IOException
{
// 初始化fxml界面
Stage FindStage = new Stage();
Parent root = FXMLLoader.load(getClass().getResource(FxmlName));
Scene scene = new Scene(root, 350, 70);
FindStage.setScene(scene);
FindStage.setTitle(title);
FindStage.show();
}
4.文件类型过滤
//文件类型过滤
FileChooser.ExtensionFilter extensionFilter = new FileChooser.ExtensionFilter
("文本文档(*.txt)","*.txt");
fileChooser.getExtensionFilters().add(extensionFilter);