本文通过Swing来实现文档简易而不简单的文档编辑器,该文档编辑器的功能包括:
- 设置字体样式:粗体,斜体,下划线,可扩展
- 设置字体:宋体,黑体,可扩展
- 设置字号:12,14,18,20,30,40, 可扩展
- 设置字体颜色:红色,蓝色,绿色,黄色,黑色,可扩展
- 设置字体背景颜色:淡蓝,淡黄,淡绿,灰色,无色,可扩展
- 插入图片
效果如下所示:
本文档编辑器使用Swing的JTextPanel来实现,使用JTextPanel可以实现富文档化,包括设置文档字体,颜色等,还可以插入图片和HTML链接,
而本编辑器实现的关键是,对于字体样式,颜色,大小和字体使用Java封装好的StyledEditorKit的种种Action然后将这些Action通过addAction添加到下拉框对象即可。
- StyledEditorKit.BoldAction() 粗体
- StyledEditorKit.UnderlineAction(); 下划线
- StyledEditorKit.ItalicAction(); 斜体
- StyledEditorKit.FontFamilyAction("宋体", "宋体") 宋体
- tyledEditorKit.FontSizeAction(“12”, 12) 字体大小
- StyledEditorKit.ForegroundAction("Black",Color.black); 字体颜色
除了以上Java封装良好的支持之外,对字体的背景色,插入图片就没有那么好的待遇了,这些实现必须通过其他方式来实现,对于设置字体的背景色,可以通过查看StyledEditorKit.ForgroundAction的源代码,自行写出一个类,可见下面DocBackgroundAction类,但是插入图片就没有那么幸运了,最终采用的方式是使用JTextPanel提供的insertIcon方法来插入图片,但为了和其他方式保持一致性,依然使用Action的方式,具体代码可以参考如下的DocImageAction
JTextPane docTextPane = new JTextPane(); final JComboBox fontModelCb = new JComboBox();// 字体样式下拉框,包括粗体,下划线和斜体 fontModelCb.setModel(new DefaultComboBoxModel(new String[] { "u7C97u4F53", "u4E0Bu5212u7EBF", "u659Cu4F53" })); fontModelCb.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { Object sel = e.getItem(); Action ac = null; System.out.println("fontModelCb itemStateChanged:" + sel.toString()); if (sel.equals("u7C97u4F53")) { ac = new StyledEditorKit.BoldAction(); ac.putValue(Action.NAME, "Bold"); } else if (sel.equals("u4E0Bu5212u7EBF")) { ac = new StyledEditorKit.UnderlineAction(); ac.putValue(Action.NAME, "Underline"); } else { ac = new StyledEditorKit.ItalicAction(); ac.putValue(Action.NAME, "Italic"); } fontModelCb.setAction(ac); } }); final JComboBox fontTypeCb = new JComboBox(); //设置字体下拉框,包括宋体和黑体 fontTypeCb.setModel(new DefaultComboBoxModel(new String[] { "u5B8Bu4F53", "u9ED1u4F53" })); fontTypeCb.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { Object sel = e.getItem(); Action ac = null; System.out.println("fontTypeCb itemStateChanged:" + sel.toString()); if (sel.equals("u5B8Bu4F53")) { ac = new StyledEditorKit.FontFamilyAction("宋体", "宋体"); } else { ac = new StyledEditorKit.FontFamilyAction("黑体", "黑体"); } fontTypeCb.setAction(ac); } }); final JComboBox fontSizeCb = new JComboBox();// 设置字体下拉框 fontSizeCb.setModel(new DefaultComboBoxModel(new String[] { "12", "14", "18", "20", "30", "40" })); fontSizeCb.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { Object sel = e.getItem(); fontSizeCb.setAction(new StyledEditorKit.FontSizeAction(sel .toString(), Integer.parseInt(sel.toString()))); } }); final JComboBox fontColorCb = new JComboBox(); //设置字体颜色下拉框 fontColorCb.setModel(new DefaultComboBoxModel(new String[] { "u9ED1u8272", "u7EA2u8272", "u84DDu8272", "u9EC4u8272", "u7EFFu8272" })); fontColorCb.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { Object sel = e.getItem(); Action ac = null; if (sel.equals("u9ED1u8272")) { ac = new StyledEditorKit.ForegroundAction("Black", Color.black); } else if (sel.equals("u7EA2u8272")) { ac = new StyledEditorKit.ForegroundAction("Red", Color.red); } else if (sel.equals("u84DDu8272")) { ac = new StyledEditorKit.ForegroundAction("Green", Color.green); } else if (sel.equals("u9EC4u8272")) { ac = new StyledEditorKit.ForegroundAction("Yellow", Color.yellow); } else { ac = new StyledEditorKit.ForegroundAction("Blue", Color.blue); } fontColorCb.setAction(ac); } }); final JComboBox fontBgColorCb = new JComboBox(); //设置字体背景下拉框 fontBgColorCb.setModel(new DefaultComboBoxModel(new String[] { "u65E0u8272", "u7070u8272", "u6DE1u7EA2", "u6DE1u9EC4", "u6DE1u84DD", "u6DE1u7EFF" })); fontBgColorCb.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { Object sel = e.getItem(); Action ac = null; System.out.println("fontBgColorCb:" + sel.toString()); if (sel.equals("u7070u8272")) {// 灰色 ac = new DocBackgroundAction("LightBlack", new Color(200, 200, 200)); } else if (sel.equals("u6DE1u7EA2")) {// 淡红 ac = new DocBackgroundAction("LightRed", new Color(255, 200, 200)); } else if (sel.equals("u6DE1u9EC4")) { // 淡黄 ac = new DocBackgroundAction("LightGreen", new Color(255, 255, 200)); } else if (sel.equals("u6DE1u84DD")) {// 淡蓝 ac = new DocBackgroundAction("YLightYellow", new Color(200, 200, 255)); } else if (sel.equals("u6DE1u7EFF")) {// 淡绿 ac = new DocBackgroundAction("LightBlue", new Color(200, 255, 200)); } if (ac != null) { fontBgColorCb.setAction(ac); } } }); JButton insertImageBt = new JButton("u63D2u5165u56FEu7247"); //插入图片按钮 insertImageBt.setAction(new DocImageAction("插入图片", docTextPane));
DocBackgroundAction类仿照StyledEditorKit.ForegroundAction而成,区别在于使用StyleConstants.setBackground(attr, fg);
public class DocBackgroundAction extends StyledTextAction { private static final long serialVersionUID = 1L; public DocBackgroundAction(String nm, Color bg) { super(nm); this.bg = bg; } public void actionPerformed(ActionEvent e) { JEditorPane editor = getEditor(e); if (editor != null) { Color fg = this.bg; if ((e != null) && (e.getSource() == editor)) { String s = e.getActionCommand(); try { fg = Color.decode(s); } catch (NumberFormatException nfe) { } } if (fg != null) { MutableAttributeSet attr = new SimpleAttributeSet(); StyleConstants.setBackground(attr, fg); setCharacterAttributes(editor, attr, false); } else { UIManager.getLookAndFeel().provideErrorFeedback(editor); } } } private Color bg; }
DocImageAction类继承了StyledTextAction,在JtextPane中插入图片的方式其实非常简单使用panel.insertIcon方法即可,如下
public class DocImageAction extends StyledTextAction { private static final long serialVersionUID = 1L; public DocImageAction(String nm, JTextPane panl) { super(nm); this.panl = panl; } public void actionPerformed(ActionEvent e) { JFileChooser f = new JFileChooser(); // 查找文件 f.showOpenDialog(null); System.out.println(f.getSelectedFile()); ImageIcon icon = createImageIcon(f.getSelectedFile(), "a cute pig"); JTextPane editor = this.panl; if (editor != null) { System.out.println("I am in here"); StyledDocument doc = getStyledDocument(editor); editor.setCaretPosition(doc.getLength()); // 设置插入位置 editor.insertIcon(icon); // 插入图片 } } private JTextPane panl; /** Returns an ImageIcon, or null if the path was invalid. */ protected static ImageIcon createImageIcon(String path, String description) { java.net.URL imgURL = DocImageAction.class.getResource(path); if (imgURL != null) { return new ImageIcon(imgURL, description); } else { System.err.println("Couldn't find file: " + path); return null; } } }