1. 程式人生 > >【無浪】花了兩週時間純手打打出來的Java記事本

【無浪】花了兩週時間純手打打出來的Java記事本

最近的大作業是記事本,兩週的大塊時間和碎片時間都花在這上面了,資料結構已經落下了,要惡補了。

注意這個記事本在沒有聯網的時候會在關於記事本類中的一個JLabel標籤裡停下,該標籤使用了HTML連向一張圖片,所以不聯網的時候把這個JLabel刪掉即可開啟,或者聯網就能正常開啟。

PS:由於當時是初學Java,看到中文能作為變數名很新鮮,且這樣子可讀性較好。但是建議Java不要用中文名

       手推程式碼幫了很多忙。

難度以★來表示

1.Windows記事本已有功能:

【新建】(★★★)

【開啟】(★★★)

【儲存】(★★★★)

【另存為】(★★★)

【頁面設定】(★★)

【列印】(★★★★★)

【退出】(★★)

【撤銷】(★★)

【剪下】(★)

【複製】(★)

【貼上】(★)

【刪除】(★)

【查詢】(★★★★★)

【查詢下一個】(★)

【替換】(★)

【轉到】(★)

【全選】()

【時間日期】()

【自動換行】()

【字型】(★)

【狀態列】()

【幫助文件】(★★)

【關於記事本】(★)

2.自己擴充套件的功能

【加密解密】(★★★★)

【即時存檔】(★★)

【即讀讀檔】(★★)

【清空文字】()

【字型顏色】()

【背景顏色】()

【顯示行號】()

[文字區域拖拽字串移動其位置] (★★★)

[拖動txt檔案到文字區域開啟檔案] (★★)

[文字框左側顯示行數](★★★★)


import java.awt.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetAdapter;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Stack;
import java.util.List;
import javax.swing.*;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeSelectionModel;



//檔案->新建N CTRL+N
class NewC implements ActionListener {
	private JTextArea editText;
	private boolean choose;
	public JFrame frame;
	public static String path1;//在開啟的事件中path1="";
	public String str;
	NewC() {
		this.editText = JLinePrint.editText;
		path1="";
		NewMenu();
	}//新建
	public void NewMenu(){
		//建立詢問框,設定大小位置,設為自己佈局
		frame=new JFrame("記事本");
		frame.setBounds(424, 269, 355, 181);
		frame.setLayout(null);
		//建立兩個標籤
		JLabel label1=new JLabel("檔案的內容已經改變");
		label1.setFont(new Font("新宋體",Font.PLAIN,14));
		JLabel label2=new JLabel("想儲存檔案嗎?:)");
		label2.setFont(new Font("新宋體",Font.PLAIN,14));
		label1.setBounds(113,23,180, 23);
		label2.setBounds(113,46,180,23);
		frame.add(label1);
		frame.add(label2);
		//建立"是"按鈕
		JButton button_Yes=new JButton("是(Y)");
		button_Yes.setMnemonic(KeyEvent.VK_Y);//按ALT+Y選擇
		//給"是"按鈕加上事件監聽
		button_Yes.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e1){
				SaveF.path="";//儲存類的路徑清空
				SaveF.FirstSave=false;//儲存類恢復未儲存狀態
				//與另存為相同
				choose=false;//條件未滿足,不儲存
				//彈框設定路徑
				FileDialog filedialog=new FileDialog(frame,"另存為",FileDialog.SAVE); 
				filedialog.setVisible(true);
				path1=filedialog.getDirectory()+filedialog.getFile()+".txt";
				//如果為選擇路徑(檔名為null或nullnull),則直接返回
		    	if(path1.equals("nullnull.txt")||path1.equals(filedialog.getDirectory()+"null.txt"))
		    	{
		     		return;
			    }//if
		    	
		    	final File file=new File(path1);
			    choose=true;//滿足條件,設為能儲存狀態
			    
			    if( file.exists()){//如果檔案重名
			    	choose=false;            //有條件不滿足,重設為不能儲存狀態
			    	final JFrame f=new JFrame("另存為");
		        	f.setBounds(435,276,path1.length()*7+200,125);
		        	f.setVisible(true);
		        	f.setLayout(null);
		        	JLabel label=new JLabel(path1+"已存在。"+"要替換它嗎?");
		        	label.setBounds(20,10,path1.length()*7+130,30);
		        	f.add(label);
		        	
		        	JButton button_Yes=new JButton("是(Y)");
		        	button_Yes.setMnemonic(KeyEvent.VK_Y);//按ALT+Y選擇
		        	button_Yes.setBounds(43,58,100,30);
		        	button_Yes.addActionListener(new ActionListener(){
				    	public void actionPerformed(ActionEvent e){
					    	try {
					    		//選擇是以後直接儲存
					    		//若有檔案重名時候的檔案輸出流,輸出後直接退出新建視窗
						    	FileWriter out;
						    	out = new FileWriter(file);
						        BufferedWriter out_ = new BufferedWriter(out);
						        String temp[]=str.split("\n");
			                    if (file.canRead()||file.getName()!=null) {
			                    	int i=-1;
			                     	for(;++i<temp.length-1;){
			                     		out_.write(temp[i]);
			                     		out_.newLine();
			                     	}out_.write(temp[i]);
			                    	out_.close();
			                    }//if
			                    editText.setText(null);//把文字框清空                             
			                    }//try
			                catch (IOException e3) {
					        	}//catch
					       	f.dispose();
						
		    	     	}//actionperformed
		        	});//ActionListener
		        	f.add(button_Yes);
			
			        JButton button_No=new JButton("否(N)");
			        button_No.setMnemonic(KeyEvent.VK_N);//按ALT+N選擇
			        button_No.setBounds(143+path1.length()*4,58,100,30);
			        button_No.addActionListener(new ActionListener(){
			    	public void actionPerformed(ActionEvent e)
			    	{
						f.dispose();
						editText.setText(str);
			    	}
			    });
			    f.add(button_No);
			}//if
			//檔案不重名時候的檔案輸出流
			if(choose)//如果前面的條件都滿足則執行儲存命令
			{
				//檔案輸出流
    			try {
					FileWriter out;
					out = new FileWriter(file);
				    BufferedWriter out_ = new BufferedWriter(out);
				    String temp[]=str.split("\n");
	                if (file.canRead()||file.getName()!=null) {
                    	int i=-1;
                     	for(;++i<temp.length-1;){
                     		out_.write(temp[i]);
                     		out_.newLine();
                     	}out_.write(temp[i]);
                    	out_.close();
	                 }//if
	                editText.setText(null);
	            }//try
	            catch (IOException e3) {
				}//catch
			}//if
			frame.dispose();
			}//actionPerformed
		});
		JButton button_No=new JButton("否(N)");
		button_No.setMnemonic(KeyEvent.VK_N);//按ALT+N選擇
		button_No.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e){
				//若選擇否則儲存條件不滿足
				choose=false;
	    		JLinePrint.editText.setText(null);
	    		SaveF.path="";//儲存恢復
	    		frame.dispose();
			}
		});
		button_Yes.setBounds(81,93,100,30);
		button_No.setBounds(211,93,100,30);
		frame.add(button_Yes);
		frame.add(button_No);
		frame.setResizable(false);
	}
	public void actionPerformed(ActionEvent e) {
		//若檔案內容有改變,詢問使用者是否存檔
		if(Textfieldincident.change){
			str=editText.getText();
			frame.setVisible(true);
		}//if
	}//actionPerformed
}//新建

