自制文本文件編輯器


Text(6) Text Editor ——自制文本編輯器

題目描述:

Text Editor – Notepad style application that can open, edit, and save text documents. Add syntax highlighting and other features.

題目翻譯:

文本編輯器——編寫一個筆記本類型的應用,可以打開,編輯和保存文本文檔(text文檔)。可以添加一些語法高亮和其他的特性。

實現過程:

基於java的GUI框架javaFX來實現整個編輯器的功能。

使用java的textArea組件作為文本編輯器的編輯區,並且textArea已經集成了基本的文本編輯操作(復制,剪切,粘貼,撤銷,恢復,全選),所以編輯器的實現重點是文本文件的新建(create),保存(save)和另存為(save as)

接下來按照前端界面(front-end)和后端(back-end)講述文本編輯器的實現。

javaFX框架簡介

javaFX框架可以用來開發跨平台的GUI應用程序。

javaFX框架可以基於MVC模式來構建GUI應用程序。

javaFX框架使用FXML文件來定義用戶界面。(View層,展示數據),使用Controller來操作前端上的數據。

1.1 前端設計

整個編輯器主界面采用BorderPane布局(top,center,left,right,bottom五個子節點)。

top節點為菜單欄(MenuBar)

center節點設置為編輯區(editArea)

bottom節點設置為尾部狀態欄(state)

left節點暫定為行號顯示欄(暫時未實現)

image-20201117173652536

對於菜單欄:包括菜單,編輯,保存,字體調整等菜單(Menu)

菜單:

  1. 打開文件

  2. 新建文件

編輯:(javaFx的TextArea以及集成了全部功能,無須自己實現)

  1. 復制(copy)
  2. 剪切(cut)
  3. 粘貼(paste)
  4. 撤銷(undo)
  5. 恢復(consume)
  6. 高亮(highlight)

保存:

  1. 保存文件
  2. 另存為文件

字體調整:

設置三個級別的字體大小(small,middle,large)

整個編輯器界面對應的fxml文件如下:

<?xml version="1.0" encoding="UTF-8"?>

<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<BorderPane xmlns="http://javafx.com/javafx"
            xmlns:fx="http://javafx.com/fxml"
            fx:controller="com.sunfulv.ViewController"
            fx:id="borderPane"
            prefHeight="400.0" prefWidth="600.0">
    <top>
        <MenuBar>
            <Menu id="fileMenu" text="菜單">
                <MenuItem fx:id="openMenu" text="打開文件" onAction="#openFileAction"></MenuItem>
                <MenuItem id="createMenu" text="新建文件" onAction="#createFileAction"></MenuItem>
            </Menu>
            <Menu id="editMenu" text="編輯">
                <MenuItem fx:id="copyMenu" text="復制" onAction="#copyMenuAction"></MenuItem>
                <MenuItem id="cutMenu" text="剪切"></MenuItem>
                <MenuItem id="pasteMenu" text="粘貼"></MenuItem>
                <MenuItem id="undo" text="撤銷"></MenuItem>
                <MenuItem id="resumeMenu" text="恢復"></MenuItem>
            </Menu>
            <Menu id="saveMenu" text="保存" >
                <MenuItem id="save" text="保存文件" onAction="#saveFileAction"></MenuItem>
                <MenuItem id="saveAs" text="另存為" onAction="#saveAsFileAction"></MenuItem>
            </Menu>
            <Menu id="fontMenu" text="字體大小">
                <MenuItem id="smallFont" text="小字" onAction="#smallFontAction"></MenuItem>
                <MenuItem id="middleFont" text="中號字體" onAction="#middleFontAction"></MenuItem>
                <MenuItem id="largeFont" text="大號字體" onAction="#lagreFontAction"></MenuItem>
            </Menu>
        </MenuBar>
    </top>
    <center>
        <TextArea fx:id="textArea" text="Hello World">
        </TextArea>
    </center>
    <bottom >
        <AnchorPane snapToPixel="true"></AnchorPane>
    </bottom>
    <left>
        <
    </left>
</BorderPane>

1.2 后端設計

在設計完前端界面時,會為每個菜單綁定(onAction)事件響應方法,我們需要在后端實現這些事件響應方法。

在javaFX框架中,我們將這些事件響應方法統一定義在自定義的ViewController類中。同時在fxml文件中引入這個類。

首先在ViewController類中定義一個File實例,用於代表當前正被激活的文本文件(當前沒有打開的文件時,File實例默認為null)

在ViewController類中,使用@FXML注解來導入在fxml文件中定義的容器和組件

這里導入在fxml中定義的布局組件(borderPane)和文本區域組件(textArea)

@FXML private BorderPane borderPane;
@FXML private TextArea textArea;

在定義事件響應方法時,方法名要和fxml中各個菜單組件綁定的響應方法名相同,

在響應方法前添加@FXML注解, 可以將兩者綁定起來。

package com.sunfulv;

import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.scene.layout.BorderPane;
import javafx.stage.FileChooser;
import javafx.stage.Stage;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.Optional;


public class ViewController {


