package notepad;
import java.awt.BorderLayout;
import java.awt.Component;
import javax.swing.ButtonGroup;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JFrame;
import javax.swing.JMenuBar;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JRadioButtonMenuItem;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Date;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
public class JNotepad extends JFrame implements Runnable, ActionListener, MouseListener, CaretListener
{
private static final long serialVersionUID = 1L;
private JPanel jContentPane, jStatusPanel;
private JScrollPane jScrollNotepadPane;
private JMenuBar jMenuBar;
private JMenu jMenuFile, jMenuEdit, jMenuFormat, jMenuList;
private JMenuItem jMenuNew, jMenuOpen, jMenuSave, jMenuAsSave, jMenuExit, jMenuFont;
private JMenuItem jMenuCut, jMenuCopy, jMenuPaste, jMenuSelectAll, jMenuFind, jMenuDate;
private JCheckBoxMenuItem jMenuWrap;
private JRadioButtonMenuItem jRadioItem;
private ButtonGroup group = new ButtonGroup();
private JLabel jLabelFile, jLabelDate, jLabelLines;
private JTextArea jNotepad;
private JFileChooser fileChooser;
private File fileInfo;
private Find findText;
private SetFont fontText;
private StringBuilder sbTitle = new StringBuilder("无标题 - 记事本 ");
private StringBuilder sbText = new StringBuilder();
private JMenuBar getJMainBar()
{
if (jMenuBar == null)
{
jMenuBar = new JMenuBar();
jMenuBar.add(getJMenuFile());
jMenuBar.add(getJMenuEdit());
jMenuBar.add(getJMenuFormat());
jMenuList = new JMenu("最近访问的文件(L)");
jMenuList.setMnemonic('L');
jMenuBar.add(jMenuList);
}
return jMenuBar;
}
@SuppressWarnings("deprecation")
private JMenu getJMenuFile()
{
if (jMenuFile == null)
{
jMenuFile = new JMenu("文件(F)");
jMenuFile.setMnemonic('F');
jMenuNew = new JMenuItem("新建(N)");
jMenuNew.setMnemonic('N');
jMenuFile.add(jMenuNew).addActionListener(this);
jMenuOpen = new JMenuItem("打开(O)");
jMenuOpen.setMnemonic('O');
jMenuFile.add(jMenuOpen).addActionListener(this);
jMenuSave = new JMenuItem("保存(S)");
jMenuSave.setMnemonic('S');
jMenuSave.setEnabled(false);
jMenuFile.add(jMenuSave).addActionListener(this);
jMenuAsSave = new JMenuItem("另存为(A)");
jMenuAsSave.setMnemonic('A');
jMenuFile.add(jMenuAsSave).addActionListener(this);
jMenuFile.addSeparator();
jMenuExit = new JMenuItem("退出(X)");
jMenuExit.setMnemonic('X');
jMenuFile.add(jMenuExit).addActionListener(this);
}
return jMenuFile;
}
private JMenu getJMenuEdit()
{
if (jMenuEdit == null)
{
jMenuEdit = new JMenu("编辑(E)");
jMenuEdit.setMnemonic('E');
jMenuCut = new JMenuItem("剪切(T)");
jMenuCut.setMnemonic('T');
jMenuEdit.add(jMenuCut).addActionListener(this);
jMenuCopy = new JMenuItem("复制(C)");
jMenuCopy.setMnemonic('C');
jMenuEdit.add(jMenuCopy).addActionListener(this);
jMenuPaste = new JMenuItem("粘贴(P)");
jMenuPaste.setMnemonic('P');
jMenuEdit.add(jMenuPaste).addActionListener(this);
jMenuSelectAll = new JMenuItem("全选(A)");
jMenuSelectAll.setMnemonic('A');
jMenuEdit.add(jMenuSelectAll).addActionListener(this);
jMenuEdit.addSeparator();
jMenuFind = new JMenuItem("查找/替换(F)");
jMenuFind.setMnemonic('F');
jMenuEdit.add(jMenuFind).addActionListener(this);
jMenuEdit.addSeparator();
jMenuDate = new JMenuItem("时间/日期(D)");
jMenuDate.setMnemonic('D');
jMenuEdit.add(jMenuDate).addActionListener(this);
}
return jMenuEdit;
}
private JMenu getJMenuFormat()
{
if (jMenuFormat == null)
{
jMenuFormat = new JMenu("格式(O)");
jMenuFormat.setMnemonic('O');
jMenuWrap = new JCheckBoxMenuItem("自动换行(W)", true); // jMenuWrap.setState(true);
jMenuWrap.setMnemonic('W');
jMenuFormat.add(jMenuWrap).addActionListener(this);
jMenuFont = new JMenuItem("字体(F)");
jMenuFont.setMnemonic('F');
jMenuFormat.add(jMenuFont).addActionListener(this);
}
return jMenuFormat;
}
private JPanel getJStatusPanel()
{
if (jStatusPanel == null)
{
jLabelFile = new JLabel(" ");
jLabelDate = new JLabel(" ");
jLabelLines = new JLabel("总行数 1");
GridLayout gridLayout = new GridLayout();
gridLayout.setRows(1);
jStatusPanel = new JPanel();
jStatusPanel.setLayout(gridLayout);
jStatusPanel.add(jLabelFile, null);
jStatusPanel.add(jLabelDate, null);
jStatusPanel.add(jLabelLines, null);
}
return jStatusPanel;
}
private JScrollPane getJScrollNotepadPane()
{
if (jScrollNotepadPane == null)
{
jScrollNotepadPane = new JScrollPane();
jNotepad = new JTextArea();
jNotepad.setLineWrap(true); // 设置自动换行
jNotepad.setWrapStyleWord(true);
jNotepad.addCaretListener(this);
jScrollNotepadPane.setViewportView(jNotepad);
}
return jScrollNotepadPane;
}
public static void main(String[] args)
{
JNotepad notepad = new JNotepad();
Thread thread = new Thread(notepad);
thread.run();
thread.start();
}
public JNotepad()
{
this.setJMenuBar(getJMainBar());
this.setContentPane(getJContentPane());
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setBounds(100,100, 800, 560);
this.setVisible(true);
this.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
toFileList(false);
}
});
toFileList(true);
fileChooser = new JFileChooser(); // 创建文件对话框的对象
fileChooser.setSize(400, 300);
}
private JPanel getJContentPane()
{
if (jContentPane == null)
{
jContentPane = new JPanel();
jContentPane.setLayout(new BorderLayout());
jContentPane.add(getJStatusPanel(), BorderLayout.SOUTH);
jContentPane.add(getJScrollNotepadPane(), BorderLayout.CENTER);
}
return jContentPane;
}
/**
* 读取或写入最近访问的文件的路径。
* @param flag:True 表示读取,False 表示写入。
*/
private void toFileList(boolean flag)
{
File fileList = new File("notepad//FileList.txt");
try
{
if(flag)
{
if(fileList.exists())
{
String line = null; // null 不能替换为 "" 。
FileReader fr = new FileReader(fileList);
BufferedReader br = new BufferedReader(fr);
while((line = br.readLine()) != null)
{
jRadioItem = new JRadioButtonMenuItem(line);
group.add(jRadioItem);
jMenuList.add(jRadioItem).addMouseListener(this);
}
br.close();
fr.close();
}
}
else
{
if(!fileList.exists())
fileList.createNewFile();
FileWriter fw = new FileWriter(fileList);
BufferedWriter bw = new BufferedWriter(fw);
for(Component item : jMenuList.getMenuComponents())
{
bw.write(((JRadioButtonMenuItem)item).getText());
bw.newLine();
}
bw.close();
fw.close();
}
}
catch(IOException ie)
{
ie.printStackTrace();
}
}
/**
* 读取选定文件的内容。
* @param file:选定的文件的对象。
*/
private void toFileReader(File file)
{
try
{
FileReader fr = new FileReader(fileInfo = file);
BufferedReader br = new BufferedReader(fr);
jNotepad.read(br, null); // 读取所有字符。
br.close();
fr.close();
sbTitle.delete(0, sbTitle.length());
sbTitle.append(fileInfo.getName());
sbTitle.append(" ");
this.setTitle(null);
jMenuSave.setEnabled(true);
jNotepad.setCaretPosition(1); // 更新总行数。
}
catch(IOException ie)
{
ie.printStackTrace();
}
}
/**
* 写入当前文本的内容。
* @param file:选定的文件的对象。
*/
private void toFileWriter(File file)
{
try
{
FileWriter fw = new FileWriter(file);
BufferedWriter bw = new BufferedWriter(fw);
jNotepad.write(bw); // 逐行写入。
bw.close();
fw.close();
}
catch(IOException ie)
{
ie.printStackTrace();
}
}
public void run()
{
while(true)
{
try
{
if (this.getTitle().length() < sbTitle.length())
this.setTitle(sbTitle.substring(0, this.getTitle().length() + 1));
else
{
sbTitle.append(sbTitle.charAt(0));
this.setTitle(sbTitle.deleteCharAt(0).toString());
}
jLabelDate.setText(String.format("%1$tA %1$tB %1$td %1$tY, %1$tp %1$tl:%1$tM:%1$tS", new Date()));
if(fileInfo != null && fileInfo.exists())
{
sbText.append("文件属性:");
if (!fileInfo.canWrite() && fileInfo.isHidden())
sbText.append("只读,隐藏");
else if (!fileInfo.canWrite())
sbText.append("只读");
else if (fileInfo.isHidden())
sbText.append("隐藏");
else
sbText.append("正常");
}
else
sbText.append("文件不存在");
jLabelFile.setText(sbText.toString());
sbText.delete(0, sbText.length());
Thread.sleep(200);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
public void actionPerformed(ActionEvent e)
{
if (e.getSource().equals(jMenuExit))
System.exit(0);
else if (e.getSource().equals(jMenuNew))
{
if(JOptionPane.showConfirmDialog(this, "当前文本内容以改变,是否新建?", "记事本", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE) == 0)
{
sbTitle.delete(0, sbTitle.length());
sbTitle.append("无标题 - 记事本 ");
this.setTitle(null);
}
}
else if (e.getSource().equals(jMenuOpen))
{
if(fileChooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION)
{
toFileReader(fileChooser.getSelectedFile());
jRadioItem = new JRadioButtonMenuItem(fileInfo.getPath());
group.add(jRadioItem);
jMenuList.add(jRadioItem).addMouseListener(this);
}
}
else if(e.getSource().equals(jMenuSave))
{
if(fileInfo.canWrite()) // 文件属性是否为只读
toFileWriter(fileInfo);
else
JOptionPane.showMessageDialog(this, String.format("文件“%s”的属性为只读,请先更改其属性。", fileInfo.getPath()));
}
else if(e.getSource().equals(jMenuAsSave))
{
if(fileChooser.showSaveDialog(this) == JFileChooser.APPROVE_OPTION)
{
File file = fileChooser.getSelectedFile();
if(file.exists())
{
if(JOptionPane.showConfirmDialog(this, String.format("文件“%s”已存在,要替换它吗?", file.getPath()), "记事本", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE) == 1)
return;
if(!file.canWrite())
{
JOptionPane.showMessageDialog(this, String.format("文件“%s”的属性为只读,请先更改其属性。", file.getPath()));
return;
}
}
toFileWriter(file);
}
}
else if(e.getSource().equals(jMenuFind))
{
if(findText == null)
findText = new Find(this, jNotepad);
findText.setVisible(true);
}
else if(e.getSource().equals(jMenuFont))
{
if(fontText == null)
fontText = new SetFont(this, jNotepad);
fontText.setVisible(true);
}
else if(e.getSource().equals(jMenuCut))
{
jNotepad.cut();
}
else if(e.getSource().equals(jMenuCopy))
{
jNotepad.copy();
}
else if(e.getSource().equals(jMenuPaste))
{
jNotepad.paste();
}
else if(e.getSource().equals(jMenuSelectAll))
{
jNotepad.selectAll();
}
else if(e.getSource().equals(jMenuDate))
{
jNotepad.insert(String.format("%1$tF %1$tT", new Date()), jNotepad.getSelectionStart());
}
else if(e.getSource().equals(jMenuWrap))
{
jNotepad.setLineWrap(!jNotepad.getLineWrap()); // 自动换行
}
}
public void mouseReleased(MouseEvent e) // 处理鼠标释放事件
{
JRadioButtonMenuItem item = (JRadioButtonMenuItem)e.getSource();
switch(e.getButton()) // 鼠标右键。
{
case 1:
File file = new File(item.getText());
if(file.exists())
toFileReader(file);
else
JOptionPane.showMessageDialog(this, String.format("文件“%s”不存在!", item.getText()));
break;
case 3:
if(JOptionPane.showConfirmDialog(this, String.format("确实要删除“%s”吗?", item.getText()), "记事本", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE) == 0)
jMenuList.remove(item);
break;
default:
break;
}
}
public void mouseClicked(MouseEvent e)
{}
public void mouseEntered(MouseEvent e)
{}
public void mouseExited(MouseEvent e)
{}
public void mousePressed(MouseEvent e)
{}
public void caretUpdate(CaretEvent e)
{
jLabelLines.setText(String.format("总行数 %d", jNotepad.getLineCount()));
}
}