// 檔案->開啟O CTRL+O
class OpenF implements ActionListener {
	private FileDialog filedialog;
	private JLinePrint lineprint;
	OpenF(JFrame frame,JLinePrint lineprint) {
		this.lineprint=lineprint;
		filedialog = new FileDialog(frame, "開啟", FileDialog.LOAD);
	}//開啟
    public void actionPerformed(ActionEvent e) {
		Open();
	}//actionPerformed
	public void Open(){
		String regex="[.txt]";//正則表示式
		filedialog.setVisible(true);
		if(filedialog.getDirectory()==null)return;//按取消的時候
		String Filepath=filedialog.getDirectory();  //獲取檔案路徑,最後面帶"\"
		String FileName=filedialog.getFile();      //獲取檔名字(帶.txt)

		String path=Filepath + FileName;           //檔案路徑+檔名字
		FileName=FileName.replaceAll(regex, "");   //獲取檔名字(不帶.txt)
		File file = new File(path);
		try {
			FileReader in = new FileReader(file);
			BufferedReader in_ = new BufferedReader(in);
			String s = in_.readLine();
			String temp = s;
			s=in_.readLine();
			if (file.canRead()) {
				while (s != null) {
					temp +=("\r\n"+s);                //存在一個String裡面,到時候一次性賦給JTextArea
					s = in_.readLine();                  //一行一行讀取
				}//while
				JLinePrint.editText.setText(temp);
				in_.close();
				//讀入即時存檔檔案
				for(int i=0;++i<11;){
					File file1=new File(Filepath+FileName+String.valueOf(i)+".txt");//檔案路徑+檔名(不帶.txt)+存檔編號+.txt
					if(file1.exists()){
						in = new FileReader(file1);
						in_ = new BufferedReader(in);
						s = in_.readLine();//第一行讀取 時間
						Notepad.Save_subMenu[i-1].setText(s);//給即時存檔子選單改變時間;儲存檔名在後面加1-10,陣列下標由0-9
						Notepad.Load_subMenu[i-1].setText(s);//給即時讀檔子選單改變時間
						s=in_.readLine();//第二行開始讀取正文
						temp = "";
						if (file1.canRead()) {
							while (s != null) {
								temp += (s + "\r\n");
								s = in_.readLine();
							}//while
							Notepad.Save[i-1].s=temp;
							Notepad.Load[i-1].s=Notepad.Save[i-1];
							in_.close();
					    }//if
			     	}//if
					else{//如果沒有該編號的存檔
						Notepad.Save_subMenu[i-1].setText("--------/--------     ");//給即時存檔子選單改變時間;
						Notepad.Load_subMenu[i-1].setText("--------/--------     ");//給即時讀檔子選單改變時間;
						Notepad.Save[i-1].s="";
						Notepad.Load[i-1].s=Notepad.Save[i-1];
					}//else
				}//for
				lineprint.repaint_1();
				final JFrame frame = new JFrame("讀入成功!");
				frame.setResizable(false);
				frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
				frame.setLayout(null);
				frame.setBounds(300, 400, 250, 125);
				frame.setVisible(true);
				JButton button = new JButton("確定");
				button.setBounds(75, 50, 100, 30);
				frame.add(button);
				button.addActionListener(new ActionListener() {
					public void actionPerformed(ActionEvent e) {
						frame.dispose();
					}//actionPerformed
				});//addActionListener
				
				// (String) File.getParent()返回此抽象路徑名父目錄的路徑名字串;如果此路徑名沒有指定父目錄,則返回 null。
		        //(File) File.getParentFile()返回此抽象路徑名父目錄的抽象路徑名;如果此路徑名沒有指定父目錄,則返回 null。
				SaveF.fileName=FileName+".txt";//獲取文字名字
				SaveF.filepath=path.replace("\\"+FileName+".txt", "");//獲取路徑名字,這個路徑沒有XX.txt
				SaveF.path=path;//開啟的時候儲存路徑已設好   這個路徑有XX.txt
				SaveF.FirstSave=true;//開啟的時候算作有第一次儲存,CTRL+S無需彈框儲存
				NewC.path1="";//新建恢復
			}//if
		}//try 
		catch (IOException e1) {
		}//catch
	}//Open
}//開啟


//檔案->儲存||另存為
class SaveF implements ActionListener{//囊括了儲存和另存為
	private JTextArea editText;
	private FileDialog filedialog;
	public static String path;//path用於"儲存"選單項;在即時存檔中檢測有無儲存;在新建中在選擇過後path恢復為"";在開啟的時候直接獲取path,同時控制在儲存一次後不再彈出儲存對話方塊
	private String path1;//;path1用於"另存為"選單項
	public static boolean FirstSave;//用於在"儲存"選單項中判斷是否為第一次儲存;在新建中儲存後FirstSave賦值為false;在開啟類中開啟檔案後FirstSave賦值為true
	private boolean choose;//檔案重名時候的選擇為true or false
	public static String filepath;//filepath檔案路徑名,用於即時存檔; 在開啟中獲取檔案路徑
	public static String fileName;//fileName檔名,用於即時存檔;在開啟中獲取檔名
	SaveF(JFrame frame){
		this.editText=JLinePrint.editText;
		filedialog=new FileDialog(frame,"儲存",FileDialog.SAVE);
		path="";
		FirstSave=false;
	}//儲存
	public void actionPerformed(ActionEvent e){
		choose=false;
		if(((JMenuItem)e.getSource()).getActionCommand().equals("儲存(S)")){
			Save();
		}//if("儲存(S)")
		else if(((JMenuItem)e.getSource()).getActionCommand().equals("另存為(A)...")){
			Resave();
	    }//另存為(A)...
    }//actionPerformed
	public void Save(){
		if(path.equals("")){//如果檔案路徑為空則彈框獲得檔案路徑
			filedialog.setVisible(true);	
			filepath=filedialog.getDirectory();
			fileName=filedialog.getFile();
			path=filepath+fileName+".txt";
		}//if
		if(path.equals("nullnull.txt")||path.equals(filedialog.getDirectory()+"null.txt"))
		{
			path="";
			return;
		}//if
		choose=true;
		File file=new File(path);
		if(!FirstSave && file.exists()){//如果不是第一次儲存同時檔案重名
			final JFrame f=new JFrame("另存為");
	    	f.setBounds(435,276,path.length()*7+200,125);
	    	f.setVisible(true);
	    	f.setLayout(null);
	    	JLabel label=new JLabel(path+"已存在。"+"要替換它嗎?");
	    	label.setBounds(20,10,path.length()*7+130,30);
	    	f.add(label);
	    	JButton button_Yes=new JButton("是(Y)");
	    	button_Yes.setMnemonic(KeyEvent.VK_Y);//按ALT+Y選擇
	    	button_Yes.setBounds(43,58,100,30);
	    	button_Yes.addActionListener(new ActionListener(){
				public void actionPerformed(ActionEvent e){
					choose=true;
					FirstSave=true;
					f.dispose();
	    		}
	    	});//ActionListener
	    	f.add(button_Yes);
		
		    JButton button_No=new JButton("否(N)");
		    button_No.setMnemonic(KeyEvent.VK_N);//按ALT+N選擇
		    button_No.setBounds(143+path.length()*4,58,100,30);
		    button_No.addActionListener(new ActionListener(){
		    	//新增事件,在確認是否覆蓋的時候選擇否,不儲存,重置第一次儲存,路徑重置
		    	public void actionPerformed(ActionEvent e)
		    	{
		    		choose=false;
		    		FirstSave=false;
		    		path="";
		    		f.dispose();
		    		
		    	}
		    });
		    f.add(button_No);
		}//if
		if(choose)
		{
			//檔案輸出流
			try {
				FirstSave=true;
				FileWriter out;
				out = new FileWriter(file);
			    BufferedWriter out_ = new BufferedWriter(out);
    	        String s=editText.getText();
    	        String temp[]=s.split("\n");
                if (file.canRead()||file.getName()!=null) {
                	int i=-1;
                 	for(;++i<temp.length-1;){
                 		out_.write(temp[i]);
                 		out_.newLine();
                 	}out_.write(temp[i]);
                	out_.close();
                 }//if
            }//try
            catch (IOException e1) {
			}//catch
		}//if
	}//Save
	
	public void Resave(){
		//另存為沒有儲存那麼麻煩,儲存儲存一次後不再彈開啟框,直接以原路徑儲存;另存為需要不斷彈出開啟框來進行儲存。
		filedialog.setVisible(true);
		path1=filedialog.getDirectory()+filedialog.getFile()+".txt";
	if(path1.equals("nullnull.txt")||path1.equals(filedialog.getDirectory()+"null.txt"))
	{
		return;
	}//if
	File file=new File(path1);
	choose=true;
	if(!FirstSave && file.exists()){//如果不是第一次儲存同時檔案重名
		final JFrame f=new JFrame("另存為");
    	f.setBounds(435,276,path1.length()*7+200,125);
    	f.setVisible(true);
    	f.setLayout(null);
    	JLabel label=new JLabel(path1+"已存在。"+"要替換它嗎?");
    	label.setBounds(20,10,path1.length()*7+130,30);
    	f.add(label);
    	JButton button_Yes=new JButton("是(Y)");
    	button_Yes.setMnemonic(KeyEvent.VK_Y);//按ALT+Y選擇
    	button_Yes.setBounds(43,58,100,30);
    	button_Yes.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e){
				choose=true;
				f.dispose();
				
    		}
    	});//ActionListener
    	f.add(button_Yes);
	
	    JButton button_No=new JButton("否(N)");
	    button_No.setMnemonic(KeyEvent.VK_N);//按ALT+N選擇
	    button_No.setBounds(143+path1.length()*4,58,100,30);
	    button_No.addActionListener(new ActionListener(){
	    	public void actionPerformed(ActionEvent e)
	    	{
	    		choose=false;
	    		f.dispose();
	    	}
	    });
	    f.add(button_No);
	}//if
	if(choose)
	{
		//檔案輸出流
		try {
			FirstSave=true;
			FileWriter out;
			out = new FileWriter(file);
		    BufferedWriter out_ = new BufferedWriter(out);
	        String s=editText.getText();
	        String temp[]=s.split("\n");
            if (file.canRead()||file.getName()!=null) {
            	int i=-1;
             	for(;++i<temp.length-1;){
             		out_.write(temp[i]);
             		out_.newLine();
             	}out_.write(temp[i]);
            	out_.close();
             }//if
        }//try
        catch (IOException e1) {
		}//catch
	}//if
	}//Resave
}//儲存