    File currentFile = null;//始終代表當前編輯框中對應的文件
    @FXML private BorderPane borderPane;
    @FXML private TextArea textArea;
    //打開文件
    @FXML protected void openFileAction(ActionEvent event) throws IOException {
        FileChooser fileChooser = new FileChooser();
        fileChooser.setTitle("打開所選文件");
        fileChooser.getExtensionFilters().addAll( //添加文件過濾器,默認只允許文本文件
                new FileChooser.ExtensionFilter("文本文件","*.txt"),
                new FileChooser.ExtensionFilter("全部文件","*.*")
        );

        Stage currentStage = (Stage)borderPane.getScene().getWindow();
        currentFile = fileChooser.showOpenDialog(currentStage);//讀取選中的文件
        if(currentFile == null) return; //如果沒有選擇要打開的文件,直接返回
        currentStage.setTitle("Text Editor-"+currentFile.getName());
        //System.out.println(textFile.getName());

        FileInputStream fin= null;
        Reader fr = null;
        try {
            fin= new FileInputStream(currentFile);
            fr = new InputStreamReader(fin, StandardCharsets.UTF_8); //默認使用utf8格式打開
            String str = null;
            char[] byteArray = new char[(int) currentFile.length()];
            fr.read(byteArray);
            str = new String(byteArray);
            System.out.println(str);
            textArea.setText(str);
        }catch(Exception e){
            e.printStackTrace();
        }finally{
            fr.close();
        }
    }

    // 新建文件
    @FXML protected void createFileAction(ActionEvent event) throws IOException{
        //新建一個文件前,首先確認是否保存當前正在編輯的文件
        Alert alert = new Alert(Alert.AlertType.INFORMATION,"是否保存當前文件!",new ButtonType("是", ButtonBar.ButtonData.YES),new ButtonType("否",ButtonBar.ButtonData.NO));
        alert.setHeaderText("提示信息");
        Optional<ButtonType> buttonType = alert.showAndWait(); //顯示對話框,並等待返回,用於確定對話框選擇的是確認按鈕還是取消按鈕
        if(buttonType.get().getButtonData().equals(ButtonBar.ButtonData.YES)){ //如果選擇的是,表明要保存當前正在編輯的文件
            ////判斷當前編輯框中沒有打開的文件,如果沒有,直接清空當前編輯框
            if(currentFile !=null)
                saveFile(currentFile);
        }else{
            return;
        }

        textArea.setText(""); //清空當前編輯框
        currentFile = null;
        Stage currentStage = (Stage)borderPane.getScene().getWindow();
        currentStage.setTitle("Text Editor-"+"未命名文件");

    }

    // 保存文件
    @FXML protected void saveFileAction(ActionEvent event) throws IOException{
        //保存當前編輯器中的內容
        if(currentFile !=null) //如果當前有打開的文件,可以進行保存,否則將當前編輯框中的內容另存為一個新的文件
            saveFile(currentFile);
        else {
            if(saveAsFile()) {
                Stage currentStage = (Stage) borderPane.getScene().getWindow();
                currentStage.setTitle("Text Editor-" + currentFile.getName());
            }
        }
    }
    //文件另存為
    @FXML protected void saveAsFileAction(ActionEvent event) throws IOException{
        saveAsFile();
    }

    //字體大小調整

    @FXML protected void smallFontAction(ActionEvent event){
        textArea.setStyle("-fx-font-size: 20px");
    }

    @FXML protected void middleFontAction(ActionEvent event){
        textArea.setStyle("-fx-font-size: 40px");
    }

    @FXML protected void lagreFontAction(ActionEvent event){
        textArea.setStyle("-fx-font-size: 60px");
    }
    //保存當前正在編輯的文件(將編輯框中的字符串保存到對應的文件中)
    private boolean saveFile(File currentFile) throws IOException{
        String currentStr = textArea.getText();//讀取編輯框中的內容
        Writer writer = null;
        try {
            writer = new FileWriter(currentFile);
            char[] byteArray = currentStr.toCharArray();
            writer.write(byteArray);
    //            System.out.println(new String(byteArray));
            return true;
        }catch(Exception e){
            e.printStackTrace();
            return false;
        }finally{
            writer.close();
        }
    }

    // 將當前編輯框中的內容另存為一個新的文件
    protected boolean saveAsFile() throws IOException{
        //新建一個txt文件
        FileChooser createFileChooser = new FileChooser();
        createFileChooser.setTitle("另存為");
        createFileChooser.getExtensionFilters().addAll( //添加文件過濾器,默認只允許文本文件
                new FileChooser.ExtensionFilter("文本文件","*.txt"),
                new FileChooser.ExtensionFilter("全部文件","*.*")
        );
        Stage currentStage = (Stage)borderPane.getScene().getWindow();
        File newFile = createFileChooser.showSaveDialog(currentStage);
        if(newFile == null) //如果沒有選擇要將文件另存為,直接返回
            return false;
        saveFile(newFile);
        currentFile = newFile;
        System.out.println(newFile.getName());
        return true;
    }
}






免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM