• <JAVA


    <JAVA - 大作业(1)文本编辑器 >

    背景

    • JAVA上机大作业:qq / 代码评价系统

    • 第一次上机主题是练习JAVA自带的GUI图形化编程

    • 目的:实现一个跟window10记事本界面相同,功能相近的文本编辑器,时间有剩余的话再添加类似notepad++上的一些额外功能。

    • 记事本结构

      • 标题栏
        显示标题title

      • 菜单栏
        文件、编辑、格式、查看、帮助 - 菜单项

        • <文件>下拉栏有:新建、新窗口、打开、保存、退出

        • <编辑>下拉栏有:撤销、恢复、剪切、复制、粘贴、删除

        • <格式>下拉栏有:字体

        • <帮助>下拉栏有:关于

      • 文本区域

        • 底侧滚动条

    设计思路

    • 菜单栏:

      • 主体就是一个JFrame,设置一些属性,然后设置菜单栏JMenuBar,add菜单项JMenu,菜单项的下拉栏add菜单子项JMenuItem
    • 文本区域:

      • 完成菜单栏之后就是一个占屏幕率超大的JTextArea,注意该文本区域需要将他设置为静态,并且写一个静态get函数得到它,因为有跨类的需要改该文本属性。由于有滚动条,后续还要加上显示行号的功能,所以用一个JScrollPane装载它。
    • 文件菜单子栏:

      • 新建:就新建一个窗口new TextEdition(),并且把当前窗口退出dispose(),退出前调用一次保存函数savefile()

      • 新窗口:

        • 新建一个窗口,并且当前窗口不退出,两窗口相互不影响,即默认退出操作使用DISPOSE_ON_CLOSE(当然可以自己写,退出时加上是否保存询问)
      • 打开:

        • 使用JFileChooser,界面为打开界面,打开跳出一个Dialog对话框,选择文件进行打开,InputStreamReader+BufferedReader
      • 保存:

        • 使用JFileChooser,界面为保存界面,跟打开操作一样,OutputStreamWriter+BufferedWriter
      • 退出:

        • 调用保存函数savefile(),并且dispose()当前窗口
    • 编辑菜单子栏:

      • 撤销:

        • 撤销与恢复都需要用到撤销管理类um = new UndoManager(),在监听器初始化时注册撤销可编辑监听器 - 文本区域getDocument().addUndoableEditListener,撤销操作就是 um.undo()
      • 恢复:

        • 恢复操作与上一致,监听器设置好以后,调用um.redo()即是恢复
      • 剪切:

        • 剪切与复制、粘贴是一起完成,需要用到系统剪切板clipboard = this.getToolkit().getSystemClipboard(),剪切就是复制+删除操作
      • 复制:

        • 先将文本区域的文本放到string里面,创建能传输指定 String 的 StringSelection,把系统剪切板的内容设置成StringSelection:clipboard.setContents(editText,null);
      • 粘贴:

        • 先将系统剪切板的内容放在一个Transferable里面,之后再将Transferable转成string,文本区域append即可
      • 删除

        • getSelectionStart,getSelectionEnd得到头尾,再replaceRange替换成空文本即可
    • 格式菜单子栏:

      • 字体
        • 新建一个窗体设置字体,用JComboBox实现下拉列表,一个JTextField放演示文本,再是确认取消按钮,三个JPanel分别装这三部分整理布局排版,确认按钮点击后就调用静态get函数得到父窗体的文本区域设置其属性。
    • 帮助菜单子栏:

      • 关于
        • 弹出一个新窗体,里面用label写文本显示

    TextEdition - 主窗体类实现

    主窗体属性

    ublic class TextEditor extends JFrame implements ActionListener{
    	//	其实我们这里也可以用ItemListener用于捕获带有item的组件产生的事件,
    	//	而ActionListener是所有监听器的父类,可以监听到所有的事件,由于担心还会有其他的事件需要监听,
    	//	所以就直接用 ActionListener 了
    
    	//菜单栏
    	private JMenuBar menuBar;
    	//菜单项
    	private JMenu menu_File,menu_Edit,menu_Help,menu_Format;
    	//file菜单项内容
    	private JMenuItem item_new,item_newwindow,item_open,item_save,item_exit;
    	//edit菜单项内容
    	private JMenuItem item_undo,item_redo,item_cut,item_copy,item_stick,item_delete;
    	//help菜单项内容
    	private JMenuItem item_about;
    	//format菜单项内容
    	private JMenuItem item_word_format;
    	
    	//文本区域
    	private static JTextArea edit_text_area;	//static因为要在其他窗口对其他字体格式进行改动
    	//文本滚动条
    	private JScrollPane scroll_bar;
    	//撤销管理
    	private UndoManager um;
    	//系统剪切板
    	private Clipboard clipboard;
    	//文件选择器
    	private JFileChooser fileChooser;
    

    主窗体构造器

    public TextEditor()
    	{
    		initMenuBar();
    		initEditText();
    		initListener();
    		 
    		this.setJMenuBar(menuBar);
    		this.setSize(800,600);
    		this.add(scroll_bar);
    		this.setTitle("黄龙士文本编辑器");
    		this.setVisible(true);
    		this.setLocationRelativeTo(null);	//窗体位于正中间位置
    		this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);	// EXIT_ON_CLOSE  https://www.cnblogs.com/lihaiming93/p/4752422.html 后续还要改,加上退出询问
    	}
    

    initMenuBar() - 初始化菜单栏

    private void initMenuBar() {
    		
    		//初始化菜单栏
    		menuBar = new JMenuBar();
    		
    		//file菜单项
    		menu_File = new JMenu("文件(F)");
    		menu_File.setMnemonic('f');		// 设置快捷键-alt+f:打开 - 也可以传入KeyEvent.VK_F
    		item_new = new JMenuItem("新建");
    		item_newwindow = new JMenuItem("新窗口");
    		item_open = new JMenuItem("打开");
    		item_save = new JMenuItem("保存");
    		item_save.setAccelerator(KeyStroke.getKeyStroke('S',java.awt.Event.CTRL_MASK,false));//给item添加快捷键 CTRL_MASK = ctrl键
    		item_exit = new JMenuItem("退出");
    		menu_File.add(item_new);
    		menu_File.add(item_newwindow);
    		menu_File.add(item_open);
    		menu_File.add(item_save);
    		menu_File.add(item_exit);
    
    		//edit菜单项
    		menu_Edit = new JMenu("编辑(E)");
    		menu_Edit.setMnemonic('e');
    		item_undo = new JMenuItem("撤销");
    		item_redo = new JMenuItem("恢复");
    		item_cut = new JMenuItem("剪切");
    		item_copy = new JMenuItem("复制");
    		item_stick = new JMenuItem("粘贴");
    		item_delete = new JMenuItem("删除");
    		menu_Edit.add(item_undo);
    		menu_Edit.add(item_redo);
    		menu_Edit.add(item_cut);
    		menu_Edit.add(item_copy);
    		menu_Edit.add(item_stick);
    		menu_Edit.add(item_delete);
    		 
    		//help菜单项
    		menu_Help = new JMenu("帮助(H)");
    		menu_Help.setMnemonic('h');
    		item_about = new JMenuItem("关于");
    		menu_Help.add(item_about);
    
    		//format菜单项
    		menu_Format = new JMenu("格式(O)");
    		menu_Format.setMnemonic('o');
    		item_word_format = new JMenuItem("字体(F)");			//CTRL_MASK = ctrl键
    item_word_format.setAccelerator(KeyStroke.getKeyStroke('F',java.awt.Event.CTRL_MASK,false));//给item添加快捷键
    		menu_Format.add(item_word_format);
    
    		//加入菜单栏
    		menuBar.add(menu_File);
    		menuBar.add(menu_Edit);
    		menuBar.add(menu_Format);
    		menuBar.add(menu_Help);
    	}
    

    initEditText() - 初始化文本区域

    private void initEditText() {
    		
    		edit_text_area = new JTextArea();
    		scroll_bar = new JScrollPane(edit_text_area);
    		//垂直滚动条总是出现 - 自动出现:JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED||VERTICAL_SCROLLBAR_ALWAYS
    		scroll_bar.setRowHeaderView(new LineNumberHeaderView());		//显示行号
    		// 具体显示行号类:https://blog.csdn.net/wangjianyu0115/article/details/50780269
            
        scroll_bar.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
      scroll_bar.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
    		
    		um = new UndoManager();
    		clipboard = this.getToolkit().getSystemClipboard();
    	}
    

    saveFile - 保存文件

    private void saveFile() {
    		// TODO Auto-generated method stub
    
    		File file =null;
    		int result;		//int型值,showSaveDialog返回值用来判断用户是否选择了文件或路径。
    		fileChooser = new JFileChooser("C:\Users\62473\Desktop\");	//打开用户默认目录
    		result = fileChooser.showSaveDialog(rootPane); // 设置Dialog的根View根布局	显示对话框
    		
    		if(result == JFileChooser.APPROVE_OPTION) {
    			file = fileChooser.getSelectedFile(); // 若点击了确定按钮,给file填文件路径
    		}
    		else return;	//按取消键后不会运行下面代码
    		
    		try{
    			OutputStreamWriter write = new OutputStreamWriter(new FileOutputStream(file),"UTF-8"); // 对字符进行编码转换 输出流
    			BufferedWriter writer = new BufferedWriter(write);
    			for (String value : edit_text_area.getText().split("
    ")) {		// 实现在JTextArea多行如何转换到实际文本多行
    				writer.write(value);
    				writer.newLine();//换行
                }
    			writer.close();
    		}
    		catch(IOException e) {
    			e.printStackTrace();
    		}
    	}
    

    openfile() - 打开文件

    private void openFile() {
    	
    		File file =null;
    		int result;
    		fileChooser =new JFileChooser("C:\Users\62473\Desktop\");
    		result = fileChooser.showOpenDialog(rootPane);
    		
    		if(result == JFileChooser.APPROVE_OPTION) {
    			file = fileChooser.getSelectedFile(); // 若点击了确定按钮,给file填文件路径
    		}
    		else return;	//按取消键后不会运行下面代码
    	
    		if(file.isFile() && file.exists()) {
    			try {
    				edit_text_area.setText("");		//清空目前文本内容
    				InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream(file),"UTF-8");
    				BufferedReader reader = new BufferedReader(inputStreamReader);
    				String readLine;
    				while ((readLine = reader.readLine()) != null) {
    					edit_text_area.append(readLine+'
    ');
    				}
    				reader.close();
    			} 
    			catch (IOException e) {
    				// TODO: handle exception
    				e.printStackTrace();
    			}
    		}
    	
    	}
    

    actionPerformed(ActionEvent e) - 监听事件响应

    public void actionPerformed(ActionEvent e) {
    		// TODO Auto-generated method stub
    		//https://zhidao.baidu.com/question/2204274734088183468.html
    		
    		if(e.getSource()==item_about)
    		{
    			new helpWindow();
    		}
    		else if (e.getSource()==item_word_format) {
    			new aboutFormat();
    		}
    		else if (e.getSource()==item_new) {
    			this.saveFile();		//新建文件前保存原文件
    			new TextEditor();
    			this.dispose();		
    		}
    		else if (e.getSource()==item_newwindow) {
    			new TextEditor();		//添加新窗口,父窗口不会退出
    		}
    		else if (e.getSource()==item_exit){
    			this.saveFile();
    			this.dispose();			//退出询问(目前有无更改都会弹出保存窗口)
    		}
    		else if (e.getSource()==item_save) {
    			this.saveFile();
    		}
    		else if (e.getSource()==item_open) {
    			this.openFile();
    		}
    		else if (e.getSource()==item_undo&&um.canUndo()) {		//撤销可以撤销是撤销上一步文本操作
    			um.undo();
    		}
    		else if (e.getSource()==item_redo&&um.canRedo()) {		//恢复就是恢复上一步文本操作(需要被撤销)
    			um.redo();
    		}
    		else if (e.getSource()==item_copy) {
    			String temptext = edit_text_area.getSelectedText();		//得到选取文本
    			StringSelection editText = new StringSelection(temptext);	//创建能传输指定 String 的 Transferable
    			clipboard.setContents(editText,null);		// 将剪贴板的当前内容设置到指定的 transferable 对象,
    														// 并将指定的剪贴板所有者作为新内容的所有者注册。
    		}
    		else if (e.getSource()==item_cut) {
    			String temptext = edit_text_area.getSelectedText();
    			StringSelection editText = new StringSelection(temptext);
    			clipboard.setContents(editText,null);
    			int start= edit_text_area.getSelectionStart();		//复制+删除
    			int end  = edit_text_area.getSelectionEnd(); 
    			edit_text_area.replaceRange("",start,end);
    		}
    		else if (e.getSource()==item_stick) {
    			Transferable contents = clipboard.getContents(this);
    			DataFlavor  flavor= DataFlavor.stringFlavor;
    		    if( contents.isDataFlavorSupported(flavor))
    		    {
    			    try
    			    {  
    			    	String str;
    			    	str = (String)contents.getTransferData(flavor);
    			    	edit_text_area.append(str);
    			    }
    			    catch(Exception ex)
    			    {
    			    	ex.printStackTrace();
    			    }
    		    }
    		}
    		else if (e.getSource()==item_delete) {
    			int start= edit_text_area.getSelectionStart();		//删除
    			int end  = edit_text_area.getSelectionEnd(); 
    			edit_text_area.replaceRange("",start,end);
    		}
    	}
    

    initListener() - 初始化监听器

    public void initListener()
    	{
    		// 菜单iter监听
    		item_new.addActionListener(this);
    		item_newwindow.addActionListener(this);
    		item_open.addActionListener(this);
    		item_save.addActionListener(this);
    		item_exit.addActionListener(this);
    		item_undo.addActionListener(this);
    		item_redo.addActionListener(this);
    		item_cut.addActionListener(this);
    		item_copy.addActionListener(this);
    		item_stick.addActionListener(this);
    		item_delete.addActionListener(this);
    		item_word_format.addActionListener(this);
    		item_about.addActionListener(this);
    		
    		//注册撤销/恢复可编辑监听器
    		edit_text_area.getDocument().addUndoableEditListener(new UndoableEditListener(){		
                public void undoableEditHappened(UndoableEditEvent e) {
                    um.addEdit(e.getEdit());
                }
            });
    		
    	}
    

    getEdit_text_area() - 静态get函数得到文本区域

    public static JTextArea getEdit_text_area() {
    	//返回文本编辑区给其他窗口
    		return edit_text_area;
    	}
    

    main() - main函数

    public static void main(String[] args) {
    		
    		TextEditor test = new TextEditor();
    	
    	}
    	
    }
    

    aboutFormat - 字体窗口实现

    字体窗口属性

    public class aboutFormat extends JFrame implements ItemListener,ActionListener {
    
    	private JComboBox choose_word_style;	//下拉列表
    	private JComboBox choose_word_big;
    	private JComboBox choose_word_pattern;
    	private JComboBox choose_word_color;
    	
    	private String[] styles = {"宋体","黑体","楷体","微软雅黑","隶书"};
    	private String[] colors = {"黑色","蓝色","绿色","红色","白色","黄色"};
    	private String[] word_big = {"2","4","8","16","24","32","64","72"};
    	private String[] pattern = {"常规","倾斜","粗体"};
    	
    	private JPanel paneNorth;//用于装四个ComboBox
    	private JPanel paneCenter;//用来装演示区
    	private JPanel paneSouth;//用来装按钮
    	
    	private JTextField showText;//演示文本
    	
    	private JButton btn_ok;		
    	private JButton btn_cancel;
    	
    	private Font selectedFont = TextEditor.getEdit_text_area().getFont();	//用来封装改变的属性
    	private String selectedStyle = "宋体";		//默认字体属性
    	private int selectedBig = 32;
    	private int selectedPattern = Font.PLAIN;
    	private Color selectedColor = TextEditor.getEdit_text_area().getForeground();	//颜色要单独加上改
    

    字体窗口构造器

    public aboutFormat() {
    		  initBox();
    		  initText();
    		  initButton();
    		  initLocation();
    		  initListener();
    		  addBtnListener();
    		  
    		  this.setSize(550,240);
    		  this.setTitle("文字格式");
    		  this.setVisible(true);
    		  this.setLocationRelativeTo(null);
    		  this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    	  }
    

    addBtnListener() - 注册监听

    private void addBtnListener() {
    		// TODO Auto-generated method stub		//注册按钮监听
    		btn_cancel.addActionListener(this);
    		btn_ok.addActionListener(this);
    	}
    

    initListener() - 初始化监听器

    private void initListener() {		//注册下拉框监听
    		// TODO Auto-generated method stub
    		choose_word_style.addItemListener(this);
    		choose_word_big.addItemListener(this);
    		choose_word_pattern.addItemListener(this);
    		choose_word_color.addItemListener(this);
    	}
    

    initButton() - 初始化按钮

    private void initButton() {
    		// TODO Auto-generated method stub
    		btn_ok = new JButton("OK");
    		btn_cancel = new JButton("CANCEL");
    	}
    

    initText() - 初始化演示文本

    private void initText() {
    		// TODO Auto-generated method stub
    		showText = new JTextField("字体展示");
    		showText.setHorizontalAlignment(JTextField.CENTER);	//文本居中
    		showText.setFont(selectedFont);
    		showText.setEditable(false);	//不可编辑
    		showText.setSize(200,200);
    //		showText.setForeground(Color.green);//字体颜色
    	}
    

    initLocation() - 初始化布局

    /**
    	   * 初始化布局
    	   * 将每个控件按照一定得布局排在this窗口中
    	   */
    	  public void initLocation() {
    		  paneNorth = new JPanel();
    		  paneNorth.add(new JLabel("字体:"));	//添加下拉区
    		  paneNorth.add(choose_word_style);
    		  paneNorth.add(new JLabel("字号:"));
    		  paneNorth.add(choose_word_big);
    		  paneNorth.add(new JLabel("字形:"));
    		  paneNorth.add(choose_word_pattern);
    		  paneNorth.add(new JLabel("颜色:"));
    		  paneNorth.add(choose_word_color);
    		  paneNorth.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));	//让add的组件不置顶
    		  this.add(paneNorth,BorderLayout.NORTH);
    		  
    		  paneCenter = new JPanel();	//添加展示区
    		  paneCenter.add(showText);
    		  
    		  this.add(paneCenter, BorderLayout.CENTER);	//添加按钮去
    		  paneSouth = new JPanel();
    		  paneSouth.add(btn_ok);
    		  paneSouth.add(btn_cancel);
    		  this.add(paneSouth, BorderLayout.SOUTH);
    		  
    	  }
    

    initBox() - 初始化下拉栏

    /**
      	 * 初始化几个comboBox 
      	 * 把相应的选项加入
      	 */
      public void initBox() {
    	  choose_word_style = new JComboBox(styles);	//数组传入就不用addItem
    	  choose_word_big = new JComboBox(word_big);
    	  choose_word_pattern = new JComboBox(pattern);
    	  choose_word_color = new JComboBox(colors);
      }
    

    actionPerformed(ActionEvent e) - 监听事件响应

    @Override
    	public void actionPerformed(ActionEvent e) {	//对按钮的监听
    		// TODO Auto-generated method stub
    		if (e.getSource() == btn_cancel) {
    			  this.dispose();//销毁当前窗口
    		}else if (e.getSource() == btn_ok) { // 调用父窗体的实例,拿到text_area并对其setFont
    	    
    			TextEditor.getEdit_text_area().setFont(selectedFont);	//改字体
    			TextEditor.getEdit_text_area().setForeground(selectedColor);	//改字体颜色
    			this.dispose();
    		}
    	}
    

    itemStateChanged(ItemEvent e) - 下拉栏的监听

    @Override
    	public void itemStateChanged(ItemEvent e) {	//对下拉框的监听
    		// TODO Auto-generated method stub
    		if (e.getItem() == "宋体") {
    			  selectedStyle = "宋体";
    			  renewFont();
    		  }else if (e.getItem() == "黑体") {
    			  selectedStyle = "黑体";
    			  renewFont();
    		  }else if (e.getItem() == "楷体") {
    			  selectedStyle = "楷体";
    			  renewFont();
    		  }else if (e.getItem() == "微软雅黑") {
    			  selectedStyle = "微软雅黑";
    			  renewFont();
    		  }else if (e.getItem() == "隶书") {
    			  selectedStyle = "隶书";
    			  renewFont();
    		  }else if (e.getItem() == "常规") {
    			  selectedPattern = Font.PLAIN;
    			  renewFont();
    		  }else if (e.getItem() == "倾斜") {
    			  selectedPattern = Font.ITALIC;
    			  renewFont();
    		  }else if (e.getItem() == "粗体") {
    			  selectedPattern = Font.BOLD;
    			  renewFont();
    		  }else if (e.getItem() == "2") {
    			  selectedBig = 2;
    			  renewFont();
    		  }else if (e.getItem() == "4") {
    			  selectedBig = 4;
    			  renewFont();
    		  }else if (e.getItem() == "8") {
    			  selectedBig = 8;
    			  renewFont();
    		  }else if (e.getItem() == "16") {
    			  selectedBig = 16;
    			  renewFont();
    		  }else if (e.getItem() == "24") {
    			  selectedBig = 24;
    			  renewFont();
    		  }else if (e.getItem() == "32") {
    			  selectedBig = 32;
    			  renewFont();
    		  }else if (e.getItem() == "64") {
    			  selectedBig = 64;
    			  renewFont();
    		  }else if (e.getItem() == "72") {
    			  selectedBig = 72;
    			  renewFont();
    		  }else if (e.getItem() == "红色") {
    			  selectedColor = Color.red;
    			  renewFont();
    		  }else if (e.getItem() == "黑色") {
    			  selectedColor = Color.black;
    			  renewFont();
    		  }else if (e.getItem() == "蓝色") {
    			  selectedColor = Color.blue;
    			  renewFont();
    		  }else if (e.getItem() == "黄色") {
    			  selectedColor = Color.yellow;
    			  renewFont();
    		  }else if (e.getItem() == "绿色") {
    			  selectedColor = Color.green;
    			  renewFont();
    		  }else if (e.getItem() == "白色") {
    			  selectedColor = Color.WHITE;
    			  renewFont();
    		  }
    	}
    

    renewFont() - 更改默认字体

    private void renewFont() {
    		// TODO Auto-generated method stub
    		selectedFont = new Font(selectedStyle,selectedPattern,selectedBig);
    		showText.setFont(selectedFont);
    		showText.setForeground(selectedColor);
    	}
    
    }
    

    helpWindow - 帮助窗口实现

    帮助窗口属性

    public class helpWindow extends JFrame {
    
    	private JButton btn_ok;
    	private JLabel about_label;
     
    	private JPanel panel ;
    	private BoxLayout boxlayout;	//指定在容器中是否对控件进行水平或者垂直放置
    

    帮助窗口构造器

    	public helpWindow() {
    		panel = new JPanel();	//轻量级面板容器
    		boxlayout = new BoxLayout(panel,BoxLayout.Y_AXIS);	//Y_AXIS - 控件垂直放置
    		panel.setLayout(boxlayout);
    		
    		btn_ok = new JButton("OK");
    		btn_ok.setAlignmentX(CENTER_ALIGNMENT);	//alignment对齐
    //		about_label = new JLabel("https://www.cnblogs.com/ymjun/");
    		about_label = new JLabel("<html><br /><h3 style='text-align:center;color:brown;'>黄龙士文本编辑器</h3>"	//JLabel里面可以嵌入html
    				+ "blog:https://www.cnblogs.com/ymjun/<br />"
    				+ "github:https://github.com/iym070010<br />"
    				+ "email:iym070010@163.com<br />"
    				+ "使用方式跟.txt文本编辑器一致<br />"
    				+ "<br /><br />"
    				+ "</html>",JLabel.CENTER);
    		about_label.setAlignmentX(CENTER_ALIGNMENT);
     
    		panel.add(about_label);
    		panel.add(btn_ok);
    		
    		this.add(panel);
    		this.setSize(400,300);
    		this.setTitle("关于");
    		this.setVisible(true);
    		this.setLocationRelativeTo(null);
    		this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    		
    		btn_ok.addActionListener(e->{	//窗口关闭
    			this.dispose();
    		});
    	}
    }
    

    LineNumberHeaderView - TextArea行数显示插件

    //package com.ui;
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Font;
    import java.awt.FontMetrics;
    import java.awt.Graphics;
    import java.awt.Rectangle;
    //TEXTAREA 行号显示插件
    public class LineNumberHeaderView extends javax.swing.JComponent {		//貌似就是Notepad++行号显示的实现类
     
        /**
    	 * JAVA TextArea行数显示插件
    	 */
    	private static final long serialVersionUID = 1L;
    	private final  Font DEFAULT_FONT = new Font(Font.MONOSPACED, Font.PLAIN, 11);
        public final Color DEFAULT_BACKGROUD = new Color(228, 228, 228);
        public final Color DEFAULT_FOREGROUD = Color.BLACK;
        public final int nHEIGHT = Integer.MAX_VALUE - 1000000;
        public final int MARGIN = 5;
        private int lineHeight;
        private int fontLineHeight;
        private int currentRowWidth;
        private FontMetrics fontMetrics;
     
        public LineNumberHeaderView() {
            setFont(DEFAULT_FONT);
            setForeground(DEFAULT_FOREGROUD);
            setBackground(DEFAULT_BACKGROUD);
            setPreferredSize(9999);
        }
     
        public void setPreferredSize(int row) {
            int width = fontMetrics.stringWidth(String.valueOf(row));
            if (currentRowWidth < width) {
                currentRowWidth = width;
                setPreferredSize(new Dimension(2 * MARGIN + width + 1, nHEIGHT));
            }
        }
     
        @Override
        public void setFont(Font font) {
            super.setFont(font);
            fontMetrics = getFontMetrics(getFont());
            fontLineHeight = fontMetrics.getHeight();
        }
     
        public int getLineHeight() {
            if (lineHeight == 0) {
                return fontLineHeight;
            }
            return lineHeight;
        }
     
        public void setLineHeight(int lineHeight) {
            if (lineHeight > 0) {
                this.lineHeight = lineHeight;
            }
        }
     
        public int getStartOffset() {
            return 4;
        }
     
        @Override
        protected void paintComponent(Graphics g) {
            int nlineHeight = getLineHeight();
            int startOffset = getStartOffset();
            Rectangle drawHere = g.getClipBounds();
            g.setColor(getBackground());
            g.fillRect(drawHere.x, drawHere.y, drawHere.width, drawHere.height);
            g.setColor(getForeground());
            int startLineNum = (drawHere.y / nlineHeight) + 1;
            int endLineNum = startLineNum + (drawHere.height / nlineHeight);
            int start = (drawHere.y / nlineHeight) * nlineHeight + nlineHeight - startOffset;
            for (int i = startLineNum; i <= endLineNum; ++i) {
                String lineNum = String.valueOf(i);
                int width = fontMetrics.stringWidth(lineNum);
                g.drawString(lineNum + " ", MARGIN + currentRowWidth - width - 1, start);
                start += nlineHeight;
            }
            setPreferredSize(endLineNum);
        }
    }
    
  • 相关阅读:
    Dilworth定理,链还是反链?
    pku 3259Wormholes
    hdu 2612 Find a way
    hdu 2614
    hdu 2544 最短路
    hdu 2553 N皇后问题
    hdu2717 Catch That Cow
    hdu 1874 畅通工程续
    jquery学习必备代码和技巧
    HTML5 WebApp part4:使用 Web Workers 来加速您的移动 Web 应用程序(上)
  • 原文地址:https://www.cnblogs.com/ymjun/p/11846826.html
Copyright © 2020-2023  润新知