//檔案->頁面設定
class PageSetting implements ActionListener{//頁面設定1
	private JFrame frame;
	PageSetting(){
		frame=new JFrame("頁面設定");
		frame.setBounds(419,244,472,323);
        frame.setLayout(new GridLayout(5,1));
		JPanel Pane=new JPanel();
		//設定每一頁列印的行數
		final JLabel LineEveryPage_set=new JLabel("每一頁輸出 "+Printout.LineEverypage+" 行");
		LineEveryPage_set.setForeground(Color.blue);
		LineEveryPage_set.setFont(new Font("華文行楷",Font.BOLD,24));
		final JTextField LineEverypage_set1=new JTextField(5);
		final JLabel LineEveryPage_status=new JLabel("預設");
		LineEverypage_set1.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e){
				int s=Integer.parseInt(e.getActionCommand());
				if(s<=0||s>100){
					LineEverypage_set1.setText(null);
					LineEveryPage_status.setText("限制在1-100之間");
					return;
				}
				Printout.LineEverypage=s;
				LineEveryPage_set.setText("每一頁輸出 "+Printout.LineEverypage+" 行");
				if(Printout.LineEverypage==80){
					LineEveryPage_status.setText("預設");
				}//if
				else{
					LineEveryPage_status.setText("已修改");
				}//else
				LineEverypage_set1.setText(null);
			}//actionPerformed
		});//addActionListener
		Pane.add(LineEveryPage_set);
		Pane.add(LineEverypage_set1);
		Pane.add(LineEveryPage_status);
		Pane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder("修改列印時每一頁列印的行數"),BorderFactory.createEmptyBorder()));
		frame.add(Pane);
		
		//設定x的座標偏移量
		JPanel Pane1=new JPanel();
		final JLabel set_x=new JLabel("x座標的偏移量  x="+Print.start_x);
		set_x.setFont(new Font("華文楷體",Font.BOLD,24));
		set_x.setForeground(Color.green);
		final JTextField set_x1=new JTextField(5);
		final JLabel set_x_status=new JLabel("預設");
		set_x1.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e){
				double s=Double.parseDouble(e.getActionCommand());
				if(s<0||s>100){
					set_x1.setText(null);
					set_x_status.setText("限制在0-100之間");
					return;
				}
				Print.start_x=s;
				set_x.setText("x座標的偏移量  x="+Print.start_x);
				if(Print.start_x==50.0){
					set_x_status.setText("預設");
				}//if
				else{
					set_x_status.setText("已修改");
				}//else
				set_x1.setText(null);
			}
		});
		Pane1.add(set_x);
		Pane1.add(set_x1);
		Pane1.add(set_x_status);
		Pane1.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder("修改列印時起點座標在x軸的偏移量"),BorderFactory.createEmptyBorder()));
		frame.add(Pane1);
		
		//設定y的座標偏移量
		JPanel Pane2=new JPanel();
		final JLabel set_y=new JLabel("y座標的偏移量 y="+Print.start_y);
		set_y.setFont(new Font("方正舒體",Font.BOLD,24));
		set_y.setForeground(Color.red);
		final JTextField set_y1=new JTextField(5);
		final JLabel set_y_status=new JLabel("預設");
		set_y1.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e){
				double s=Double.parseDouble(e.getActionCommand());
				if(s<0||s>100){
					set_y1.setText(null);
					set_y_status.setText("限制在0-100之間");
					return;
				}
				Print.start_y=s;
				set_y.setText("y座標的偏移量 y="+Print.start_y);
				if(Print.start_y==20.0){
					set_y_status.setText("預設");
				}//if
				else{
					set_y_status.setText("已修改");
				}//else
				set_y1.setText(null);
			}
		});
		
		Pane2.add(set_y);
		Pane2.add(set_y1);
		Pane2.add(set_y_status);
		Pane2.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder("修改列印時起點座標在y軸的偏移量"),BorderFactory.createEmptyBorder()));
		frame.add(Pane2);
		
		//設定行與行之間的間距
		JPanel pane4=new JPanel();
		final JLabel setinterval=new JLabel("行與行之間的間距為"+Print.interval);
		setinterval.setFont(new Font("黑體",Font.BOLD,24));
		setinterval.setForeground(Color.PINK);
		final JTextField textfield_setinterval=new JTextField(5);
		final JLabel setinterval_status=new JLabel("預設");
		textfield_setinterval.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e){
				int s=Integer.parseInt(e.getActionCommand());
				if(s<0||s>100){
					textfield_setinterval.setText(null);
					setinterval_status.setText("限制在0-100之間");
					return;
				}
				Print.interval=s;
				setinterval.setText("行與行之間的間距為"+Print.interval);
				if(Print.interval==10){
					setinterval_status.setText("預設");
				}//if
				else{
					setinterval_status.setText("已修改");
				}//else
				textfield_setinterval.setText(null);
			}
		});
		pane4.add(setinterval);
		pane4.add(textfield_setinterval);
		pane4.add(setinterval_status);
		pane4.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder("修改列印時行與行的間距"),BorderFactory.createEmptyBorder()));
		frame.add(pane4);
		
		//按鈕,恢復預設
		JPanel Pane3=new JPanel();
		JButton button=new JButton("恢復預設");
		button.addActionListener(new ActionListener(){
			public  void actionPerformed(ActionEvent e){
				Print.start_x=50.0d;
				Print.start_y=20.0d;
				Printout.LineEverypage=80;
				Print.interval=10;
				LineEveryPage_set.setText("每一頁輸出 "+80+" 行");
				set_x.setText("x座標的偏移量  x="+50.0);
				set_y.setText("y座標的偏移量 y="+20.0);
				setinterval.setText("行與行之間的間距為"+Print.interval);
				LineEveryPage_status.setText("預設");
				set_x_status.setText("預設");
				set_y_status.setText("預設");
				setinterval_status.setText("預設");
			}
		});
		Pane3.add(button);
		frame.add(Pane3);
	}
	public void actionPerformed(ActionEvent e){
		frame.setVisible(true);//剛開始編記事本的時候直接在這裡定義視窗了,導致每一次開啟都要定義一次視窗。
		                       //放建構函式定義視窗的好處是不用重複定義,但是弄多了後開啟記事本要等久一些。
	}//actionPerformed
}//頁面設定

//檔案->列印
class Printout implements ActionListener{//列印1
	public static int LineEverypage=80;    //設定每一頁輸出多少行,預設80
	public void actionPerformed(ActionEvent e){
		 //獲取列印服務物件
		 String printstr=JLinePrint.editText.getText();
	     PrinterJob job = PrinterJob.getPrinterJob();   
	     int max_Index=JLinePrint.lineOfC/LineEverypage;
	     int LeaveLine=JLinePrint.lineOfC-LineEverypage*(max_Index);
	     job.setPrintable(new Print(printstr,JLinePrint.lineOfC/LineEverypage,LeaveLine));//設定列印類
	     try {
	         boolean a=job.printDialog();
	         //job.getPrintService()獲取印表機名字
	         if(a)
	         {
	            	 int Copies=job.getCopies();
	                 for(int i=-1;++i<Copies;)//列印多少份
	                 {
	                	 Print.isFirst=true;
  	                     job.print();
	                 }
	         }//if
	     }//try
	     catch (PrinterException e1) {
	         e1.printStackTrace();
	     }//catch
	}//actionPerformed
}//列印

