일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
Tags
- Eclipse
- css
- 자바스크립트
- MYSQL
- 자바빈
- thymeleaf
- html
- 자바
- java
- git
- spring boot
- 초보 개발자
- 여러 종류의 사용자 정의 함수
- chart.js
- @requstbody
- JavaScript
- github
- vscode
- chart.js 라이브러리
- ui인터페이스
- open in browser
- vsc
- 상태값 저장 유지
- jsp
- IndexedDB
- 게시판
- resutful api
- tomcat
- 데이터 시각화
- 실시간 상태값 저장
Archives
- Today
- Total
수월한 IT
swing으로 만들어본 멀티 메모장 #2/2 본문
728x90
안녕하세요 IT여행자입니다.
이번 여행지는 swing으로 만들어본 멀티 메모장 두 번째 부분입니다.
첫 번째 영상에서도 언급한 것처럼 자바 GUI를 사용한 프로그램이라는 인터페이스가 많이 사용되는 인터페이스가 아니지만, 진입 장벽이 높지 않으며, 웹 인터페이스처럼 다양한 언어를 사용하지 않아도 만들어 볼 수 있는 프로그램이기에 두 편에 걸쳐 만들어 봤습니다.
개발에 필요한 보다 자세한 내용들은 영상을 참조하시면서 하나씩 개발해 보시는 걸 추천드립니다.
1편에서는 레이아웃에 관한 내용을 다루었고, 2편에서는 BACK-END 부분을 다루었습니다.
주요 내용은 아래와 같습니다.
- MemoVo.java : 하나의 메모 내용을 저장하는 Value Object
- config.xml : mybatis를 사용하기 위한 환결 설정
- memo.xml : 메모와 관련된 CRUD 매퍼 파일
- Factory.java : mybatis의 환결설정 파일과 매퍼를 읽어 들여 실제로 Sqlite 데이터베이스를 사용할 수 있게 해주는 클래스
- Content.java : 메모 목차를 지정하는 인터널 프레임
- Editor.java : 메모장을 작성할 때 사용되는 인터널 프레임
- Main.java : 메모장의 메인 프레임
영상에서 작성한 코드의 완성본을 하단에 적습니다.
MemoVo.java
하나의 메모 내용을 저장하는 클래스입니다.
package memo; public class MemoVo { int id; String nal; String subject; String doc; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getNal() { return nal; } public void setNal(String nal) { this.nal = nal; } public String getSubject() { return subject; } public void setSubject(String subject) { this.subject = subject; } public String getDoc() { return doc; } public void setDoc(String doc) { this.doc = doc; } }
config.xml
sqlite 데이터 베이스를 연결할 때 사용되는 정보들
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "https://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="UNPOOLED"> <property name="driver" value="org.sqlite.JDBC"/> <property name="url" value="jdbc:sqlite:db/memo.db"/> </dataSource> </environment> </environments> <mappers> <mapper resource="memo/myba/memo.xml"/> </mappers> </configuration>
memo.xml
메모장에 관한 CRUD 매퍼 파일
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "https://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="memo"> <insert id='insert' parameterType="memo.MemoVo"> insert into memo(nal, subject, doc) values(#{nal}, #{subject}, #{doc}) </insert> <update id='update' parameterType="memo.MemoVo"> update memo set subject = #{subject}, doc = #{doc} where id = #{id} </update> <delete id='delete' parameterType="Integer"> delete from memo where id = ${_parameter} </delete> <select id='content' resultType="memo.MemoVo"> select id, nal, subject from memo order by nal desc </select> <select id='last_row' resultType="Integer"> select last_insert_rowid() </select> <select id='select_one' parameterType="Integer" resultType="memo.MemoVo"> select id, nal, subject, doc from memo where id = #{_parameter} </select> </mapper>
Factory.java
Sqlite 데이터 베이스 연결 정보 객체
package memo.myba; import java.io.IOException; import java.io.Reader; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; public class Factory { private static SqlSessionFactory factory; static { try { Reader reader = Resources.getResourceAsReader("memo/myba/config.xml"); factory = new SqlSessionFactoryBuilder().build(reader); } catch (IOException e) { e.printStackTrace(); } } public static SqlSessionFactory getFactory() { return factory; } }
Content.java
메모장들의 제목 표시 인터널 프레임
package memo; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Point; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.ArrayList; import java.util.List; import javax.swing.DefaultListModel; import javax.swing.JInternalFrame; import javax.swing.JList; import javax.swing.JOptionPane; import javax.swing.JScrollPane; import javax.swing.event.InternalFrameAdapter; import javax.swing.event.InternalFrameEvent; import org.apache.ibatis.session.SqlSession; import memo.myba.Factory; public class Content extends JInternalFrame { Main main; // 메모목차클래스에서 Main객체의 멤버들을 접근하기 위한 요소 List<Integer> idList; // 메모의 id protected DefaultListModel<String> model; // 메모제목들 SqlSession session; // mybatis를 사용하기 위한 객체 private JScrollPane scrollPane; private JList subjectList; /** * Create the frame. */ public Content(Main main) { super("메모목차", false, true, false, false); this.main = main; addInternalFrameListener(new InternalFrameAdapter() { @Override public void internalFrameClosed(InternalFrameEvent e) { main.getDesktopPane().remove(Content.this); main.content= null; } }); setBounds(100, 100, 291, 433); getContentPane().add(getScrollPane(), BorderLayout.CENTER); idList = new ArrayList<Integer>(); makeAllSubject(); setVisible(true); } public void makeAllSubject() { if (session == null) { session = Factory.getFactory().openSession(); } List<MemoVo> list = session.selectList("memo.content"); for (MemoVo m : list) { String temp = String.format("%-12s %s", m.getNal(), m.getSubject()); model.addElement(temp); idList.add(m.getId()); } session.close(); session = null; } public void load(int[] indexs) { for (int i : indexs) { int id = idList.get(i); Editor ed = null; // 기존창이 있는지 체크 Component[] comps = main.getDesktopPane().getComponents(); boolean exist = false; for (Component comp : comps) { if (comp instanceof Editor) { ed = (Editor) comp; if (ed.getId() == id) { exist = true; break; } } } if (exist) { ed.toFront(); } else { //에디터창의 기본 위치를 지정하기 위해 int x = (i * 22); int y = (i * 22); Point point = new Point(x, y); getData(idList.get(i), point); } } } public void getData(int id, Point point) { if (session == null) { session = Factory.getFactory().openSession(); } MemoVo vo = session.selectOne("memo.select_one", id); Editor ed = new Editor(main); ed.setData(vo); ed.setLocation(point); main.getDesktopPane().add(ed); ed.toFront(); session.close(); session = null; } public void delete(int index) { if (session == null) { session = Factory.getFactory().openSession(); } int yn = JOptionPane.showConfirmDialog(Content.this, "정말 삭제하시겠습니까?", "데이터 삭제", JOptionPane.YES_NO_OPTION); if (yn == JOptionPane.OK_OPTION) { int id = idList.get(index); int cnt = session.delete("memo.delete", id); if (cnt > 0) { session.commit(); model.remove(index); idList.remove(index); Component[] comps = main.getDesktopPane().getComponents(); for (Component comp : comps) { if (comp instanceof Editor) { Editor ed = (Editor) comp; if (ed.getId() == id) { main.getDesktopPane().remove(ed); main.getDesktopPane().updateUI(); } } } } session.close(); session = null; } } protected JScrollPane getScrollPane() { if (scrollPane == null) { scrollPane = new JScrollPane(); scrollPane.setViewportView(getSubjectList()); } return scrollPane; } protected JList getSubjectList() { if (subjectList == null) { model = new DefaultListModel<String>(); subjectList = new JList(model); subjectList.addKeyListener(new KeyAdapter() { @Override public void keyReleased(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_ENTER) { int[] indexs = subjectList.getSelectedIndices(); load(indexs); } } }); subjectList.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { if (e.isMetaDown()) { // 마우스 우클릭하여 삭제 int index = subjectList.locationToIndex(e.getPoint()); if (index == -1) return; subjectList.setSelectedIndex(index); delete(index); } else if (e.getClickCount() == 2) { int[] indexs = subjectList.getSelectedIndices(); load(indexs); } else { int index = subjectList.getSelectedIndex(); if (index == -1) return; int id = idList.get(index); Component[] comps = main.getDesktopPane().getComponents(); for (Component comp : comps) { if (comp instanceof Editor) { Editor ed = (Editor) comp; if (ed.getId() == id) { ed.toFront(); break; } } } } } }); } return subjectList; } }
Editor.java
메모 작성과 관련된 인터널 프레임
package memo; import java.awt.BorderLayout; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; import javax.swing.JInternalFrame; import javax.swing.JList; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import javax.swing.event.InternalFrameAdapter; import javax.swing.event.InternalFrameEvent; import org.apache.ibatis.session.SqlSession; import memo.myba.Factory; public class Editor extends JInternalFrame implements DocumentListener{ int id=0;// 에디터 자신의 아이디 boolean editFlag=false; // 현재 편집 상태 boolean load = false; //처음 로딩된 경우 SqlSession session; Main main; private JScrollPane scrollPane; private JTextArea textArea; /** * Create the frame. */ public Editor(Main m) { super("새 메모", true, true, true, true); this.main = m; setVisible(true); addMouseListener(new MouseAdapter() { @Override public void mouseEntered(MouseEvent e) { activate(); } }); addInternalFrameListener(new InternalFrameAdapter() { @Override public void internalFrameActivated(InternalFrameEvent e) { activate(); } }); setBounds(100, 100, 450, 300); getContentPane().add(getScrollPane(), BorderLayout.CENTER); } public void activate() { //열러진 메모장의 id목록을 가져옴. if(main.getContent() == null) return; List<Integer> idList = main.getContent().idList; //메모목차(Content)에 들어있는 JLIST 항목들 JList jlist = main.getContent().getSubjectList(); for(int i=0; i<idList.size() ; i++) { int id = idList.get(i); if(id == this.id) { jlist.setSelectedIndex(i); } } } public void setId(int id) { this.id = id; } public int getId() { return id; } public void setData(MemoVo vo) { this.setId(vo.getId()); this.setTitle(vo.getSubject()); this.getTextArea().setText(vo.getDoc()); } public void save() { if(session == null) { session = Factory.getFactory().openSession(); } String doc = getTextArea().getText(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); MemoVo vo = new MemoVo(); //엔터없이 한줄인 경우 int length = doc.indexOf("\n"); if(length == -1) { length = doc.length(); } // 제목으로 사용할 문자열을 15자 아내로 length = (length<15)? length : 15; // 테이블에 저장할 데이터를 vo 객체에 담음. String subject = doc.substring(0,length); vo.setNal(sdf.format(new Date())); vo.setId(id); vo.setSubject(subject); vo.setDoc(doc); try { int cnt = 0; // 새글인 경우 insert if(this.id == 0) { cnt = session.insert("memo.insert", vo); // 저장에 성공했다면 저장된 마지막 행번호를 가져와 // 에디터창의 id로 사용하고 // 메모 목차 설정, 에디터창 타이틀 설정 if(cnt>0) { this.id = session.selectOne("memo.last_row"); String temp = String.format("%-12s %s",vo.getNal(), subject); if(main.getContent() != null) { main.getContent().model.addElement(temp); main.getContent().idList.add(this.id); } setTitle(subject); } }else { // 수정인 경우 update cnt = session.update("memo.update", vo); setTitle(subject); String temp = String.format("%-12s %s",vo.getNal(), subject); int index = main.getContent().idList.indexOf(this.id); main.getContent().model.set(index, temp); } if(cnt>0) { session.commit(); editFlag=false; }else { session.rollback(); throw new Exception("저장되지 않았습니다."); } }catch(Exception ex) { ex.printStackTrace(); } session.close(); session = null; } public void changed() { if( !editFlag && load) { setTitle(getTitle() + " *"); editFlag = true; } load = true; // 이미로딩되었다. } protected JScrollPane getScrollPane() { if (scrollPane == null) { scrollPane = new JScrollPane(); scrollPane.setViewportView(getTextArea()); } return scrollPane; } protected JTextArea getTextArea() { if (textArea == null) { textArea = new JTextArea(); textArea.getDocument().addDocumentListener(this); textArea.addMouseListener(new MouseAdapter() { @Override public void mouseEntered(MouseEvent e) { activate(); } }); textArea.addKeyListener(new KeyAdapter() { @Override public void keyPressed(KeyEvent e) { // Ctrl +s 키를 누를 때 if(e.isControlDown() && e.getKeyCode()== KeyEvent.VK_S) { save(); } } }); } return textArea; } @Override public void insertUpdate(DocumentEvent e) { // TODO Auto-generated method stub changed(); } @Override public void removeUpdate(DocumentEvent e) { // TODO Auto-generated method stub changed(); } @Override public void changedUpdate(DocumentEvent e) { // TODO Auto-generated method stub changed(); } }
Main.java
메모장의 메인 프레임
package memo; import java.awt.BorderLayout; import java.awt.Component; import java.awt.EventQueue; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import javax.swing.JDesktopPane; import javax.swing.JFrame; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.border.EmptyBorder; public class Main extends JFrame { protected Content content; private JPanel contentPane; private JMenuBar menuBar; private JMenu mnNewMenu; private JMenuItem mntmNewMenuItem; private JMenuItem mntmNewMenuItem_1; private JMenuItem mntmNewMenuItem_2; private JMenuItem mntmNewMenuItem_3; private JMenuItem mntmNewMenuItem_4; private JDesktopPane desktopPane; /** * Launch the application. */ public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { public void run() { try { Main frame = new Main(); frame.setVisible(true); } catch (Exception e) { e.printStackTrace(); } } }); } /** * Create the frame. */ public void exit() { int yn = JOptionPane.showConfirmDialog(Main.this, "프로그매을 종료하시겠습니까?", "프로그램 종료", JOptionPane.YES_NO_OPTION); if(yn == JOptionPane.OK_OPTION) { setDefaultCloseOperation(EXIT_ON_CLOSE); System.exit(0); }else { setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); } } public Main() { addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { exit(); } }); setTitle("메모장"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setBounds(100, 100, 761, 460); setJMenuBar(getMenuBar_1()); contentPane = new JPanel(); contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); setContentPane(contentPane); contentPane.setLayout(new BorderLayout(0, 0)); contentPane.add(getDesktopPane(), BorderLayout.CENTER); } public Content getContent() { return content; } protected JMenuBar getMenuBar_1() { if (menuBar == null) { menuBar = new JMenuBar(); menuBar.add(getMnNewMenu()); } return menuBar; } protected JMenu getMnNewMenu() { if (mnNewMenu == null) { mnNewMenu = new JMenu("관리"); mnNewMenu.add(getMntmNewMenuItem()); mnNewMenu.add(getMntmNewMenuItem_1()); mnNewMenu.add(getMntmNewMenuItem_2()); mnNewMenu.add(getMntmNewMenuItem_3()); mnNewMenu.add(getMntmNewMenuItem_4()); } return mnNewMenu; } protected JMenuItem getMntmNewMenuItem() { if (mntmNewMenuItem == null) { mntmNewMenuItem = new JMenuItem("목차보기"); mntmNewMenuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if(content == null) { content = new Content(Main.this); contentPane.add(content,BorderLayout.WEST); } } }); } return mntmNewMenuItem; } protected JMenuItem getMntmNewMenuItem_1() { if (mntmNewMenuItem_1 == null) { mntmNewMenuItem_1 = new JMenuItem("새로만들기"); mntmNewMenuItem_1.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { Editor ed = new Editor(Main.this); desktopPane.add(ed); ed.toFront(); } }); } return mntmNewMenuItem_1; } protected JMenuItem getMntmNewMenuItem_2() { if (mntmNewMenuItem_2 == null) { mntmNewMenuItem_2 = new JMenuItem("저장"); mntmNewMenuItem_2.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { Editor ed = (Editor) desktopPane.getSelectedFrame(); ed.save(); } }); } return mntmNewMenuItem_2; } protected JMenuItem getMntmNewMenuItem_3() { if (mntmNewMenuItem_3 == null) { mntmNewMenuItem_3 = new JMenuItem("모두저장"); mntmNewMenuItem_3.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { Component[] comps = desktopPane.getComponents(); for(Component comp : comps) { if(comp instanceof Editor) { Editor ed = (Editor)comp; ed.save(); } } } }); } return mntmNewMenuItem_3; } protected JMenuItem getMntmNewMenuItem_4() { if (mntmNewMenuItem_4 == null) { mntmNewMenuItem_4 = new JMenuItem("종료"); mntmNewMenuItem_4.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { exit(); } }); } return mntmNewMenuItem_4; } protected JDesktopPane getDesktopPane() { if (desktopPane == null) { desktopPane = new JDesktopPane(); } return desktopPane; } }
'BOOKS > 수월한 Java' 카테고리의 다른 글
추상 클래스 (0) | 2024.04.07 |
---|---|
인터페이스 (0) | 2024.04.07 |
swing으로 만들어본 멀티 메모장 #1/2 (0) | 2023.03.01 |
List에 담긴 정보를 배열로 변환하기 (0) | 2022.11.27 |
이클립스에서 Data Management로 MySQL 연결하기 (0) | 2021.10.30 |