//使用虛擬印表機SmartPrinterV4
//轉載自http://www.blogjava.net/kelly/archive/2007/01/31/96973.html
//需要較大的改動
//在pdf輸出排版上需要修改。以及換頁命令。
//將文字以'\n'來分成一個String陣列,然後一行一行地Graphics.drawString兩次,第一次是噴電子,第二次噴墨
//能夠設定一頁列印多少行,最後LeaveLine小於所設行數,獨立出來列印
class Print implements Printable{//Print1
	   /**
	   * @param Graphic指明列印的圖形環境
	   * @param PageFormat指明列印頁格式(頁面大小以點為計量單位,1點為1英才的1/72,1英寸為25.4毫米。A4紙大致為595×842點)
	   * @param pageIndex指明頁號
	   **/
	public static double start_x=50.0d;//設定列印起點的x座標偏移量
	public static double start_y=20.0d;//設定列印起點的y座標偏移量
	public static int interval=10;//設定列印中行與行的間距,預設為10
	private int max_pageIndex; //每頁輸出x行,總共有max_pageIndex頁。
	private int LeaveLine;//剩餘的一頁裡有多少行
	private String str;//傳入列印文字
	private String temp[];
	public static boolean  isFirst;  //用於控制最後一頁g2.drawString()執行兩次
	public static int page;
	Print(String str,int max_pageIndex,int LeaveLine){
		this.max_pageIndex=max_pageIndex;
		this.LeaveLine=LeaveLine;
		temp=str.split("\n");
		isFirst=true;
	}
	public int print(Graphics gra, PageFormat pf, int pageIndex) throws PrinterException {
		//print string
		//轉換成Graphics2D
		Graphics2D g2 = (Graphics2D) gra;
		//設定列印顏色為黑色
		g2.setColor(Color.black);

		//列印起點座標
		double x = pf.getImageableX();
		double y1 = pf.getImageableY();
		//設定列印字型(字型名稱、樣式和點大小)(字型名稱可以是物理或者邏輯名稱)
		//Java平臺所定義的五種字體系列:Serif、SansSerif、Monospaced、Dialog 和 DialogInput
		Font font = new Font("新宋體", Font.PLAIN, 9);
		g2.setFont(font);//設定字型
		g2.setColor(FontColour.fontColor);//設定顏色
       
		float heigth = font.getSize2D();//字型高度   
		double y=y1+1*heigth;
		x=x+start_x;
		y=y+start_y;
		if(pageIndex<max_pageIndex){
			int i=Printout.LineEverypage*pageIndex-1;
			int len=i+Printout.LineEverypage;
			for(;++i<=len;y+=interval)
			{    
				try{
					if(temp[i].isEmpty())continue;
					}catch(Throwable e){continue;}
				g2.drawString(temp[i], (float)x, (float)y);  //這個去掉沒有任何輸出,用於輸出String
			}//for
			return PAGE_EXISTS;
		}//if
	    //注意這裡列印要g2.drawString()兩次才能輸出
		else if(LeaveLine!=0){ 
			if(pageIndex==max_pageIndex){
				int i=pageIndex*Printout.LineEverypage-1;
				int len=i+LeaveLine;
				for(;++i<=len;y+=interval){
					if(temp[i].isEmpty())continue;
					g2.drawString(temp[i], (float)x, (float)y);  //這個去掉沒有任何輸出,用於輸出String
				}
			}//if
			if(isFirst){
				isFirst=false;
				return PAGE_EXISTS;
			}
			else {
				LeaveLine=0;
			}//else
		}//if
		return NO_SUCH_PAGE;
	}//print
}//Print

//ObjectInputStream和ObjectInputSteam的作用物件
//如果沒有implements Serializable介面的話無法儲存和讀取Object
class Jtext implements Serializable{//序列化
	private String SecreteFile;    //密文
	public Jtext(String SecreteFile){
		this.SecreteFile=SecreteFile;
	}
	public String getSecreteFile(){
		return SecreteFile;
	}
}

//加密解碼的方式參照了http://blog.csdn.net/zhuxueke_830111/article/details/2009916的記事本加密解密方法
//該例子解密加密的字元預設為'a'和's'
//解密加密方式為        char^char    會變成一個奇怪的字元      即我們看到的密文          再一次       char^char    會恢復成原文
//這個類將每一個密碼字元都用於解密加密,且不儲存密碼,開啟時如果密碼輸入錯誤會導致解密失敗,密文會變成另一段亂碼,但是不影響已儲存檔案的內容
//本例子將JTextField用作密碼框,限制輸入字元數為10,並使顯示字元為 '*' ;
//注意:密文無法使用BufferedWriter類進行儲存,需要用ObjectOutputStream類進行儲存,否則解密的時候會多出字元
//檔案->加密解密
class Encryptdecode implements ActionListener{
	private JFrame frame;
	private String keyWord;
	private int len;
	private String s;
	public Encryptdecode(){
		Menu();
		len=0;
		s="";
		keyWord="";
	}//加密解密
	public void actionPerformed(ActionEvent e){
		frame.setVisible(true);
	}//actionPerformed
	public void Menu(){
		frame=new JFrame("輸入密碼框");
		frame.setBounds(447,190,250,158);
		frame.setLayout(null);
		frame.setResizable(false);
		JLabel label_InputYourKeyWord=new JLabel("請輸入密碼(限制10個字元)再點選按鈕:");
		label_InputYourKeyWord.setBounds(10,10,250,20);
		final JTextField passWordField=new JTextField(10);
		//把文字框改裝成密碼框,同時實現限制了10個字元的功能
		passWordField.addKeyListener(new KeyListener(){
			public void keyPressed(KeyEvent e) {
				if(len>=10)passWordField.setText(s);
				if(e.getKeyChar()==(char)KeyEvent.VK_BACK_SPACE){
					if(len>0){
						len--;
			    		s=s.substring(0,len);
				    	keyWord=keyWord.substring(0,len);
				    	
					}//if
				}//if
				else if(len<10){
					s+="*";//把密碼框裡的字元全部變為 "*"
					len++;
					keyWord+=String.valueOf(e.getKeyChar());   //密碼用keyWord儲存
				}//else if
			}//keyPressed

			public void keyReleased(KeyEvent e1) {			
				passWordField.setText(s);     //把文字框的內容變為'*'號。
			}//keyReleased
			public void keyTyped(KeyEvent arg0) {}
			
		});
		passWordField.setBounds(20,50,100,30);
		JButton button_confirm=new JButton("儲存");
		button_confirm.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e){
				passWordField.setText(null);//密碼框清空
				SecretFileSave(Encryption_Decryption(JLinePrint.editText.getText(),keyWord));
				len=0;//密碼字數重置為0
				keyWord="";//密碼清空
				s="";//密碼字元清空
			}
		});
		button_confirm.setBounds(135,50,100,30);
		JButton button_Open=new JButton("開啟");
		button_Open.setBounds(135,90,100,30);
		button_Open.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e){
				passWordField.setText(null);
				SecretFileOpen();
				len=0;//密碼字數重置為0
				keyWord="";//密碼清空
				s="";//密碼字元清空
				//把視野轉到文字最後面
				JLinePrint.editText.setSelectionStart(JLinePrint.editText.getText().length()-2);
				JLinePrint.editText.setSelectionEnd(JLinePrint.editText.getText().length()-2);
			}
		});
		frame.addWindowListener(new WindowListener(){

			public void windowActivated(WindowEvent arg0) {
				//視窗開啟的時候
				//System.out.println(1);
			}

			public void windowClosed(WindowEvent arg0) {
				//System.out.println(2);
			}

			public void windowClosing(WindowEvent arg0) {
				//視窗關閉的時候
				//System.out.println(3);		
				passWordField.setText(null);
				len=0;
				keyWord="";
				s="";
			}

			public void windowDeactivated(WindowEvent arg0) {
				//視窗關閉的時候
				//System.out.println(4);				
			}

			public void windowDeiconified(WindowEvent arg0) {
				//System.out.println(5);				
			}

			public void windowIconified(WindowEvent arg0) {
				//System.out.println(6);				
			}

			public void windowOpened(WindowEvent arg0) {
				//視窗開啟的時候
				//System.out.println(7);				
			}
			
		});
		frame.add(button_Open);
		frame.add(button_confirm);
		frame.add(label_InputYourKeyWord);
		frame.add(passWordField);
	}//Menu
	private String Encryption_Decryption(String s,String keyWord){
		StringBuffer BF=new StringBuffer(s);
		char a=0;
		if(keyWord.length()!=0)
		{
	    	for(int i=-1;++i<s.length();){
	    		for(int j=-1;++j<keyWord.length();){
		    		a=(char) (s.charAt(i)^keyWord.charAt(j));
		    	}
		    	BF.replace(i, i+1, String.valueOf(a));
	    	}//for
	    	s=BF.toString();
		}//if
		return s;
	}//Encryption
	public void SecretFileSave(String s){
		try {
		    	FileDialog filedialog=new FileDialog(frame,"加密儲存",FileDialog.SAVE);
	    	    filedialog.setVisible(true);
	    	    Jtext Text=new Jtext(s);
	    	    if(filedialog.getDirectory()!=null && filedialog.getFile()!=null){
	    	        ObjectOutputStream out=new ObjectOutputStream(new FileOutputStream(filedialog.getDirectory()+filedialog.getFile()));
	    	        out.writeObject(Text);
	    	        out.close();
	             }
	      }catch(Exception e){}
	}//SecretFileSave
	public void SecretFileOpen(){
		try {
	    	FileDialog filedialog=new FileDialog(frame,"加密開啟",FileDialog.LOAD);
    	    filedialog.setVisible(true);
    	    if(filedialog.getDirectory()!=null && filedialog.getFile()!=null){
    	    	ObjectInputStream in=new ObjectInputStream(new FileInputStream(filedialog.getDirectory()+filedialog.getFile()));
    	    	Jtext Text=(Jtext)in.readObject();
    	        in.close();		
    	        String temp=Encryption_Decryption(Text.getSecreteFile(),keyWord);
    	                      Textfieldincident.s.push(JLinePrint.editText.getText());
    	        JLinePrint.editText.setText(temp);
            	       
            }//if
            }catch(Exception e1){System.err.println("Error!");}
         }//SecretFileOpen
}//加密解密



//檔案->退出
class Exit implements ActionListener,WindowListener{
	private JFrame frame;
	private boolean choose;
	private JTextArea editText;
	private String path1;
	Exit(JFrame frame){
		this.frame=frame;
		this.editText=JLinePrint.editText;;
		path1="";
	}
	public void actionPerformed(ActionEvent e)
	{
		//若檔案內容有改變,詢問使用者是否存檔
			if(Textfieldincident.change){
				Save();
			}
		frame.dispose();
	}//actionPerformed
	public void Save(){
		final String str=editText.getText();//用於輸出流時候使用
		final JFrame frame=new JFrame("記事本");
		frame.setBounds(424, 269, 355, 181);
		frame.setLayout(null);
		frame.setVisible(true);
		JLabel label1=new JLabel("檔案的內容已經改變");
		label1.setFont(new Font("新宋體",Font.PLAIN,14));
		JLabel label2=new JLabel("想儲存檔案嗎?:)");
		label2.setFont(new Font("新宋體",Font.PLAIN,14));
		label1.setBounds(113,23,180, 23);
		label2.setBounds(113,46,180,23);
		frame.add(label1);
		frame.add(label2);
		JButton button_Yes=new JButton("是(Y)");
		button_Yes.setMnemonic(KeyEvent.VK_Y);//ALT+Y
		button_Yes.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e1){
				//與另存為相同
				choose=false;
				FileDialog filedialog=new FileDialog(frame,"另存為",FileDialog.SAVE); 
				filedialog.setVisible(true);
				path1=filedialog.getDirectory()+filedialog.getFile()+".txt";
				
		    	if(path1.equals("nullnull.txt")||path1.equals(filedialog.getDirectory()+"null.txt"))
		    	{
		     		return;
			    }//if
		    	
		    	final File file=new File(path1);
			    choose=true;
			    
			    if( file.exists()){//如果不是第一次儲存同時檔案重名
			    	choose=false;
			    	final JFrame f=new JFrame("另存為");
		        	f.setBounds(435,276,path1.length()*7+200,125);
		        	f.setVisible(true);
		        	f.setLayout(null);
		        	JLabel label=new JLabel(path1+"已存在。"+"要替換它嗎?");
		        	label.setBounds(20,10,path1.length()*7+130,30);
		        	f.add(label);
		        	
		        	JButton button_Yes=new JButton("是(Y)");
		        	button_Yes.setMnemonic(KeyEvent.VK_Y);
		        	button_Yes.setBounds(43,58,100,30);
		        	button_Yes.addActionListener(new ActionListener(){
				    	public void actionPerformed(ActionEvent e){
					    	try {
					    		//若有檔案重名時候的檔案輸出流,輸出後直接退出視窗
						    	FileWriter out;
						    	out = new FileWriter(file);
						        BufferedWriter out_ = new BufferedWriter(out);
						        String temp[]=str.split("\n");
			                    if (file.canRead()||file.getName()!=null) {
			                    	int i=-1;
			                     	for(;++i<temp.length-1;){
			                     		out_.write(temp[i]);
			                     		out_.newLine();
			                     	}out_.write(temp[i]);
			                    	out_.close();
			                    }//if
			                    editText.setText(null);//把文字框清空
			                    }//try
			                catch (IOException e3) {
					        	}//catch
					       	f.dispose();
						
		    	     	}//actionPerformed
		        	});//ActionListener
		        	f.add(button_Yes);
			
			        JButton button_No=new JButton("否(N)");
			        button_No.setMnemonic(KeyEvent.VK_N);//按ALT+N選擇
			        button_No.setBounds(143+path1.length()*4,58,100,30);
			        button_No.addActionListener(new ActionListener(){
			    	public void actionPerformed(ActionEvent e)
			    	{
			    		choose=false;
			    		f.dispose();
			    	}
			    });
			    f.add(button_No);
			}//if
			//檔案不重名時候的檔案輸出流
			if(choose)
			{
				//檔案輸出流
    			try {
					FileWriter out;
					out = new FileWriter(file);
				    BufferedWriter out_ = new BufferedWriter(out);
				    String temp[]=str.split("\n");
	                if (file.canRead()||file.getName()!=null) {
                    	int i=-1;
                     	for(;++i<temp.length-1;){
                     		out_.write(temp[i]);
                     		out_.newLine();
                     	}out_.write(temp[i]);
	                	out_.close();
	                 }//if
	            }//try
	            catch (IOException e3) {
				}//catch
			}//if
			frame.dispose();
			}//actionPerformed
		});
		JButton button_No=new JButton("否(N)");
		button_No.setMnemonic(KeyEvent.VK_N);//按ALT+N選擇
		button_No.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e){
				frame.dispose();
				editText.setText(str);
			}//actionPerformed
		});
		button_Yes.setBounds(81,93,100,30);
		button_No.setBounds(211,93,100,30);
		frame.add(button_Yes);
		frame.add(button_No);
		frame.setResizable(false);
	}//Save
	@Override
	public void windowActivated(WindowEvent arg0) {
		//視窗初始化
		//System.out.println(1);
		
	}
	@Override
	public void windowClosed(WindowEvent arg0) {
		//System.out.println(2);
		
	}
	@Override
	public void windowClosing(WindowEvent arg0) {
		//視窗關閉
		//System.out.println(3);
	}
	@Override
	public void windowDeactivated(WindowEvent arg0) {
		//視窗最小化
		//System.out.println(4);
	}
	@Override
	public void windowDeiconified(WindowEvent arg0) {
		//視窗恢復
		//System.out.println(5);
		
	}
	@Override
	public void windowIconified(WindowEvent arg0) {
		//視窗隱藏
		//System.out.println(6);
	}
	@Override
	public void windowOpened(WindowEvent arg0) {
		//視窗開啟
		//System.out.println(7);
		
	}
}//退出

//編輯->撤銷
class Undo implements ActionListener{
	public static Stack<String>ss;
	Undo(){ss=new Stack<String>();}
	public void actionPerformed(ActionEvent arg0) {
		if(!Textfieldincident.s.empty()){
			String str=Textfieldincident.s.peek();
			String str1=JLinePrint.editText.getText();
			ss.push(str1);
			Textfieldincident.s.pop();
			JLinePrint.editText.setText(str);
		}//if
		else{
			String str=JLinePrint.editText.getText();
			if(!str.equals(""))ss.push(str);
			JLinePrint.editText.setText(null);
		}//else
	}//actionPerformed
};//撤銷

//編輯->恢復
class Recover implements ActionListener{
	public void actionPerformed(ActionEvent e){
		if(!Undo.ss.empty()){
			String str=Undo.ss.peek();
			String str1=JLinePrint.editText.getText();
			Textfieldincident.s.push(str1);
			Undo.ss.pop();
			JLinePrint.editText.setText(str);
     	}//if
	}//actionPerformed
}//恢復

//轉載自http://zhidao.baidu.com/link?url=_LX5dnt3qCyQgCyLHN4nT7GyXpKpBdRWqCOyX4kzpgikEAcWHGK3MdkTeLRSKCSzMYzmUNYRR81KqxT09bpPwK
//建立一個輸出文字行號附帶文字框編輯的元件
//加以改動,將repaint方法放在文字框的鍵盤事件以及開啟事件裡執行。
//增添了滑鼠滑輪事件和拖拽滾動條事件,行框在行數超過1000時改變大小
//增加了文字框滑鼠事件,用該事件實現了用滑鼠拖拽字串改變其位置的功能
class JLinePrint extends Panel implements MouseMotionListener,MouseListener{//JJL
	public static JTextArea editText;
	public JScrollPane RollPane;
	public static int pos;//游標在(String)JTextArea.gettext()的位置
	public static int lineOfC;//行數
	public static int col;//列數
	public static boolean refresh;//用於在超過1000行時候重新整理
	private int fontHeight;//文字字型高度
	private int fontWidth;//獲得文字字型寬度
	public int x;//用於增大行框
	public int nowSize;//目前視窗的大小
	public static int Mousepos;//獲得當前滑鼠位置前面的字元個數  ,用於字串的拖拽
	private String s;//用於拖拽字串到指定位置,用於字串的拖拽
	private boolean isChoosesubstring;//判斷是否選擇了子串,用於字串的拖拽
	private boolean isClickedsubstring;//判斷是否點選了子串,用於字串的拖拽
	private int Start;    //子串的開始位置,用於字串的拖拽
	private int End;      //子串的結束位置,用於字串的拖拽
	public static int X;        //滑鼠在文字區域內的X座標,顯示在狀態列裡
	public static int Y;        //滑鼠在文字區域內的Y座標,顯示在狀態列裡
	public JMenu menu;
	public static Point P;     //獲得滑鼠的座標
	public void repaint_1(){
		JLinePrint.this.repaint(); 
		editText.addCaretListener(new CaretListener(){
			public void caretUpdate(CaretEvent arg0) {
			try
			{
			     pos=editText.getCaretPosition();
			     //獲取行數                
			     lineOfC=editText.getLineOfOffset(pos)+1;
			     //獲取列數               
			     col=pos-editText.getLineStartOffset(lineOfC-1)+1;
			} catch(Exception   e){}
			}  
		});
	}
	public void setmenu(JMenu menu){
		this.menu=menu;
	}
	public JLinePrint(){
		super();   //呼叫父類的建構函式
		P=new Point(0,0);
		X=0;
		Y=0;
		Start=0;
		End=0;
		isChoosesubstring=false;
		isClickedsubstring=false;
		nowSize=0;
		x=0; 
		setMinimumSize(new Dimension(30, 30));
		setPreferredSize(new Dimension(30,30));//用於修改行框的寬度  
		editText=new JTextArea(){
			public void paint(Graphics g){
				super.paint(g);//呼叫paint方法
			}
		};		
		editText.addMouseListener(this);
		editText.addMouseMotionListener(this);
		RollPane=new JScrollPane(editText);
		refresh=false;
		RollPane.addMouseWheelListener(new MouseWheelListener(){
            //新增滑鼠滾輪改變行框事件
			@Override
			public void mouseWheelMoved(MouseWheelEvent arg0) {
				repaint_1();
				if(refresh){//行框超過1000行以後行框重新整理
					setVisible(false);
					menu.setVisible(false);
					try {
						Thread.sleep(50);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					setVisible(true);
					menu.setVisible(true);
					refresh=false;
				}
			}//mouseWheelMoved
		});;//addMouseWheelListener
		RollPane.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener(){//監聽滾動條事件
			@Override
			public void adjustmentValueChanged(AdjustmentEvent arg0) {
				repaint_1();
				if(JLinePrint.refresh){//行框超過1000行以後行框重新整理
					setVisible(false);
					menu.setVisible(false);
					try {
						Thread.sleep(50);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}//catch
					setVisible(true);
					menu.setVisible(true);
					refresh=false;
				}//if
			}//adjustmentValueChanged
		});//new AdjustmentListener();
	}//JLinePrint()
	
	//重寫paint方法
	public void paint(Graphics g){
		super.paint(g);
		//當行數超過1000的時候需要改變行框的寬度
		if(lineOfC/1000!=0){
			String ss=Integer.toString(lineOfC);
			x=(ss.length()-3)*10;
		}//if
		else{//設定這個的目的是為了當行數超過1000行在回到1000行一下的時候恢復行框原來的寬度
			x=0;
		}
		if(x!=nowSize){
			setPreferredSize(new Dimension(30+x,30+x));//用於修改行框的寬度 
	    	menu.setPreferredSize(new Dimension(30+x,25));
			nowSize=x;
	    	refresh=true;
		}
		else if(lineOfC/1000==0){   //回到1000行以下恢復行框大小
			refresh=false;
		}

		//JTextArea.viewToModel(Point);  給定的檢視座標系換到最近的模型的位置。    即提供當前檢視中的文字位置
		//(JViewPoint)JScollPane.getViewPort()  返回滾動視窗
		//(Point)JViewPoint.getViewPosition();  返回檢視座標,若無檢視返回(0,0);
		//start獲取的是不在文字框當前檢視的滾動條上面的字元個數(包括換行鍵,換行鍵算一個字元)
		int start=editText.viewToModel(RollPane.getViewport().getViewPosition());
		//end獲取的是該文字框下所有字元個數(包括換行鍵,換行鍵算一個字元)
		int end=editText.viewToModel(
				new Point(
			         	RollPane.getViewport().getViewPosition().x+editText.getWidth(),
		                RollPane.getViewport().getViewPosition().y+editText.getHeight()
		                )
				);
		Document doc=editText.getDocument();//獲取editText的Document類
		
		//AbstactDocument.返回檢視依賴的根元素().(java.swing.text.Element)返回子元素指數接近給定的偏移量(int)+1
		//startline獲取的是當前檢視下文字框的第一行是幾行
		int startline=doc.getDefaultRootElement().getElementIndex(start)+1;
		
		//endline獲取的是當前檢視下文字框的最後一行是幾行
		int endline=doc.getDefaultRootElement().getElementIndex(end)+1;
		
		//(Graphics.getFontMetrics(JTextField.getFont())).getHeight()
		//獲取文字框內字型的高度,用於讓行數對應文字框內的文字
		fontHeight=(g.getFontMetrics (editText.getFont()).getHeight());
	//	fontWidth= (g.getFontMetrics (editText.getFont()).getWidths());
		
		//(Graphics.得到當前字型的字型度量(文字框裡的字型)).獲得字型的大小
		//fontDesc用於校準第一行的1與邊框頂端的偏移量
		int fontDesc=(g.getFontMetrics(editText.getFont())).getDescent();
		int starting_y=-1;
		try{
			starting_y=editText.modelToView(start).y-RollPane.getViewport().getViewPosition().y+fontHeight-fontDesc;
		}
		
		catch(BadLocationException e1){}
		for(int line=startline-1,y=starting_y;++line<=endline;y+=fontHeight){
		    g.drawString(Integer.toString(line), 0, y);
		}
	}//paint
	
	public void mouseDragged(MouseEvent e) {
		if(e.getModifiers()==16){//如果拖動時候使用的是左鍵
			if(isChoosesubstring){
				Mousepos=editText.viewToModel(e.getPoint());
				editText.setSelectionStart(Mousepos);
				editText.setSelectionEnd(Mousepos);
			//	System.out.println("選中檔案+滑鼠拖拽 Start="+Start+" End="+End+" s="+s);
			}//if
		}//if
	}//mouseDragged

	public void mouseMoved(MouseEvent e) {
		    P=e.getPoint();
	    	Mousepos=editText.viewToModel(P);
	    	X=e.getX();   //獲取滑鼠的X座標
	    	Y=e.getY();   //獲取滑鼠的Y座標
	    	Notepad.status_menubar.setText("Ln:"+JLinePrint.lineOfC+"    Col:"+JLinePrint.col+"    Letters:"+JLinePrint.pos+"      Mousepos="+Mousepos+"     X="+X+"    Y="+Y);//點選滑鼠的時候返回游標位置在狀態列裡顯示
	}//mouseDragged
	
	public void mouseClicked(MouseEvent e) {
		  FindandReplace.First=true;//如果游標位置改變則恢復向上查詢的第一次執行以能從最後一個開始遍歷。
         Notepad.status_menubar.setText("Ln:"+JLinePrint.lineOfC+"    Col:"+JLinePrint.col+"    Letters:"+JLinePrint.pos+"      Mousepos="+Mousepos+"     X="+X+"    Y="+Y);//點選滑鼠的時候返回游標位置在狀態列裡顯示
	}
	
	public void mouseEntered(MouseEvent arg0) {
		//滑鼠進入
		//System.out.println(2);
		
	}
	
	public void mouseExited(MouseEvent arg0) {
		//鼠標出去
		//System.out.println(3);
		
	}
	
	public void mousePressed(MouseEvent e) {
         if(e.getModifiers()==16){//左鍵按下
        	 if(isChoosesubstring){//如果已經選中了一段文字
        		 if(Mousepos>Start && Mousepos<End){//如果滑鼠時按下選中的文字上的
        			 isClickedsubstring=true;//那麼 “點在文字上” 這個boolean變為true
        		 }//if
        		 else{
        			 isChoosesubstring=false;     //否則,"選中文字"   這個boolean變為false
        			 Start=0;                     //選中文字的始下標變為0
        			 End=0;                       //選中文字的尾下標變為0
        		 }//else
        	 }//if
         }//if
	}//mousePressed
	
	public void mouseReleased(MouseEvent e) {
		//滑鼠彈起
        if(e.getModifiers()==16){  //左鍵彈起
        	//以下兩行程式碼只要彈起左鍵隨時都會執行。
        	int Start=editText.getSelectionStart();    //獲得選中文字的始下標
        	int End=editText.getSelectionEnd();        //獲得選中文字的尾下標
        	if(Start!=End){
        		isChoosesubstring=true;
        		s=editText.getText().substring(Start,End);
        		this.Start=Start;
        		this.End=End;
        	}//if
        	else if(isClickedsubstring){
        		if(isClickedsubstring){
        			editText.replaceRange("", this.Start, this.End);
        			Mousepos=editText.viewToModel(e.getPoint());
        			editText.insert(s, Mousepos);
        			isClickedsubstring=false;
        			this.Start=0;
        			this.End=0;
        		}//if
        	}//else
        }//if
	}//mouseReleased
}//JLinePrint

//編輯->即時讀檔
class Loadstate implements ActionListener{
	public Savestate s;
	Loadstate(Savestate s){
		this.s=s;
	}//即時讀檔
	public void actionPerformed(ActionEvent e){
		String ss=new String(s.s);
		if(!ss.isEmpty())
			JLinePrint.editText.setText(ss);
	}//actionPerformed
}//即時讀檔 

//編輯->即時存檔
class Savestate implements ActionListener{
	public String s;
	public String time;
	public JMenuItem Load;
	public Date nowtime;
	private int num;
	Savestate(JMenuItem Load,int num){
		this.Load=Load;
		this.num=num;
		s=new String();
		nowtime=new Date();
	}//即時存檔
	public void actionPerformed(ActionEvent e){
		String regex="[.txt]";//正則表示式
		if(SaveF.path.equals("")){
			JOptionPane.showMessageDialog(new JFrame(), "<html><ul><font face=新宋體 font size=4><i>請儲存檔案後再使用即時存讀檔功能。</i></font></ul></html>");
		}//if
		else{
			String Filepath=SaveF.filepath;
			String FileName=SaveF.fileName;
			FileName=FileName.replaceAll(regex,"");
			File file=new File(Filepath+"\\"+FileName+String.valueOf(num)+".txt");//下次開啟的時候可以直接讀入即時存讀檔
			try {
				FileWriter out;
				out = new FileWriter(file);
			    BufferedWriter out_ = new BufferedWriter(out);
    	        String s=JLinePrint.editText.getText();
                if (file.canRead()||file.getName()!=null) {
                 	out_.write(nowtime.toString());
                 	out_.newLine();
                 	out_.write(s);
                	out_.close();
                 }//if
            }//try
            catch (IOException e1) {
			}//catch
		}//else
		nowtime=new Date();
		time=nowtime.toString();
		s=JLinePrint.editText.getText();
		((JMenuItem)e.getSource()).setText(time+"      ");
		Load.setText(time+"      ");
	}//actionPerformed
}//即時存檔

//編輯->時間日期
class Timeanddate implements ActionListener{
	public void actionPerformed(ActionEvent e){
		Date nowtime=new Date();
		SimpleDateFormat matter1=new SimpleDateFormat("yyyy'年'MM月dd日HH時mm分ss秒(a)(EE)");
		JLinePrint.editText.append(matter1.format(nowtime));
	}//actionPerformed
}//時間日期

//編輯->轉到
class Gototheline implements ActionListener{
	public void actionPerformed(ActionEvent e){
		final JFrame frame=new JFrame("轉到下列行");
		frame.setLayout(new GridLayout(2,1));
		frame.setBounds(455,225,249,100);
		JPanel pane=new JPanel();
		JPanel pane1=new JPanel();
		JLabel label=new JLabel("<html><font face='仿宋_GB2312 size=5'>行數:</font></html>");
		final JTextField textfield=new JTextField(5);
		JButton button=new JButton("確定");
		button.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e){
				String text=textfield.getText();
				if(!text.matches("\\p{Digit}+"))return;//如果輸入有非數字則不執行
				String[] s=JLinePrint.editText.getText().split("\n");//以回車符切割成String陣列
				int Position=0;
				int EndPosition=Integer.parseInt(text);
				if(EndPosition>s.length)EndPosition=s.length;//如果輸入的行數大於最大行數則行數等於最大行數
				for(int i=0;++i<EndPosition;){//獲得指定行數第一個字元在JTextArea.getText()內的位置
					Position+=s[i-1].length()+1;
				}//for
				//起點終點都一樣即一個游標
				JLinePrint.editText.setSelectionStart(Position);
				JLinePrint.editText.setSelectionEnd(Position);
			}
		});
		JButton button1=new JButton("取消");
		button1.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e){
				frame.dispose();
			}
		});
		pane.add(label);//行數:
		pane.add(textfield);//行數文字框
		pane1.add(button);//確定按鈕
		pane1.add(button1);//取消按鈕
		frame.add(pane);//行數+行數文字框
		frame.add(pane1);//確定+取消按鈕
		frame.setVisible(true);
		frame.setResizable(false);
	}//actionPerformed
}//轉到

//編輯->剪下
class Cut implements ActionListener{
	public static String cut;
	public Cut(){
		cut=null;
	}
	public void actionPerformed(ActionEvent e) {
		String s=JLinePrint.editText.getText();
		int Start=JLinePrint.editText.getSelectionStart();
		int End=JLinePrint.editText.getSelectionEnd();
		if(Start!=End){
			cut=s.substring(Start, End);
		    JLinePrint.editText.replaceRange("", Start, End);
		           Copy.copy=false;
		}//if
	}//actionPerformed
}//剪下

//編輯->複製
class Copy implements ActionListener{
	public static boolean copy;
	public Copy(){
		copy=false;
	}//複製
	public void actionPerformed(ActionEvent e){
		String s=JLinePrint.editText.getText();
		int Start=JLinePrint.editText.getSelectionStart();
		int End=JLinePrint.editText.getSelectionEnd();
		if(Start!=End){
	    	Cut.cut=s.substring(Start, End);
      		copy=true;
		}//if
	}
}//複製

//編輯->貼上
class Paste implements ActionListener{
	public void actionPerformed(ActionEvent e){
		if(Cut .cut!=null){
	    	int Start=JLinePrint.editText.getSelectionStart();
		    int End=JLinePrint.editText.getSelectionEnd();
		    JLinePrint.editText.replaceRange(Cut.cut, Start, End);
		    if(!Copy.copy)Cut.cut=null;
		}//if
	}//actionPerformed
}//複製

//編輯->刪除
class Delete implements ActionListener{
	public void actionPerformed(ActionEvent e){
    	int Start=JLinePrint.editText.getSelectionStart();
	    int End=JLinePrint.editText.getSelectionEnd();
	    JLinePrint.editText.replaceRange("",Start,End);
	}//actionPerformed
}//刪除

//編輯->查詢和替換 
class FindandReplace implements ActionListener{
	public int Start;
	public int End;
	public int pos;
	public JFrame frame;
	public String s;//替換內容
	public String p;//子串 
	public String mainstr;//父串
	public boolean isUP;//查詢順序是否為向上,預設為向上
	public static boolean First;//用於向上查詢
	public boolean UpperAndLowerCase;//用於區分大小寫,預設為不區分
	public boolean Search_Stop;
	public FindandReplace(){
		p=null;
		mainstr="0";
		isUP=true;
		UpperAndLowerCase=false;
		Start=0;
		End=0;
		Search_Stop=false;
		FindMenu();   	//建立選單
	}//查詢和替換
	public void actionPerformed(ActionEvent e){
     	if(((JMenuItem)e.getSource()).getText().equals("查詢和替換(F)...")){
	    	frame.setVisible(true);
		}//e.getSource=="查詢";
	    if(p != null){	
	    	if(((JMenuItem)e.getSource()).getText().equals("查詢下一個(N)")){
		    	Find();
	    	}//e.getSource().equals(查詢下一個);
		}//if
	}//actionPerformed
	public void FindMenu(){
    	First=true;//用於向上查詢
    	//建立查詢視窗
    	frame=new JFrame("查詢和替換");
    	frame.setBounds(433,347,327,200);
    	frame.setResizable(false);
    	frame.setLayout(new FlowLayout());
    	JLabel label_TheContentForResearching=new JLabel("查詢內容(N):");
    	label_TheContentForResearching.setBounds(8,8,70,8);
    	final JTextField textfield=new JTextField(10);
    	textfield.addCaretListener(new CaretListener(){
	    	public void caretUpdate(CaretEvent e) {
	    		p=((JTextField)e.getSource()).getText();
	    	}
     	});
    	textfield.addActionListener(new ActionListener(){
    		public void actionPerformed(ActionEvent e){
    			if(p!=null)Find();
    		}
    	});
    	JButton button_searchfornext=new JButton("查詢下一個");
    	button_searchfornext.addActionListener(new ActionListener(){
    		public void actionPerformed(ActionEvent e){
    			if(p!=null)Find();
	    	}//actionPerformed
	   });//addActionListener
    	JLabel label_TheContentForReplacing=new JLabel("替換內容(C):");
    	label_TheContentForReplacing.setBounds(8,8,70,8);
    	final JTextField textfield1=new JTextField(10);
    	textfield1.addCaretListener(new CaretListener(){
	    	public void caretUpdate(CaretEvent e) {
	    		s=((JTextField)e.getSource()).getText();
	    	}
     	});
    	JButton button_replace=new JButton("替換這一個");
    	button_replace.addActionListener(new ActionListener(){
    		public void actionPerformed(ActionEvent e){
    			if(s!=null){
	          		JLinePrint.editText.replaceRange(s, Start, End);
    			}
	    	}//actionPerformed
	   });//addActionListener
    	JButton button_replaceall=new JButton("替換全部");
    	button_replaceall.addActionListener(new ActionListener(){
    		public void actionPerformed(ActionEvent e){
    			if(p!=null&&s!=null){
    			    	JLinePrint.editText.setText(JLinePrint.editText.getText().replaceAll(p, s));
    			}//if
    		}//actionPerformed
    	});//addActionListener
    	JButton button_change=new JButton("互換");
    	button_change.addActionListener(new ActionListener(){
    		public void actionPerformed(ActionEvent e){
    			if(p!=null&&s!=null){
    	     		String temp=p;
    	    		textfield.setText(s);
    		    	textfield1.setText(temp);
    			}//if
    		}
    	});
    	JButton button_cancel=new JButton("取消");
    	button_cancel.addActionListener(new ActionListener(){
    		public void actionPerformed(ActionEvent e){
    			frame.dispose();
    		}
    	});
		JCheckBox checkbox=new JCheckBox("區分大小寫(C)");
		checkbox.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e){
				if(UpperAndLowerCase){
					UpperAndLowerCase=false;
				}
				else{
					UpperAndLowerCase=true;
				}
			}
		});
    	ButtonGroup Direction=new ButtonGroup();
    	JRadioButton button3=new JRadioButton("向上");
    	JRadioButton button4=new JRadioButton("向下");
    	JPanel pane1=new JPanel();
	
    	Direction.add(button3);
    	Direction.add(button4);
    	button3.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e){
				isUP=true;
			}
		});
		button4.addActionListener(new ActionListener(){
    		public void actionPerformed(ActionEvent e){
    			isUP=false;
    		}
    	});
    	Direction.setSelected(button3.getModel(), true);
		UpperAndLowerCase=false; //預設為不區分大小寫
    	pane1.add(button3);
    	pane1.add(button4);

    	frame.add(label_TheContentForResearching);//查詢內容
    	frame.add(textfield);                      //查詢內容文字框
    	frame.add(button_searchfornext);           //"查詢下一個"按鈕
    	
    	frame.add(label_TheContentForReplacing);  //替換內容
    	frame.add(textfield1);                    //替換內容文字框
    	frame.add(button_replace);                //"替換這一個"按鈕
    	
    	frame.add(checkbox);                //區分大小寫
	
    	frame.add(pane1);                 //方向
    	//設定方向文字框
    	pane1.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder("方向"),BorderFactory.createEmptyBorder()));
	
    	frame.add(button_cancel);        //取消按鈕
    	frame.add(button_change);        //互換按鈕
    	frame.add(button_replaceall);     //替換全部按鈕
	}//FindMenu
	public void Find(){
  		mainstr=JLinePrint.editText.getText();
    	int[] next=new int[p.length()];
    	if(isUP){//如果選擇了向上查詢
    		//向上查詢
    		//若pos=JLinePrint.pos只有這句的話會卡在最後一個沒辦法繼續向上查詢
    		//若pos=JLinePrint.pos-1只有這句的話會跳過最後一個只從倒數第二個開始執行
    		if(First){
    			pos=JLinePrint.pos;//UP獲取游標位置
    			First=false;
     		}//if
    		else {
    			pos=JLinePrint.pos-1;
    			if(pos<=1)First=true;
    		}//else
    		getNext_UP(p,next);
    		if(!UpperAndLowerCase){ //是否區分大小寫
    			KMPFind_UP_UpperAndLowerCase(mainstr,p,next,pos);
    		}
    		else{
         		KMPFind_UP(mainstr,p,next,pos);
    		}
    		//選擇Start位置和End位置之間的文字
            JLinePrint.editText.setSelectionStart(Start);
            JLinePrint.editText.setSelectionEnd(End);
    	}//if
    	else//向下查詢
    	{
    		pos=JLinePrint.pos+1;//DOWN獲取游標位置
    		getNext_DOWN(p,next);
    		if(!UpperAndLowerCase){ //是否區分大小寫
    			KMPFind_DOWN_UpperAndLowerCase(mainstr,p,next,pos);
    		}//if
    		else
    		{
         		KMPFind_DOWN(mainstr,p,next,pos);
    		}//else
    		//選擇Start位置和End位置之間的文字
        	JLinePrint.editText.setSelectionStart(Start);
        	JLinePrint.editText.setSelectionEnd(End);
    	}//else
	}//Find
	public void KMPFind_DOWN_UpperAndLowerCase(String mainstr,String p,int[] next,int pos){//向下查詢,不區分大小寫
		int i=pos,j=1;
		while(i<=mainstr.length()&&j<=p.length()){
		//	str=String.valueOf(mainstr.charAt(i-1));
		//	str1=String.valueOf(p.charAt(j-1));
			if(j==0||judge(i-1,j-1)){
				i++;
				j++;
			}//if
			else{
				j=next[j-1]+1;
			}
		}//while
		if(j>p.length()){
			Start=i-p.length()-1;
			End=Start+p.length();
		}
		else{
			Search_Stop=true;
			JOptionPane.showMessageDialog(new JFrame(), "已完成對文件下半部分的搜尋");
			Start=0;End=0;
		}
	}//KMPFind_DOWN_UpperAndLowerCase
	public void KMPFind_UP_UpperAndLowerCase(String mainstr,String p,int[] next,int pos){//向上查詢,不區分大小寫
		int length=p.length()-1;
		int i=pos-1,j=length;
		while(i>-1 && j>-1){
			if(j==length+1||judge(i,j)){
				i--;
				j--;
			}//if
			else{
				j=next[j];
			}
		}//while
		if(j<=-1){
			End=i+p.length()+1;
			Start=End-p.length();
		}
		else{
			JOptionPane.showMessageDialog(new JFrame(), "已完成對文件上半部分的搜尋");
			Start=mainstr.length();
			End=mainstr.length();
			First=true;