레지스트 간단예제

package swt.registry;

import java.util.prefs.BackingStoreException;
import java.util.prefs.Preferences;

public class RegistryUserTest {
	// 주어진 노드에 키를 포함하고 있는지 체크한다.
	public static boolean contains(Preferences node, String key) {
		return node.get(key, null) != null;
	}

	public static void main(String args[]) throws BackingStoreException {
		
		Preferences userRootPrefs = Preferences.userRoot();
		//레지스트리에 시스템 Root못건드림 Preferences systemRootPrefs = Preferences.systemRoot();
		
		String key = "xname";
		if (contains(userRootPrefs, key)) {
			String value = userRootPrefs.get(key, "");	//있으면 있는거 출력
			System.out.println("xname : " + value);
		} else {
			String value = "upark";
			userRootPrefs.put(key, value);	//없으면 만들어 set
			System.out.println("create uname : " + value);
		}
	}
}

HKEY_CLASSES_ROOT레지스트리에 http\\shell\\open\\command  에 보면 default 브라우저 설정

package swt.registry;

import java.util.Enumeration;

import com.ice.jni.registry.NoSuchValueException;
import com.ice.jni.registry.RegStringValue;
import com.ice.jni.registry.Registry;
import com.ice.jni.registry.RegistryException;
import com.ice.jni.registry.RegistryKey;

public class JNIRegistryTest {
	private static final String REG_SWT_PARAMS = "Software\\RnDClub\\Client\\Params";

	public static final String REG_AMS_KEY_CLASSNAME = "AMS";

	public static final String REG_AMS_KEY_ID = "id";

	public static final String REG_AMS_KEY_DIR_HOME = "home";

	public static final String REG_AMS_KEY_DB_DRIVER = "dbDriver";

	public static final String REG_AMS_KEY_DB_URL = "dbUrl";

	public static final String REG_AMS_KEY_DB_USER = "dbUser";

	public static final String REG_AMS_KEY_DB_PASS = "dbPass";

	private static RegistryKey amsClientParamsRkey = null;

	public static String getDefaultBrowserCommand() {
		String value = null;
		String name = "http\\shell\\open\\command";
		try {
			RegistryKey rkey = Registry.HKEY_CLASSES_ROOT.createSubKey(name,
					"", RegistryKey.ACCESS_ALL);
			// System.out.println("rkey : " + rkey);
			value = rkey.getStringValue("");
		} catch (RegistryException e) {
			e.printStackTrace();
		}
		return (value);
	}

	public static RegistryKey getCurrentUserRegistryKey(String name) {
		RegistryKey rkey = null;
		try {
			rkey = Registry.HKEY_CURRENT_USER.createSubKey(name,
					"", RegistryKey.ACCESS_ALL);
			if (rkey.wasCreated() == true) {
				System.out.println("'" + name + "' rkey was created...");
			}
		} catch (RegistryException e) {
			e.printStackTrace();
		}
		return (rkey);
	}

	public static String getAmsClientParameter(String name) {
		String value = null;
		try {
			if (amsClientParamsRkey == null) {
				amsClientParamsRkey = getCurrentUserRegistryKey(REG_SWT_PARAMS);
			}
			value = amsClientParamsRkey.getStringValue(name);
		} catch (RegistryException e) {
			e.printStackTrace();
		}
		return (value);
	}

	public static void putAmsClientParameter(String name, String str) {
		try {
			if (amsClientParamsRkey == null) {
				amsClientParamsRkey = getCurrentUserRegistryKey(REG_SWT_PARAMS);
			}
			RegStringValue value = new RegStringValue(amsClientParamsRkey,
					name, str);
			amsClientParamsRkey.setValue(name, value);
		} catch (NoSuchValueException e) {
			e.printStackTrace();
		} catch (RegistryException e) {
			e.printStackTrace();
		}
	}

	public static void test() {
		try {
			if (amsClientParamsRkey == null) {
				amsClientParamsRkey = getCurrentUserRegistryKey(REG_SWT_PARAMS);
			}
			System.out.println("getFullName : "
					+ amsClientParamsRkey.getFullName());
			System.out.println("getMaxSubkeyLength : "
					+ amsClientParamsRkey.getMaxSubkeyLength());
			System.out.println("getMaxValueDataLength : "
					+ amsClientParamsRkey.getMaxValueDataLength());
			System.out.println("getMaxValueNameLength : "
					+ amsClientParamsRkey.getMaxValueNameLength());
			System.out.println("getName : " + amsClientParamsRkey.getName());
			System.out.println("getNumberSubkeys : "
					+ amsClientParamsRkey.getNumberSubkeys());
			System.out.println("getNumberValues : "
					+ amsClientParamsRkey.getNumberValues());

			Enumeration e = amsClientParamsRkey.valueElements();
			while (e.hasMoreElements()) {
				String key = (String) e.nextElement();
				String val = amsClientParamsRkey.getStringValue(key);
				System.out.println("key : " + key + ", val : " + val);
			}
			/*
			 * System.out.println(); for (int i = 0; i <
			 * amsClientParamsRkey.getNumberValues(); i++) { String key =
			 * amsClientParamsRkey.regEnumValue(i); String val =
			 * amsClientParamsRkey.getStringValue(key); System.out.println("[" +
			 * i + "] key : " + key + ", val : " + val); }
			 */
		} catch (RegistryException e) {
			e.printStackTrace();
		}
	}

	public static void main(String args[]) {
		test();

		putAmsClientParameter("server", "127.0.0.1");
		String value = getAmsClientParameter("server");
		System.out.println("server : " + value);

		putAmsClientParameter("dbUrl",
				"jdbc:oracle:thin:@127.0.0.1:1521:opendb");
		value = getAmsClientParameter("dbUrl");
		System.out.println("dbUrl : " + value);

		putAmsClientParameter("workspace", "D:\\workspace");
		value = getAmsClientParameter("workspace");
		System.out.println("workspace : " + value);

		putAmsClientParameter("home", "D:\\Temp\\ams_client");
		value = getAmsClientParameter("home");
		System.out.println("home : " + value);

		putAmsClientParameter("id", "ywoopark");
		value = getAmsClientParameter("id");
		System.out.println("id : " + value);

		value = getDefaultBrowserCommand();
		System.out.println("ie : " + value);
	}
}

위 경우는 현재 32bit만 가능하며 32bit인경우 registry.jar,ICE_JNIRegistry.dll 가 필요하며

registry.jar에 Native에 ICE_JNIRegistry.dll를 추가 설정해주어야 가능하다.

'IT > RCP' 카테고리의 다른 글

[RCP] 개발 환경설정  (0) 2020.12.20
[RCP] 사전 준비 및 주요 용어  (0) 2020.12.20
[SWT] Win32 OLE  (0) 2020.12.19
[SWT] 클립보드  (0) 2020.12.19
[SWT] Drag & Drop  (0) 2020.12.19

이클립스에서 OLEFrame으로 OLE객체를 내장할 수 있다.

여기서 OLE란 Object Link Editer로 MS의 OCX, ActiveX 컨트롤를 말한다.

먼저 주요클래스를 확인하여 보자

 

[Win32 주요 클래스]

객체를 생성하는 방법, 그리고 객체를 사용하는 방법을 알아보자

먼저 간단하게 MS워드, 익스플로러, 엑셀, 미디어플레이어 을 띄우는 방법을 알아보자

참고로 oleviewer라고 Visual Studio에서 나온것이 있는데, OLE를 사용하기 위한 API문서처럼 메소드들을 제공한다.

oleview_setup&amp;dll.zip
0.66MB

OLE를 사용하기에 위해 주요클래스 중 몇가지를 살펴보자

OleClientSite : OLE 도큐먼트를 관리하기위함.
  -편집기 생성, 토큐먼트 활성/비활성, 변경내용저장
 OleControlSite : OleClientSite의 상속받아 액티브X컨트롤를 관리
  -컨트롤 이벤트 제공, 변경되었음을 제공, 폰트 배경색 등 변경가능
 OleAutomation : IDispatch 인터페이스 지원,메소드 사용(매개변수는 Variant형태 전달)
   setProperty
   invoke 
   invokeNoReply  

OLE를 사용하여 객체 생성예제

package swt.ole;

import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.ole.win32.OLE;
import org.eclipse.swt.ole.win32.OleClientSite;
import org.eclipse.swt.ole.win32.OleFrame;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

public class OLE_Test {

	public static void main(String[] args) {
		
		Display display = new Display();
		Shell shell = new Shell(display);
		shell.setLayout(new FillLayout());
		shell.setText("SWT Ole Test");
		OleClientSite clientSite;
		//OleControlSite oleControlSite;
		OleFrame frame = new OleFrame(shell, SWT.NONE);
		clientSite = new OleClientSite(frame, SWT.NONE,"Word.Document");
		clientSite.doVerb(OLE.OLEIVERB_INPLACEACTIVATE);
		//각 OLE객체를 생성하는 방법1~4
		/*
		//1.1 MS Word 띄우기:OLE객체 -ProgramID
		clientSite = new OleClientSite(frame, SWT.NONE,"Word.Document");
		*/
		/*
		//1.2 MS Word 띄우기-MS워드파일로 띄우기 
		clientSite = new OleClientSite(frame, SWT.NONE,new File("d:\\test.doc"));
		*/
		/*
		//2.MS Excel 띄우기-ProgramID
		clientSite = new OleClientSite(frame, SWT.NONE,"Excel.Sheet");
		*/
		/*
		//3.익스플로러 띄우기-ProgramID
		clientSite = new OleClientSite(frame, SWT.NONE,"Shell.Explorer");
		*/
		//4.미디어 플레이어 띄우기
		//clientSite = new OleClientSite(frame, SWT.NONE,"WMPlayer.OCX");
		
		System.out.println("clientSite : " + clientSite.getProgramID());
		
		shell.setSize(640, 480);
		shell.open();
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch())
				display.sleep();
		}
		
		//oleAuto.dispose();
		display.dispose();
	}
}

여기서 주석으로 각각 막아 놓은것은 주요 OLE객체에 임. 1.2에서 파일을 통하여 OLE객체를 생성할 수도 있다.

파일을 통해 OLE객체를 생성한경우 객체에 ProgID를 추가적으로 알수 있다.

clientSite.getProgramID()

 

그럼 OLE객체의 메소드, Property등을 oleview.exe외 자바에서 추출하는 예제를 확인해보자

OleControlSite를 통하여 메소드들을 알수 있다.(너무 많아 자세히 보기 어렵긴하네요)

package swt.ole;

import java.io.File;

import org.eclipse.swt.SWT;
import org.eclipse.swt.internal.ole.win32.TYPEATTR;
import org.eclipse.swt.ole.win32.OLE;
import org.eclipse.swt.ole.win32.OleAutomation;
import org.eclipse.swt.ole.win32.OleClientSite;
import org.eclipse.swt.ole.win32.OleControlSite;
import org.eclipse.swt.ole.win32.OleFrame;
import org.eclipse.swt.ole.win32.OleFunctionDescription;
import org.eclipse.swt.ole.win32.OlePropertyDescription;
import org.eclipse.swt.widgets.Shell;

public class getOLEMethod {

	public static void main(String[] args) {
		/*
		 * if (args.length == 0) { System.out.println("Usage: java Main "); return; }
		 */
		Shell shell = new Shell();

		OleFrame frame = new OleFrame(shell, SWT.NONE);
		OleClientSite oleControlSite = new OleClientSite(frame, SWT.NONE, new File("d:\\test.doc"));
		String progID = oleControlSite.getProgramID();

		// 컨트롤은 프로그램 id를 통하여만 가져올수 있다.
		OleControlSite site = new OleControlSite(frame, SWT.NONE, progID);
		OleAutomation auto = new OleAutomation(site); // 각 메소드의 사용

		TYPEATTR typeattr = auto.getTypeInfoAttributes();

		if (typeattr != null) {

			// function기술시작
			if (typeattr.cFuncs > 0) {
				System.out.println("Functions for " + progID + ":");
			}
			
			for (int i = 0; i < typeattr.cFuncs; i++) {
				
				OleFunctionDescription data = auto.getFunctionDescription(i);
				String argList = "";
				
				int firstOptionalArgIndex = data.args.length - data.optionalArgCount;
				
				for (int j = 0; j < data.args.length; j++) {
					argList += "[";
					//옵션 항목기술
					if (j >= firstOptionalArgIndex) {
						argList += "optional, ";
					}
					//function항목명, type기술
					argList += getDirection(data.args[j].flags) + "] " + getTypeName(data.args[j].type) + " "
							+ data.args[j].name;
					//다음항목 , 표시
					if (j < data.args.length - 1) {
						argList += ", ";
					}
				}
				
				System.out.println(getInvokeKind(data.invokeKind) + " (id = " + data.id + ") : " + "Signature : "
						+ getTypeName(data.returnType) + " " + data.name + "(" + argList + ")" + " Description : "
						+ data.documentation + "Help File : " + data.helpFile + "");
			}

			//속성값 기술 시작
			if (typeattr.cVars > 0) {
				System.out.println(" ");
				System.out.println(" Variables for " + progID + " : ");
			}
			
			//속성값 기술목록출력
			for (int i = 0; i < typeattr.cVars; i++) {
				OlePropertyDescription data = auto.getPropertyDescription(i);
				System.out.println("PROPERTY (id = " + data.id + ") :" + "Name : " + data.name + "Type : "
													 + getTypeName(data.type) + "");
			}
		}

		auto.dispose();
		shell.dispose();
	}

	private static String getTypeName(int type) {
		switch (type) {
		case OLE.VT_BOOL:
			return "boolean";
		case OLE.VT_R4:
			return "float";
		case OLE.VT_R8:
			return "double";
		case OLE.VT_I4:
			return "int";
		case OLE.VT_DISPATCH:
			return "IDispatch";
		case OLE.VT_UNKNOWN:
			return "IUnknown";
		case OLE.VT_I2:
			return "short";
		case OLE.VT_BSTR:
			return "String";
		case OLE.VT_VARIANT:
			return "Variant";
		case OLE.VT_CY:
			return "Currency";
		case OLE.VT_DATE:
			return "Date";
		case OLE.VT_UI1:
			return "unsigned char";
		case OLE.VT_UI4:
			return "unsigned int";
		case OLE.VT_USERDEFINED:
			return "UserDefined";
		case OLE.VT_HRESULT:
			return "int";
		case OLE.VT_VOID:
			return "void";

		case OLE.VT_BYREF | OLE.VT_BOOL:
			return "boolean *";
		case OLE.VT_BYREF | OLE.VT_R4:
			return "float *";
		case OLE.VT_BYREF | OLE.VT_R8:
			return "double *";
		case OLE.VT_BYREF | OLE.VT_I4:
			return "int *";
		case OLE.VT_BYREF | OLE.VT_DISPATCH:
			return "IDispatch *";
		case OLE.VT_BYREF | OLE.VT_UNKNOWN:
			return "IUnknown *";
		case OLE.VT_BYREF | OLE.VT_I2:
			return "short *";
		case OLE.VT_BYREF | OLE.VT_BSTR:
			return "String *";
		case OLE.VT_BYREF | OLE.VT_VARIANT:
			return "Variant *";
		case OLE.VT_BYREF | OLE.VT_CY:
			return "Currency *";
		case OLE.VT_BYREF | OLE.VT_DATE:
			return "Date *";
		case OLE.VT_BYREF | OLE.VT_UI1:
			return "unsigned char *";
		case OLE.VT_BYREF | OLE.VT_UI4:
			return "unsigned int *";
		case OLE.VT_BYREF | OLE.VT_USERDEFINED:
			return "UserDefined *";
		}
		return "unknown " + type;
	}

	private static String getDirection(int direction) {
		String dirString = "";
		boolean comma = false;
		if ((direction & OLE.IDLFLAG_FIN) != 0) {
			dirString += "in";
			comma = true;
		}
		if ((direction & OLE.IDLFLAG_FOUT) != 0) {
			if (comma)
				dirString += ", ";
			dirString += "out";
			comma = true;
		}
		if ((direction & OLE.IDLFLAG_FLCID) != 0) {
			if (comma)
				dirString += ", ";
			dirString += "lcid";
			comma = true;
		}
		if ((direction & OLE.IDLFLAG_FRETVAL) != 0) {
			if (comma)
				dirString += ", ";
			dirString += "retval";
		}

		return dirString;
	}

	private static String getInvokeKind(int invKind) {
		switch (invKind) {
		case OLE.INVOKE_FUNC:
			return "METHOD";
		case OLE.INVOKE_PROPERTYGET:
			return "PROPERTY GET";
		case OLE.INVOKE_PROPERTYPUT:
			return "PROPERTY PUT";
		case OLE.INVOKE_PROPERTYPUTREF:
			return "PROPERTY PUT BY REF";
		}
		return "unknown " + invKind;
	}
}

MS워드의 경우 OLEVIEW를 가지고 한번 메소드를 찾긴 했는데 찾는데 어려운듯

그럼 이걸가지고 특정파일을 열게 실행을 해보겠습니다.

'IT > RCP' 카테고리의 다른 글

[RCP] 사전 준비 및 주요 용어  (0) 2020.12.20
[SWT] 윈도우 레지스트리  (0) 2020.12.19
[SWT] 클립보드  (0) 2020.12.19
[SWT] Drag & Drop  (0) 2020.12.19
[SWT] 다이얼로그  (0) 2020.12.19

윈도우에서 흔히 사용하고 있는 클립보드를 예제를 보자

copy, paste, query(클립보드 내용및 분류)

package swt.clipboard;

import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.Clipboard;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

public class CopyAndPasteWithClipboard {
	
	Display display = null;
	Shell shell = null;
	Text text = null;
	Button copy = null;
	Button paste = null;
	Button clear = null;
	Button query = null;
	Clipboard cb = null;

	//Main시작
	public static void main(String[] args) {
		CopyAndPasteWithClipboard app = new CopyAndPasteWithClipboard();
		app.run();
	}	

	//run에서 화면 실행
	public void run() {
		shell.open();
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch()) {
				display.sleep();
			}
		}
	}	
	
	public CopyAndPasteWithClipboard() {
		createUI();		//ui선언
		doLayout();		//layout
		addListener();	//이벤트 처리
	}

	public void createUI() {
		display = new Display();
		cb = new Clipboard(display);
		shell = new Shell(display);
		shell.setText("SWT Clipboard Test");

		text = new Text(shell, SWT.BORDER | SWT.MULTI | SWT.V_SCROLL
				| SWT.H_SCROLL);

		copy = new Button(shell, SWT.PUSH);
		copy.setText("Copy");

		paste = new Button(shell, SWT.PUSH);
		paste.setText("Paste");

		clear = new Button(shell, SWT.PUSH);
		clear.setText("Clear");

		query = new Button(shell, SWT.PUSH);
		query.setText("Query");
	}

	public void doLayout() {
		shell.setLayout(new FormLayout());

		FormData data = new FormData();
		data.right = new FormAttachment(100, -5);
		data.top = new FormAttachment(0, 5);
		copy.setLayoutData(data);

		data = new FormData();
		data.right = new FormAttachment(100, -5);
		data.top = new FormAttachment(copy, 5);
		paste.setLayoutData(data);

		data = new FormData();
		data.right = new FormAttachment(100, -5);
		data.top = new FormAttachment(paste, 5);
		clear.setLayoutData(data);

		data = new FormData();
		data.right = new FormAttachment(100, -5);
		data.top = new FormAttachment(clear, 5);
		query.setLayoutData(data);

		data = new FormData();
		data.left = new FormAttachment(0, 5);
		data.top = new FormAttachment(0, 5);
		data.right = new FormAttachment(copy, -5);
		data.bottom = new FormAttachment(100, -5);
		text.setLayoutData(data);

		shell.setSize(320, 240);
	}

	public void addListener() {
		copy.addListener(SWT.Selection, new Listener() {
			public void handleEvent(Event e) {
				String textData = text.getSelectionText();
				if ((textData != null) && (!"".equals(textData))) {
					TextTransfer textTransfer = TextTransfer.getInstance();
					cb.setContents(new Object[]{textData},
							new Transfer[]{textTransfer});
				}
			}
		});
		paste.addListener(SWT.Selection, new Listener() {
			public void handleEvent(Event e) {
				TextTransfer transfer = TextTransfer.getInstance();
				String data = (String) cb.getContents(transfer);
				if (data != null) {
					text.insert(data);
				}
			}
		});
		clear.addListener(SWT.Selection, new Listener() {
			public void handleEvent(Event e) {
				cb.clearContents();
			}
		});
		query.addListener(SWT.Selection, new Listener() {
			public void handleEvent(Event e) {
				String names[] = cb.getAvailableTypeNames();
				text.insert("\n----------------------\n");
				for (int i = 0; (names != null) && (i < names.length); i++) {
					text.insert("names[" + i + "] : " + names[i] + "\n");
				}
				text.insert("----------------------\n");
			}
		});
	}

	public void dispose() {
		if (cb != null) {
			cb.dispose();
		}
		if (display != null) {
			display.dispose();
		}
	}
	

}

하나 중점으로 하나 볼것은 copy할때 Transfer 객체를 통하여 clipboard를 copy됨을 보면

앞전에 Drag&Drop과 같은 방식임을 알수 있다.

'IT > RCP' 카테고리의 다른 글

[SWT] 윈도우 레지스트리  (0) 2020.12.19
[SWT] Win32 OLE  (0) 2020.12.19
[SWT] Drag & Drop  (0) 2020.12.19
[SWT] 다이얼로그  (0) 2020.12.19
[SWT] Layout  (0) 2020.12.19

    드레그 와 드롭은 일상에서 많이 사용하고 있다. 근데 개발툴에서는 많이 사용하지 않았지만 앞으로 개발툴도 이러한 기능으로 소스코딩양을 줄여주는것이 좋을것 같다.

이기능은 사용하려면 드래그 하는 곳과 드롭하는 곳에 상호작용 및 순서가 필요하다.

    드래그소스->드롭타깃->드롭효과 ->트랜스

먼저 드레그 클래스 계층도를 살펴보자

ㅁ 드레그 소스

     드레그 소스에는 여러가지 형태가 있을수 있다

     가령 text, file, 워드와 같이 특정 문자에 색이나 강조등의 효과를 가지고 있는 RTP 형식 문서등이 있다.

여기서는 해당소스가 명칭을 TextTransfer, FileTransfer,HTML Transfer,RTF Transfer 라 하고 각

instance를 생성 전달하게 된다.

 여기서 간단한 예제로 Label에 소스를 드레그해서 이클립스 java editer에 드롭하면 move되는 소스를 참고 하여보자

package swt.drag_drop;

import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DragSource;
import org.eclipse.swt.dnd.DragSourceEvent;
import org.eclipse.swt.dnd.DragSourceListener;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;

public class DragSourceTest {
	
	public static void main(String[] args) {
		Display display = new Display();
		Shell shell = new Shell(display);
		shell.setLayout(new FillLayout());
		shell.setText("SWT DragSource Test");

		// 레이블 위젯을 드래그 원본(Drag Source)으로 활성화 한다.
		final Label label = new Label(shell, SWT.BORDER);
		label.setText("text to be transferred");


		int operations = DND.DROP_MOVE | DND.DROP_COPY;
		DragSource source = new DragSource(label, operations);

		// 텍스트 포맷 내에 데이터를 제공한다.
		Transfer[] types = new Transfer[]{TextTransfer.getInstance()};
		source.setTransfer(types);

		source.addDragListener(new DragSourceListener() {
			public void dragStart(DragSourceEvent event) {
				// 레이블 내에 실제 텍스트가 있을 경우에만, 드래그를 시작한다.
				if (label.getText().length() == 0) {
					event.doit = false;
				}
			}

			public void dragSetData(DragSourceEvent event) {
				// 요청된 타입의 데이터를 제공한다.
				if (TextTransfer.getInstance().isSupportedType(event.dataType)) {
					event.data = label.getText();
				}
			}

			public void dragFinished(DragSourceEvent event) {
				// 만약, 데이터의 이동(MOVE) 작업이 수행되었다면,
				// 드래그 원본인 레이블 위젯에서 이동한 데이터를 제거한다.
				if (event.detail == DND.DROP_MOVE) {
					 label.setText("");
				}
			}
		});

		shell.setSize(640, 480);
		shell.open();
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch())
				display.sleep();
		}
		display.dispose();
	}
}

구현시 처리되는 동영상을 참고하세요

Drag 처리

 

ㅁ 드롭 타겟

   다음은 드롭소스를 예제로 생성해 보았다 반대로 드레그는 이클립스에 자바소스에서 드롭은 개발된 소스에서 받는걸로 예제를 처리했다.

package swt.drag_drop;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DropTarget;
import org.eclipse.swt.dnd.DropTargetAdapter;
import org.eclipse.swt.dnd.DropTargetEvent;
import org.eclipse.swt.dnd.FileTransfer;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.dnd.TransferData;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

public class DropTargetCopyTextFileTest {
	private static void open(Text text, String filename) {
		File file = new File(filename);
		try {
			text.setText("");
			FileReader reader = new FileReader(file);
			BufferedReader in = new BufferedReader(reader);
			String str = null;
			while ((str = in.readLine()) != null) {
				text.append(str + "\n");
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		Display display = new Display();
		Shell shell = new Shell(display);
		shell.setLayout(new FillLayout());
		shell.setText("SWT DropTarget Test");

		final Text text = new Text(shell, SWT.BORDER | SWT.MULTI);
		int operations = DND.DROP_DEFAULT | DND.DROP_COPY | DND.DROP_MOVE;
		DropTarget target = new DropTarget(text, operations);
		target.setTransfer(new Transfer[]{FileTransfer.getInstance(),
				TextTransfer.getInstance()});

		target.addDropListener(new DropTargetAdapter() {
			
			FileTransfer fileTransfer = FileTransfer.getInstance();
			TextTransfer textTransfer = TextTransfer.getInstance();
			public void dragEnter(DropTargetEvent e) {
				System.out.println("[dragEnter] e : " + e);
				TransferData data[] = e.dataTypes;
				for (int i = 0; i < data.length; i++) {
					System.out.println("[dragEnter] data[" + i + "] : "
							+ data[i]);
				}
				if (e.detail == DND.DROP_DEFAULT) {
					e.detail = DND.DROP_COPY;
				}
			}

			public void dragOperationChanged(DropTargetEvent e) {
				if (e.detail == DND.DROP_DEFAULT) {
					e.detail = DND.DROP_COPY;
				}
			}

			public void drop(DropTargetEvent e) {
				System.out.println("[drop] e : " + e);
				if (fileTransfer.isSupportedType(e.currentDataType)) {
					String[] files = (String[]) e.data;
					if (files != null && files.length > 0) {
						open(text, files[0]); // 파일을 연다
					}
				}
				if (textTransfer.isSupportedType(e.currentDataType)) {
					String str = (String) e.data;
					if (str != null) {
						text.setText(str); // 텍스트를 커서 위치에 삽입
					}
				}
			}
		});

//		shell.setLocation(display.getBounds().width - 320,
//				display.getBounds().height - 240);
		shell.setSize(320, 240);
		shell.open();
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch())
				display.sleep();
		}
		display.dispose();
	}
}

여기도 동영상을 보면 어떻게 구현했는지를 알수 있다.

 

Drop

ㅁ 사용자 포멧 드레그 엔 드롭

  개발하다보면 사용자 포멧에 데이터를 드레그 엔 드롭을 하고 싶을때가 있다

 ▶ MySimpleDragAndDrop에서 화면구성 및 Drag 소스를 MyType으로 Table TableItem 객체로 구성

 ▶ DragSource, DragSource TransferType MyTypeTransfer 인스턴스로 선언

 ▶ addDragListener에서 이벤트가 발생시 event.data MyTyp객체로 넘겨줌

 ▶ DropTarget에서도 TransferType MyTypeTransfer 인스턴스 선언

 ▶ addDropListener에서 이벤트 발생시 evnet.data Mytype변환하여 사용

 ※ MyTypeTransfer는 인스턴스로 ByteArrayTransfer 상속받아 byte로 짤라 전달

 

ㅁ 3가지 소스사용

 MyType.java(사용자Drag&Drop선언), MyTypeTransfer.java(인스턴스), MySimpleDragAndDrop(main)

 MyType.java : 내가 Drag & Drop할 객체

package swt.drag_drop;

public class MyType {
	public String fileName;
	public long fileLength;
	public long lastModified;
}

 MySimpleDragAndDrop.java : 화면구성 및 이벤트 선언 

package swt.drag_drop;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;

import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.ByteArrayTransfer;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DragSource;
import org.eclipse.swt.dnd.DragSourceAdapter;
import org.eclipse.swt.dnd.DragSourceEvent;
import org.eclipse.swt.dnd.DropTarget;
import org.eclipse.swt.dnd.DropTargetAdapter;
import org.eclipse.swt.dnd.DropTargetEvent;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.dnd.TransferData;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;

public class MySimpleDragAndDrop {

	//시작	
	public static void main(String[] args) {

		//화면구성
		Display display = new Display();
		Shell shell = new Shell(display);
		shell.setLayout(new FillLayout());
		
		//왼쪽에 테이블: LIST는 setData가 없어 TableItem의 setData를 사용함
		final Table tblDrgSrc = new Table(shell, SWT.BORDER | SWT.WRAP | SWT.MULTI);
		
		//아이템1 : abc.txt 파일명에  크기  lastModified라는 속성을 하나의 사용자 객체를 만들어 add
		TableItem item1 = new TableItem(tblDrgSrc,SWT.NONE);
		MyType myType1 = new MyType();
		myType1.fileName = "C:\\abc.txt";
		myType1.fileLength = 1000;
		myType1.lastModified = 12312313;
		item1.setText(myType1.fileName);
		item1.setData(myType1);
		
		//아이템2 : abc.txt 파일명에  크기  lastModified라는 속성을 하나의 사용자 객체를 만들어 add
		TableItem item2 = new TableItem(tblDrgSrc,SWT.NONE);
		MyType myType2 = new MyType();
		myType2.fileName = "C:\\xyz.txt";
		myType2.fileLength = 500;
		myType2.lastModified = 12312323;
		item2.setText(myType2.fileName);
		item2.setData(myType2);
		
		//두번째는 Drop할 객체로 Lable 선언
		final Label label2 = new Label(shell, SWT.BORDER | SWT.WRAP);
		label2.setText("Drop Target for MyData[]");

		//Drag Transfer 선언 : MyTransfer 인스턴스를 넘김선언
		DragSource source = new DragSource(tblDrgSrc, DND.DROP_COPY);
		source.setTransfer(new Transfer[] { MyTypeTransfer.getInstance() });
		
		//Drag 이벤트를 선언 Transfer로는 내가만든 MyTransfer라는 객체로 넘어감
		source.addDragListener(new DragSourceAdapter() {
			public void dragSetData(DragSourceEvent event) {
				
				int arr = tblDrgSrc.getSelectionCount();
				int cnt = 0; 
				MyType[] myType = new MyType[arr];
				//Drag시 내가 만든 객체 myType이란속성에 Object를 event.data로 넘김
				for(TableItem SelItem :tblDrgSrc.getSelection()) {
					myType[cnt] = (MyType)SelItem.getData(); 
					cnt++;
				}
				event.data = myType;
				System.out.println("drageSetData");
			}
		});
		
		//Drop Target 선언 : MyTransfer 인스턴스를 받으려 선언
		DropTarget target = new DropTarget(label2, DND.DROP_COPY | DND.DROP_DEFAULT);
		target.setTransfer(new Transfer[] { MyTypeTransfer.getInstance() });
		
		//Drop 이벤트로 받은경우 Data Object를 받아 MyType으로 변환하여 그중에 이름을 가져옴
		target.addDropListener(new DropTargetAdapter() {
			
			public void dragEnter(DropTargetEvent event) {
				if (event.detail == DND.DROP_DEFAULT) {
					event.detail = DND.DROP_COPY;
				}
			}

			public void dragOperationChanged(DropTargetEvent event) {
				
				if (event.detail == DND.DROP_DEFAULT) {
					event.detail = DND.DROP_COPY;
				}
			}

			public void drop(DropTargetEvent event) {

				if (event.data != null) {
					
					MyType[] myTypes = (MyType[]) event.data;
					if (myTypes != null) {
						String string = "";
						for (int i = 0; i < myTypes.length; i++) {
							string += myTypes[i].fileName + " ";
						}
						label2.setText(string);
					}
				}

			}

		});
		shell.setSize(200, 200);
		shell.open();
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch())
				display.sleep();
		}
		display.dispose();
	}

		
	static class MyTransfer extends ByteArrayTransfer {

		//인스턴스 객체를 생성하기 위해 Name과 ID가 필요함
		private static final String MYTYPENAME 	= "name_for_my_type";
		private static final int MYTYPEID 		= registerType(MYTYPENAME);
		private static MyTransfer _instance = new MyTransfer();

		public static MyTransfer getInstance() {
			return _instance;
		}

		//Drag소스를 Buffer전환하여 원 소스에 넘김
		public void javaToNative(Object object, TransferData transferData) {
			
			if (!checkMyType(object) || !isSupportedType(transferData)) {
				DND.error(DND.ERROR_INVALID_DATA);
			}
			MyType[] myTypes = (MyType[]) object;
			try {
				// write data to a byte array and then ask super to convert to
				// pMedium
				ByteArrayOutputStream out = new ByteArrayOutputStream();
				DataOutputStream writeOut = new DataOutputStream(out);

				for (int i = 0, length = myTypes.length; i < length; i++) {
					byte[] buffer = myTypes[i].fileName.getBytes();
					writeOut.writeInt(buffer.length);
					writeOut.write(buffer);
					writeOut.writeLong(myTypes[i].fileLength);
					writeOut.writeLong(myTypes[i].lastModified);
				}

				byte[] buffer = out.toByteArray();
				writeOut.close();
				super.javaToNative(buffer, transferData);
			} catch (IOException e) {
			}
		}

		//Drop시 받은것을소스를 Buffer전환하여 원 소스에 넘김
		public Object nativeToJava(TransferData transferData) {
			if (isSupportedType(transferData)) {
				byte[] buffer = (byte[]) super.nativeToJava(transferData);
				if (buffer == null)
					return null;

				MyType[] myData = new MyType[0];
				try {
					ByteArrayInputStream in = new ByteArrayInputStream(buffer);
					DataInputStream readIn 	= new DataInputStream(in);
					
					while (readIn.available() > 20) {
						MyType datum = new MyType();
						int size = readIn.readInt();
						byte[] name = new byte[size];
						readIn.read(name);
						
						datum.fileName = new String(name);
						
						datum.fileLength = readIn.readLong();
						datum.lastModified = readIn.readLong();
						
						MyType[] newMyData = new MyType[myData.length + 1];
						
						System.arraycopy(myData, 0, newMyData, 0, myData.length);
						
						newMyData[myData.length] = datum;
						myData = newMyData;
					}
					readIn.close();
				} catch (IOException ex) {
					return null;
				}
				return myData;
			}

			return null;
		}
		
		
		//기본생성자
		protected String[] getTypeNames() {
			return new String[] { MYTYPENAME };
		}

		//기본생성자
		protected int[] getTypeIds() {
			return new int[] { MYTYPEID };
		}

		boolean checkMyType(Object object) {
			if (object == null || !(object instanceof MyType[]) || ((MyType[]) object).length == 0) {
				return false;
			}
			MyType[] myTypes = (MyType[]) object;
			for (int i = 0; i < myTypes.length; i++) {
				if (myTypes[i] == null || myTypes[i].fileName == null || myTypes[i].fileName.length() == 0) {
					return false;
				}
			}
			return true;
		}

		protected boolean validate(Object object) {
			return checkMyType(object);
		}
	}

}

 MyTypeTransfer.java : 인스턴스 구성

package swt.drag_drop;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;

import org.eclipse.swt.dnd.ByteArrayTransfer;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.TransferData;

public class MyTypeTransfer extends ByteArrayTransfer {
	
	//인스턴스 객체를 생성하기 위해 Name과 ID가 필요함
	private static final String MYTYPE_NAME = "my_type_name";
	private static final int MYTYPE_ID 		= registerType(MYTYPE_NAME);
	private static MyTypeTransfer INSTANCE 	= new MyTypeTransfer();

	
	public static MyTypeTransfer getInstance() {
		return INSTANCE;
	}

	//Drag소스를 Buffer전환하여 원 소스에 넘김
	public void javaToNative(Object object, TransferData transferData) {
		
		if (!checkMyType(object) || !isSupportedType(transferData)) {
			DND.error(DND.ERROR_INVALID_DATA);
		}
		
		System.out.println("test1 javaToNative:"+transferData);

		//if (isSupportedType(transferData)) {
			MyType[] myTypes = (MyType[]) object;
			try {
				// write data to a byte array and then ask super to convert to
				// pMedium
				ByteArrayOutputStream bout = new ByteArrayOutputStream();
				DataOutputStream out = new DataOutputStream(bout);
				for (int i = 0, length = myTypes.length; i < length; i++) {
					byte[] buffer = myTypes[i].fileName.getBytes();
					out.writeInt(buffer.length);
					out.write(buffer);
					out.writeLong(myTypes[i].fileLength);
					out.writeLong(myTypes[i].lastModified);
				}
				byte[] buffer = bout.toByteArray();
				out.close();

				super.javaToNative(buffer, transferData);
			} catch (IOException e) {
				e.printStackTrace();
			}
		//}
	}

	//Drop시 받은것을소스를 Buffer전환하여 원 소스에 넘김	
	public Object nativeToJava(TransferData transferData) {
		//System.out.println("test2"+transferData);
		System.out.println("test2 nativeToJava:"+transferData);
		
		if (isSupportedType(transferData)) {

			byte[] buffer = (byte[]) super.nativeToJava(transferData);
			if (buffer == null) {
				return null;
			}

			MyType[] myData = new MyType[0];
			try {
				ByteArrayInputStream bin = new ByteArrayInputStream(buffer);
				DataInputStream in = new DataInputStream(bin);
				while (in.available() > 20) {
					MyType datum = new MyType();

					int size = in.readInt();
					byte[] name = new byte[size];
					in.read(name);
					datum.fileName = new String(name);
					datum.fileLength = in.readLong();
					datum.lastModified = in.readLong();

					MyType[] newMyData = new MyType[myData.length + 1];
					System.arraycopy(myData, 0, newMyData, 0, myData.length);
					newMyData[myData.length] = datum;
					myData = newMyData;
				}
				in.close();
			} catch (IOException e) {
				e.printStackTrace();
				return null;
			}
			return myData;
		}

		return null;
	}

	protected String[] getTypeNames() {
		return new String[]{MYTYPE_NAME};
	}

	protected int[] getTypeIds() {
		return new int[]{MYTYPE_ID};
	}
	
	boolean checkMyType(Object object) {
		if (object == null || !(object instanceof MyType[]) || ((MyType[]) object).length == 0) {
			return false;
		}
		MyType[] myTypes = (MyType[]) object;
		for (int i = 0; i < myTypes.length; i++) {
			if (myTypes[i] == null || myTypes[i].fileName == null || myTypes[i].fileName.length() == 0) {
				return false;
			}
		}
		return true;
	}

	protected boolean validate(Object object) {
		return checkMyType(object);
	}	
}

'IT > RCP' 카테고리의 다른 글

[SWT] Win32 OLE  (0) 2020.12.19
[SWT] 클립보드  (0) 2020.12.19
[SWT] 다이얼로그  (0) 2020.12.19
[SWT] Layout  (0) 2020.12.19
[SWT] 이벤트  (0) 2020.12.19

  대화창은  흔히 쓰는 디렉토리 선택, 파일불러오기,파일저장하기, 색선택등등의 대화창을 말한다.

먼저 계층도를 살펴보자

Dialog의 세부 하위 구성

ㅁ ColorDialog

ColorDialog dialog = new ColorDialog(shell);
RGB color = dialog.open();
if (color != null){
	System.out.println("RGB color"+color.toString());			
}else {
	System.out.println("RGB color null");
}

DirectoryDialog

DirectoryDialog dialog = new DirectoryDialog(shell);
dialog.setMessage("Choose a save directory");
String savetarget= dialog.open();
if (savetarget != null){
	System.out.println("savetarget:"+savetarget);			
}else {
	System.out.println("savetarget null");
}	

File Open

FileDialog dialog = new FileDialog(shell,SWT.OPEN | SWT.MULTI);		//SWT.SAVE, SWT.OPEN,SWT.MULTI 등등 있다
dialog.setFilterExtensions(new String[] {"*.txt;*.doc"});
dialog.open();
String [] savetarget= dialog.getFileNames();
if (savetarget != null){
	System.out.println("OPEN FIle List:"+Arrays.toString(savetarget));			
}else {
	System.out.println("OPEN FIle List null");
}

ㅁ File SAVE

FileDialog dialog = new FileDialog(shell,SWT.SAVE | SWT.MULTI);
//SWT.SAVE, SWT.OPEN,SWT.MULTI 등등 있다
dialog.setFilterExtensions(new String[] {"*.txt;*.doc"});
//dialog.setFilterPath(string);
//dialog.setFileName(string);
dialog.open();
//dialog.getFileName();
String savetarget= dialog.getFileName();;
if (!savetarget.equals("")){
	System.out.println("SAVE FIle    :"+savetarget);			
	System.out.println("getFilterPath:"+dialog.getFilterPath());
	System.out.println("getOverwrite :"+dialog.getOverwrite());
}else {
	System.out.println("SAVE FIle null");
}

FontDialog

FontDialog dialog = new FontDialog(shell);		//SWT.SAVE, SWT.OPEN,SWT.MULTI 등등 있다
dialog.open();

if (dialog != null){
	System.out.println("getEffectsVisible:"+dialog.getEffectsVisible());
	System.out.println("getText :"+dialog.getText());			
	System.out.println("getStyle :"+dialog.getStyle());
	System.out.println("getFontData :"+dialog.getFontData());							
	System.out.println("getFontList :"+Arrays.toString(dialog.getFontList()));
}else {
	System.out.println("FontDialog null");
}

MessageBox

/* 버튼 타입
SWT.OK
SWT.OK | SWT.CANCEL
SWT.YES | SWT.NO
SWT.YES | SWT.NO | SWT.CANCEL
SWT.RETRY | SWT.CANCEL
SWT.ABORT | SWT.RETRY | SWT.IGNORE*/

/*아이콘타입
 SWT.ERROR_ICON
 SWT.ICON_INFOMATION
 SWT.ICON_QUESTION
 SWT.ICON_WARNING
 SWT.ICON_WORKING
 */

MessageBox dialog = new MessageBox(shell,SWT.YES | SWT.NO);
dialog.setMessage("내용부분");
dialog.setText("타이틀");
int returnVal = dialog.open();

System.out.println("returnVal :"+returnVal);	//각상수로 비교하여 사용한다
if (returnVal==SWT.YES) {
	//..
}

참고로 Jface에서는 Message Dialog많이 환경설정과 관련된 Dialog들이 추가로 제공해주고 있다

'IT > RCP' 카테고리의 다른 글

[SWT] 클립보드  (0) 2020.12.19
[SWT] Drag & Drop  (0) 2020.12.19
[SWT] Layout  (0) 2020.12.19
[SWT] 이벤트  (0) 2020.12.19
[SWT] 기본정보(구성,환경,위젯정보)  (0) 2020.12.19

레이아웃에 대해서는 잘되어 있는 사이트 먼저 공유하고자 합니다.

(참고 : https://www.eclipse.org/articles/Article-Understanding-Layouts/Understanding-Layouts.htm) 구글에 SWT layout하면 가장 많이 검색되는 화면입니다

 

 

ㅁ MarginLeft, MarginTop, MarginRight, MarginButton Vertical/Horizontal Spacing

 

그리고 layout은 SWT, JFACE 모두 동일하게 사용되어 집니다. 위젯들을 어떻게 배치하고 화면이 늘려짐에 따라 어떤것들이 늘어나고 고정되는지에 대한 얘기 입니다.

 

1. FillLayout

    FillLayout fillLayout = new FillLayout()

    fillLayout.type        = SWT.VERTICAL

    shell.setLayout(fillLayout)    적용하려는 Composite, Shell 등등에 적용

 

 

2. RowLayout

    RowLayout rowLayout = new RowLayout();

    rowLayout.wrap = false;

    rowLayout.pack = false;

    rowLayout.justify = true;

    rowLayout.marginLeft = 5;

    rowLayout.marginTop = 5;

    rowLayout.marginRight = 5;

    rowLayout.marginBottom = 5;

    rowLayout.spacing = 0;

    shell.setLayout(rowLayout);

    wrap(기본 true) : false한행 유지, 부모가 가시적으로 줄어들 때 안보이는게 발생

    pack(기본 true) : false인경우 본래 size사용

    justify(기본 false) : true인경우 균등하게 배치

 

3. GridLayout

   가장많이 사용되어집니다.

4. GridData

  setLayoutData메소드 사용

  Button button1 = new Button(shell, SWT.PUSH);

  button1.setText("B1");

  button1.setLayoutData(new GridData());

 

 

 

'IT > RCP' 카테고리의 다른 글

[SWT] 클립보드  (0) 2020.12.19
[SWT] Drag & Drop  (0) 2020.12.19
[SWT] 다이얼로그  (0) 2020.12.19
[SWT] 이벤트  (0) 2020.12.19
[SWT] 기본정보(구성,환경,위젯정보)  (0) 2020.12.19

   이벤트라 함은 버튼클릭, 텍스트 내용이 변경된경우 등등의 해당되며, 이와 SWT에서 이벤트

를 알아보고자 합니다.

먼저 이벤트 종류에 대해 알아봅시다.

 

1) 유형이벤트 : key클릭, 마우스 up 등등 특정이벤트
2) 무형이벤트 : 특정을 지칭하지 않은 이벤트들
3) 어뎁터 : 이벤트를 전부 구현하지 않고 필요한것만 구현토록 구조화
4) 이벤트를 받아 리스너에서 보통은 처리하는 메서드 구현 즉 연결관계에 있다 

참고로 자바 이벤트와 비슷하다.

1.1 이벤트 유형 리스너와 리스너 메소드

 

1.2 이벤트의 구현

이벤트 리스너의 구현방식 두가지 : 익명구현, 외부클래스

1) 익명구현방식 : 장)소스가 즉흥적 가능, 단)재활용이 안됨

helloBtn.addMouseListener(new MouseListener() {  //==>익명구현   
   @Override
   public void mouseUp(org.eclipse.swt.events.MouseEvent arg0) {
    // TODO Auto-generated method stub
    System.out.println("마우스 업");
    
   }
   
   @Override
   public void mouseDown(org.eclipse.swt.events.MouseEvent arg0) {
    // TODO Auto-generated method stub
    System.out.println("마우스 다운");
   }
   
   @Override
   public void mouseDoubleClick(org.eclipse.swt.events.MouseEvent arg0) {
    // TODO Auto-generated method stub
    System.out.println("마우스 더블클릭");
   }
  });

2) 외부클래스 구현방식 : 장)재활용가능

   
   MouseListener ExMouseListener = new MouseListener() {  //==>외부클래스구현
   @Override
   public void mouseDoubleClick(MouseEvent arg0) {
    // TODO Auto-generated method stub
    System.out.println("마우스 더블클릭");
   }
   @Override
   public void mouseDown(MouseEvent arg0) {
    // TODO Auto-generated method stub
    System.out.println("마우스 다운");
   }
   @Override
   public void mouseUp(MouseEvent arg0) {
    // TODO Auto-generated method stub
    System.out.println("마우스 업");
   }
   
  };

helloBtn.addMouseListener(ExMouseListener); //외부클래스 사용

1.3 어뎁터

 앞 이벤트에서는 특이한 것은 내부 메소드가 모두 @Override된 것을 알수 있다. 구현하지 않아도 선언되지 않으면 안되는 반면 어뎁터는 구현하고 싶은 것들만 구현하도록 되어 있다

즉 익명의 인터페이스를 사용하지 않고 또한 모든메소드를 구현하지 않기 위해 어댑터라 부르는 특별한 클래스로 사용하여 구현 :: 내부 메소드를 필요한것만 사용가능

1) 익명구현

helloBtn.addMouseListener(new MouseAdapter() {  //==>익명구현
  
   public void mouseDown(org.eclipse.swt.events.MouseEvent arg0) {
    // TODO Auto-generated method stub
    System.out.println("마우스 다운");
   }
 });

2) 외부클래스 구현

MouseListener ExMouseListener = new MouseAdapter() {  //==>외부클래스구현
   
   public void mouseDown(MouseEvent arg0) {
    // TODO Auto-generated method stub
    System.out.println("마우스 다운");
   }
   public void mouseUp(MouseEvent arg0) {
    // TODO Auto-generated method stub
    System.out.println("마우스 업");
   }   
  };

helloBtn.addMouseListener(ExMouseListener) ; //외부클래스 사용

1.4 어뎁터  종류

 

※ 참고 사항 Event에서 keyCode(KeyListne/KeyAdapter에서 사용)

 

1.5 무형이벤트

   특정이벤트가 아니라 모든 이벤트처리 대표로처리할수 있는 Listener 클래스이다

    ▶ JFaceTestMain.java작성

import org.eclipse.jface.window.ApplicationWindow;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
 
public class JFaceTestMain extends ApplicationWindow {
  
 public JFaceTestMain() {
  super(null);
  // TODO Auto-generated constructor stub
 }
 protected Control createContents(Composite parent) {
  System.out.println("test main createContents");
  new IntangibleEventTest(parent);
  parent.pack();
  return parent;
 }
 
 public static void main(String[] args) {
  JFaceTestMain obj = new JFaceTestMain();
  obj.setBlockOnOpen(true);
  obj.open();
   
  Display.getCurrent().dispose();
 }
}

 IntangibleEventTest.java작성

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
 
public class IntangibleEventTest extends Composite{
 
 Label output;
  
 public IntangibleEventTest(Composite parent) {
   
  super(parent, SWT.NULL);
  System.out.println("test IntangibleEventTest");
  Button typed = new Button(this,SWT.PUSH);
  typed.setText("Typed");
  typed.setLocation(2,10);
  typed.pack();
   
  typed.addKeyListener(new KeyAdapter() {
   public void keyPressed(KeyEvent e) {
    keyHandler();
   }
 
 
  });
   
  Button untyped = new Button(this,SWT.PUSH);
  untyped.setText("UnTyped");
  untyped.setLocation(80,10);
  untyped.pack();
  untyped.addListener(SWT.MouseEnter, UntypedListener);
  untyped.addListener(SWT.MouseExit, UntypedListener);
   
  output = new Label(this,SWT.SHADOW_OUT);
  output.setBounds(40,70,90,40);
  output.setText("No Event");
   
  pack();
   
 }
  
 Listener UntypedListener = new Listener(){
 
  @Override
  public void handleEvent(Event event) {
   System.out.println("handleEvent:"+event.widget.getClass().getSimpleName() );
   switch(event.type) {
    
   case SWT.MouseEnter:
    output.setText("Mouse Enter");
    break;
   case SWT.MouseExit:
    output.setText("Mouse Exit");
    break;
   }
    
  }
   
 };
 
 void keyHandler() {
  // TODO Auto-generated method stub
  output.setText("Key Event");
 }
}

'IT > RCP' 카테고리의 다른 글

[SWT] 클립보드  (0) 2020.12.19
[SWT] Drag & Drop  (0) 2020.12.19
[SWT] 다이얼로그  (0) 2020.12.19
[SWT] Layout  (0) 2020.12.19
[SWT] 기본정보(구성,환경,위젯정보)  (0) 2020.12.19

위젯 툴킷(Standard Widget Toolkit)으로 이클립스에서 사용하고 있는 자바기반의 위젯 툴킷(Widget Toolkit)

우리가 사용하는 이클립스에 ViewPart,EditorPart등 도구를 만들기 위한 기초입니다.

 

ㅁ 구성

    

   Display객체, Shell객체 그리고 그 하위에 위젯에 개념이 들어간다

   OS swt.jar에 따라 여러가지 운영체계 프로그램을 만들 수 있다

   위젯은 기본이다

 

ㅁ 환경설정

    Java 프로젝트 생성 

   

해당 프로젝트에 swt.jar만 있으면 된다.

ㅁ 참고사이트

    http://www.eclipse.org/swt/

    각종 위젯등에 대한 예시 가 소스하고 함께 잘되어 있음

 

ㅁ Widget의 구성요소

ㅁ 각 위젯에 요소

    위젯은 좀 프로그램을 해본 경험이 있는사람의 경우 쉽게 알수 있기 때문에 많은 설명을 하지않고 단지 기능 요약을 해보겠습니다.

 1) Control 메소드

Control메소드

기능

getSize()

위젯크기를 표시하는 Point 객체반환

setSize(int,int)

너비와 길이 값 설정

setSize(Point)

Point 객체에 따라 위젯크기 설정

computeSize()

위젯 내용을 모두 보여줄수 있는 면적을 반환

computeSize(int,int,boolean)

위젯내용을 모두 보여줄수 있는 면적을 반환하고, 위젯 특성이 바뀌었는지 알려줌

pack()

위젯을 선호하는 크기로 재조정한다

pack(boolean)

위젯을 선호하는 크기로 재조정하고, 특성이 바뀌었는지 알려줌

getLocation()

위젯의 부모에 대한 상대위치

setLocation(int,int)

위젯의 부모에 대한 상대위치 설정

getBounds()

위젯의 크기와 부모에 대한 상대 위치를 반환한다

setBounds(int,int,int,int)

위젯의 크기와 부모에 대한 상대위치 설정

toControl(int,int)

화면 기준 좌표를 컨트롤 기준 Point 값으로 바꾼다

toControl(Point)

화면 기준 Point값을 컨트롤을 기준 Point 값으로 바꾼다

toDisplay(int,int)

컨트롤 기준좌표를 컨트롤 기준 Point 값으로 바꾼다

toDisplay(Point)

컨트롤 기준 Point 값을 Point 값으로 바꾼다

※ setSize() 보다 pack() 컨테이너 크기를 알아서 조절

 

2) Label 메소드

     위치        : SWT.LEFT, SWT.RIGHT, SWT.CENTER,

     구분선     : SWT.SPARATOR

     수직/수평 : SWT.VERTICAL, SWT.HORIZONTAL

     그림자     : SWT.SHADOW_IN, SWT.SHADOW_OUT, SWT.SHADOW_NONE

     ==>SWT에는 열거형 정수형으로 많은 타입을 가지고 있다

Label메소드

기능

getText()

 Label 텍스트 읽기

setText(String)

 Label텍스트 쓰기

getAlignment()

 정렬가져오기

setAlignment(int)

 정렬 setting

getImage()

 이미지 set

setImage(Image)

이미지 get

 

3) Button

     SWT.PUSH,

     SWT.ARROW | SWT.RIGHT

     SWT.TOGGLE

     SWT.CHECK, SWT.RADIO

 

4) Composite

     각Control을 집합으로 구성가능하다

4.1) Composite 기본

Composite 메소드

기능

getChiendren()

Control 객체의 배열을 반환한다

getLayout()

Composite에 연결한 레이아웃을 반환한다

setLayout(Layout)

Composite에 연결한 레이아웃을 설정한다

getTabList()

탭 순서에 따른 Control 객체의 배열을 반환한다

setTabList(Control[])

Composite의 위젯의 탭 순서를 설정한다

 

4.2) Composite의 하위클래스로 Scrollable 속성을 추가 사용         

Scrollable 메소드

기능

getClientArea()

Scrollable 객체에 가능한 화면 표시 면적을 반환한다.

computeTrim(int,int,int,int)

기대하는 클라이언트 영역을 위한 Composite의 필요 면적을 반환한다

getHorizontalBar()

수평 ScrollBar 객체를 반환한다

getVerticalBar()

수직 ScrollBar 객체를 반환한다

 

5)  Group

  그림자 속성과 함께 추가적으로 식각(etching)을 표시한다.

  SWT.SHADOW_ETCHEND_IN SHADOW_ETCHEND_OUT

6) SashForm

7) TabFolder

    getItemCount : TabFolder  TabItem 수반환

    getItems() : TabItem 객체의 배열을 반환

    getSelection() : 사용자가 어떤 TabItem을 선택했는지

    setSelection(): 선택될 탭을 설정

 7) LIst

 8) Combo

   style : SWT.SIMPLE, SWT.DROP_DOWN, SWT.READ_ONLY

 9) Tree

    ▶ 트리에서 사용하는 메소드 : Scrollable의 확장기능임.

메소드

기능

addSelectionListener()

선택 이벤트의 통지

addTreeListener()

TreeListener 인터페이스는 +확장  축소 할 때

select()/deselect()

현재 선택/ 제외

getSelection()

현재 선택항목

 show()

 주어진 항목을 보일때까지 스크롤

  Style로는 SWT.SINGLE, SWT.MULT

 TreeItem 메소드

메소드

기능

getItem()

 Tree 하위를 각각 TreeItem이라하면 불러오기

getChecked()

체크

setExpanded(boolean)

 확장

 

예제) Widdget Window에서 Tab을 만들고 그안에 두개 Composite가 구성된 Composite를 추가

Composite에는 Group Composite, SashForm Composite구성해보았다

 

 

'IT > RCP' 카테고리의 다른 글

[SWT] 클립보드  (0) 2020.12.19
[SWT] Drag & Drop  (0) 2020.12.19
[SWT] 다이얼로그  (0) 2020.12.19
[SWT] Layout  (0) 2020.12.19
[SWT] 이벤트  (0) 2020.12.19

문제는 방화벽을 설정해서 도커내 컨테이너에서 외부 접속이 안되는 현상

제어판 ->보안->방화벽

기존에 192.168.0.1~192.168.0.255 ip외 접속허용 외로 하다 보니 도커가 172.17.0.1 영역을 사용해서 문제였음

허용으로 변경하고 가능함

'IT > 서버' 카테고리의 다른 글

Docker 명령어 정리  (0) 2020.11.21
리눅스 추가 설치 및 명령어, 주요경로  (0) 2020.11.16

원문 : coding-factory.tistory.com/71

 

[Jsp] MVC 패턴 게시판

저번 포스팅 MVC2 패턴으로 만드는 회원가입 및 로그인에 이어서 이번에는 MVC2 패턴으로 만드는 게시판을 공부해보겠습니다. 회원가입 , 로그인 기능과 마찬가지로 게시판도 어느 웹사이트에서

coding-factory.tistory.com

위 원문을 보고 Mysql로 한번 작성해보았고 나름대로 MVC 패턴을 정리하고자 함

 

ㅁ 테이블 생성

--테이블 생성
CREATE TABLE work.BOARD
(
BOARD_NUM		int(10)	 NOT NULL
,BOARD_NAME		varchar(20)	 NULL
,BOARD_PASS		varchar(15)	 NULL
,BOARD_SUBJECT		varchar(50)	 NOT NULL
,BOARD_CONTENT		text(65535)	 NULL
,BOARD_FILE		varchar(50)	 NULL
,BOARD_RE_REF		int(10)	 NULL
,BOARD_RE_LEV		int(10)	 NULL
,BOARD_RE_SEQ		int(10)	 NULL
,BOARD_READCOUNT		int(10)	 NULL
,BOARD_DATE		date	 NOT NULL
);

--PK설정
alter table work.BOARD add primary key(BOARD_NUM);

--테이블 설명
ALTER TABLE work.BOARD COMMENT = 'MVC게시판'; 

--컬럼 comment
ALTER TABLE work.BOARD MODIFY BOARD_NUM	 int(10)	 COMMENT '일련번호' 	 NOT NULL;
ALTER TABLE work.BOARD MODIFY BOARD_NAME	 varchar(20)	 COMMENT '작성자' 	 NULL;
ALTER TABLE work.BOARD MODIFY BOARD_PASS	 varchar(15)	 COMMENT '패스워드' 	 NULL;
ALTER TABLE work.BOARD MODIFY BOARD_SUBJECT	 varchar(50)	 COMMENT '제목' 	 NOT NULL;
ALTER TABLE work.BOARD MODIFY BOARD_CONTENT	 text(65535)	 COMMENT '내용' 	 NULL;
ALTER TABLE work.BOARD MODIFY BOARD_FILE	 varchar(50)	 COMMENT '파일명' 	 NULL;
ALTER TABLE work.BOARD MODIFY BOARD_RE_REF	 int(10)	 COMMENT '원문일련번호' 	 NULL;
ALTER TABLE work.BOARD MODIFY BOARD_RE_LEV	 int(10)	 COMMENT '레벨' 	 NULL;
ALTER TABLE work.BOARD MODIFY BOARD_RE_SEQ	 int(10)	 COMMENT '순서' 	 NULL;
ALTER TABLE work.BOARD MODIFY BOARD_READCOUNT	 int(10)	 COMMENT '조회건수' 	 NULL;
ALTER TABLE work.BOARD MODIFY BOARD_DATE	 date	 COMMENT '작성일자' 	 NOT NULL;

 

ㅁ DB연동하기 -JNDI,DBCP(커넥션풀) 이용 

더보기

▶ JNDI(Java Naming and Diectory Interface)  

    디렉토릭 서비스에서 제공하는 데이터 및 객체를 발견하고 참고(lookup)하기 위한 자바 API

DBCP(DataBase Connection Pool, 커넥션 풀)

    데이터베이스와 연결된 커넥션을 미리 만들어 저장하고 필요할때 저장된 공간에서 가져다 쓰는 기법

 ※ 사전작업

    WebContent\WEB-INF\lib에  해당 드라이버 mysql-connector-java-5.1.28-bin.jar 넣음

    tomcat-dbcp.jar 

 

 1) context.xml과 web.xml을 이용한 연결

  1-1) DBCP 정보설정

          context.xml 파일에 Context 태그 아래 Resource를 추가

 <Context> 
   <Resource 
	maxWait="-1" 
	maxIdle="10" 
	maxActive="20" 
	username="[아이디]" 
	password="[패스워드]" 
	url="jdbc:mysql://[ip]:3307/work" 
	type="javax.sql.DataSource" 
	driverClassName="com.mysql.jdbc.Driver" 
	auth="Container" 
	name="jdbc/MyBoard1"/> 
<!--
    auth : 컨테이너를 자원 관리자로 기술
    name : JDBC이름, 변경 가능
    driverClassName : JDBC 드라이버
    type : 웹에서 이 리소스를 사용할 때 DataSource로 리턴됨
    username : 접속계정
    password : 접속할 계정 비밀번호
    
    loginTimeout : 연결 끊어지는 시간
    maxActive : 최대 연결 가능한 Connection수 (기본 20개)
    maxIdle : Connection pool 유지를 위해 최대 대기 connection 숫자
    maxWait : 사용 가능한 커넥션이 없을 때 커넥션 회수를 기다리는 시간 (1000 = 1초)
    testOnBorrow : db에 test를 해볼 것인지
-->
    
 </Context>

    1-2) JNDI 리소스 사용설정

          WebContent\WEB-INF\에 web.xml 추가

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee                       http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> 	
	
	<servlet>
		<servlet-name>BoardController</servlet-name>
		<servlet-class>
		com.board.dicws.action.BoardController</servlet-class>
	</servlet>
	<servlet-mapping>
		<servlet-name>BoardController</servlet-name>
		<url-pattern>*.bo</url-pattern>
	</servlet-mapping>

	<display-name>
	MyBoard1</display-name>
	<welcome-file-list>
		<welcome-file>index.html</welcome-file>
		<welcome-file>index.htm</welcome-file>
		<welcome-file>index.jsp</welcome-file>
		<welcome-file>default.html</welcome-file>
		<welcome-file>default.htm</welcome-file>
		<welcome-file>default.jsp</welcome-file>
	</welcome-file-list>
	
	<resource-ref>
		<description>Connection</description>
		<res-ref-name>jdbc/MyBoard1</res-ref-name>
		<res-type>javax.sql.DataSource</res-type>
		<res-auth>Container</res-auth>
	</resource-ref>
</web-app>

   ▶ JSP 연결테스트

   WebContent\test.jsp 만들고 실행 

<%@ page import="javax.naming.*, javax.sql.*, java.sql.*"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%
		Connection con = null;
		PreparedStatement stmt = null;

		Context initCtx = new InitialContext();
		Context envCtx = (Context) initCtx.lookup("java:comp/env");
		//resource명과 res-ref-name과 일치하는 이름
		DataSource ds = (DataSource) envCtx.lookup("jdbc/MyBoard1");
		con = ds.getConnection();

		String msg = "disconnection";

		if (con != null) {

			msg = "connection";

		}
%>		
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h2>
	Results =
	<%=msg%></h2>

</body>
</html>

   ▶ 자바사용

package com.board.dicws.lib;

import java.sql.Connection;
import java.sql.SQLException;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;

public class DBConnection {
	
	public static Connection getConnection() throws SQLException, NamingException, ClassNotFoundException {
		Context initCtx = new InitialContext();

		// initCtx의 lookup메서드를 이용해서 "java:comp/env" 에 해당하는 객체를 찾아서 evnCtx에 삽입
		Context envCtx = (Context) initCtx.lookup("java:comp/env");

		// envCtx의 lookup메서드를 이용해서 "jdbc/MyBoard1"에 해당하는 객체를 찾아서 ds에 삽입
		DataSource ds = (DataSource) envCtx.lookup("jdbc/MyBoard1");

		// getConnection메서드를 이용해서 커넥션 풀로 부터 커넥션 객체를 얻어내어 conn변수에 저장
		Connection conn = ds.getConnection();
		return conn;

		/*
		 * 위의 코드를 아래와 같이 줄여서 작성 가능하다. Context context = new InitialContext(); DataSource
		 * dataSource = (DataSource) context.lookup("java:comp/env/jdbc/oracle");
		 * Connection con = dataSource.getConnection();
		 * 
		 */
	}
}

 2) server.xml과 context.xml을 이용한 연결

    1-1) DBCP 정보설정

          server.xml 편집 : GlobalNamingResources 테그에 Resource 추가

  <GlobalNamingResources>
    <!-- Editable user database that can also be used by
         UserDatabaseRealm to authenticate users
    -->
    <Resource auth="Container" description="User database that can be updated and saved" factory="org.apache.catalina.users.MemoryUserDatabaseFactory" name="UserDatabase" pathname="conf/tomcat-users.xml" type="org.apache.catalina.UserDatabase"/>
   <Resource 
	maxWait="-1" 
	maxIdle="10" 
	maxActive="20" 
	username="[아이디]" 
	password="[패스워드]" 
	url="jdbc:mysql://[ip]:3307/work" 
	type="javax.sql.DataSource" 
	driverClassName="com.mysql.jdbc.Driver" 
	auth="Container" 
	name="jdbc/MyBoard1"/> 
<!--
    auth : 컨테이너를 자원 관리자로 기술
    name : JDBC이름, 변경 가능
    driverClassName : JDBC 드라이버
    type : 웹에서 이 리소스를 사용할 때 DataSource로 리턴됨
    username : 접속계정
    password : 접속할 계정 비밀번호
    
    loginTimeout : 연결 끊어지는 시간
    maxActive : 최대 연결 가능한 Connection수 (기본 20개)
    maxIdle : Connection pool 유지를 위해 최대 대기 connection 숫자
    maxWait : 사용 가능한 커넥션이 없을 때 커넥션 회수를 기다리는 시간 (1000 = 1초)
    testOnBorrow : db에 test를 해볼 것인지
-->

  </GlobalNamingResources>

   context.xml 편집 

 

 <Context> 
    <ResourceLink global="jdbc/MyBoard1" name="jdbc/MyBoard1" type="javax.sql.DataSource"/>
 </Context>

 

'IT > 기타 프로그램' 카테고리의 다른 글

[Tomcat] 구조 및 개념정리  (0) 2020.12.13
[Tomcat] 설치 및 환경설정  (0) 2020.12.13

ㅁ webapps의 구조

webapps의 구조

ㅁ 생명주기

ㅁ 서블릿 메소드 관련 

    서블릿은 HttpServlet을 상속받아 주로 service(request,response)로 사용

    호출방식에 따라 get/post로 나누어 질때 doPost와 doGet 메소드를 사용함

     

    service 메소드 사용 또는 doGet, doPost 메소드를 오버라이딩 해서 사용

 

JSP 주요 액션태그

   (1)useBean

   (2)setProperty

   (3)getProperty

 

※ Bean 와 서블릿의 차이

   공통점 : 서버에서 작성, 실행되는 자바"클래스"

   차이점 : 서블릿은 외부와 소통 가능, 자바 빈은 불가능 (=일반 자바)

   서블릿은 HTTPServlet을 상속받음, 자바빈은 상속받지 않음

   서블릿은 패키지 안써도됨, 자바빈은 써야함

 

 

'IT > 기타 프로그램' 카테고리의 다른 글

[Tomcat] MVC게시판 만들기  (0) 2020.12.14
[Tomcat] 설치 및 환경설정  (0) 2020.12.13

ㅁ 이클립스 환경설정 : UTF-8기준 변경

      Windows -> Preferences ->General - Workspace

        ==> Text file encoding에서 Other를 선택하고 UTF-8로 변경한다

 

                                         Web - CSS Files

        ==> Encoding을 ISO 10646/Unicode(UTF-8)로 변경한다.

     ※ Web - HTML Files, JSP Files도 동일하게 변경한다

   Windows - Preferences를 클릭한다.

 

ㅁ apache tomcat 다운로드

      다운로드 사이트 : tomcat.apache.org/download-90.cgi

 

Apache Tomcat® - Apache Tomcat 9 Software Downloads

Welcome to the Apache Tomcat® 9.x software download page. This page provides download links for obtaining the latest version of Tomcat 9.0.x software, as well as links to the archives of older releases. Unsure which version you need? Specification version

tomcat.apache.org

인스톨로 말고 압축파일로 해당 bit맞게 받고 압축을 푼다

   환경설정->Server->Runtime Enviroments 에서 add->Apache Tomcat v9.0 선택

아파치 버전선택
압축경로 선택후 완료

 

※  http://localhost:8080 접속시 404 에러

    문제는 Tomcat 설치위치에 webapps가 없어서 나는 에러였음

    해결방법은 webapps.dist에 내용을 모두 webapps로 옮겨놓고 재시작하니 정상

    리눅스 서버에서는 curl 을 이용하여

    $curl http://localhost:8080 으로 test

 

ㅁ Tomcat GUI 사용자 변경

    tomcat-users.xml 변경

 

    다음내용이 주석으로되어 있음

    <role rolename="tomcat"/>

    <role rolename="role1"/>

    <user username="tomcat" password="tomcat" roles="tomcat"/>

    <user username="both" password="tomcat" roles="tomcat,role1"/>

    <user username="role1" password="tomcat" roles="role1"/>

 

    다음을 추가해준다.

 

  <role rolename="manager-gui"/>

  <user username="[사용자명]" password="[패스워드]" roles="manager-gui"/>

 

ㅁmanager에  context.xml 수정

     경로: /설치경로/webapps/manager/META-INF/context.xml

     원격허용가능토록수정(위 룰을 해놓았어도 context.xml이 수정되지 않으면 접속불가)

 

변경전)
<Valve className="org.apache.catalina.valves.RemoteAddrValve"
         allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1" />
변경후1) 외부접속 전체허용         
<Valve className="org.apache.catalina.valves.RemoteAddrValve"
         allow=".*" />
변경후2) 외부접속 내부ip허용
<Valve className="org.apache.catalina.valves.RemoteAddrValve"
         allow="192\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1" />

ㅁ log4j 추가 

    biz로그를 별도 처리 

    1) maven 으로 모듈 추가  

<dependency>
	<groupId>log4j</groupId>
	<artifactId>log4j</artifactId>
	<version>1.2.17</version>
</dependency>

    2) log4j.properties 생성

  ※ src 경로에  log4j.properties 파일생성, War파일생성시 webapp/패키지/WEB_INF/classes/에 log4j.properties 생김

# Root logger option

log4j.rootLogger=debug, stdout, logfile
#log4j.rootLogger=info, stdout, logfile

# Direct log messages to stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p (%C{2}:%L) - %m%n

# Direct log message to log file
log4j.appender.logfile=org.apache.log4j.DailyRollingFileAppender
log4j.appender.logfile.DatePattern='.'yyyy-MM-dd
log4j.appender.logfile.File=E:\\Log/application.log
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=[%d{yyyy-MM-dd HH:mm:ss}] %5p (%C{2} - %M:%L) - %m%n
log4j.appender.logfile.Append=true

'IT > 기타 프로그램' 카테고리의 다른 글

[Tomcat] MVC게시판 만들기  (0) 2020.12.14
[Tomcat] 구조 및 개념정리  (0) 2020.12.13

ㅁ Java 환경설정 두가지

    1) eclipse.ini 파일에  맨위 JDK 경로 지정

-vm
C:/Program Files/Java/jdk-11.0.1/bin  
※ 버전 및 경로 맞게 설정 

    2) 환경변수 설정

 

부가설치 및 설정

 - jad : Java class 파일을 역컴파일해서 원문소스를 보여주는 기능

        간단 사용법

 - javaCC : 이놈이 좀 특이한데 컴파일러를 만드는것으로 역공학도구로 많이 사용되어 진다.

 - svn : 특정서버에 소스 버전관리

 - javaDocument 설정

 

  ▶ Jad

    1) Java에 컴파일된 모듈을 반대로 소스로 만드는 것

      jad.exe 다운: http://varaneckas.com/jad/     특정경로 저장 

    2) Jad 플러그인설치

      다운로드 :  http://sourceforge.net/projects/jadclipse/  다운

               net.sf.jadclipse_3.3.0.jar 파일을  이클립스에 plugins폴더에 복사해 넣으면 설치완료 환경설정에 JadClipse 

               메뉴가 보이고 설정을 하고 .class파일을 Jad로 연결

       

  설정1) Jad 설정

Jad 실행파일 등록 및 Decompile시 경로 설정
Decompile 대상 연결 설정

          참고로 모든 확장자에 대한 파일연결 기본설정은 해당 화면에서 처리한다.

 

   JavaCC

     역공학으로 소스분석을 하기위해 사용, 관계없으면 해당설치는 생략한다. 코볼역공학을 한번 활용해봤으나, 다른모듈에 대한 역공학도 가능하다.

   다운로드 : https://sourceforge.net/projects/eclipse-javacc/

   다운파일 : sf.eclipse.javacc-1.5.33-plugin.zip 압축을 풀고 하위에 features, plugins 폴더를

   이클립스에 features, plugins폴더에 복사해 넣으면 설치완료

 

  ▶ SVN설치

     Help  -> Eclipse Marketplace 실행

   검색어에 SVN 입력 검색하고 설치

   ※ 참고로 Marketplace는 이클립스에 플러그인을 어플깔듯 깔수있게 패키지로 되어 있는

      사이트이다.

 

   ▶JavaDocument 설정 

    Java라이브러리에 대한 설명들을 개발시 보여주어 효율적으로 개발할수 있다.

Java Document 설정 확인
Java Document(참고 로칼로 받고 경로 선택도 가능)

 

ㅁ 환경정보 저장/복원 방법

1. File > Export > General > Preference Next.

2. To preference file. 저장경로설정


1. File > Import > General > Preferences Next.

2. From preference file. 파일가져오기

※ 몇개는 해당 메뉴에서 개별로

ㅁ ObjectAid

    클래스 다이어그램를 보는 좋은 툴인데 아쉽게도 이클립스 2018-12-R버전이후 사용할수 없다

    

   ==>   objectaid-1.1.14.zip 파일을 구해서 이클립스 install에 아카이브로 설치 사용

 

    

 

'IT > 개발툴설치' 카테고리의 다른 글

MobaXterm 원격데스크톱 ssh 등등사용  (0) 2021.12.20
Oracle ODBC 설치  (0) 2021.02.28
[SWT] SWT만 설치사용(구방식)  (0) 2020.12.20
[이클립스] WindowBuilder 설치  (0) 2020.11.08
Maven 설치 및 기본사용법  (0) 2020.11.08

VB 참고 사이트

- 기본적인 문법이 잘되어 있음

https://docs.microsoft.com/ko-kr/dotnet/visual-basic/language-reference/

 

엑셀에서 다른 특이한거 하나는 행동을 코딩으로 나오는 매크로라 생각되어 진다.

행동을 기록하여 코딩으로 나온 소스를 보고 이해하고 이용하는것

엑셀도 하나의 좋은 DataBase 이다 .

엑셀파일을 DataBase 에 스키마와 동급이다

엑셀시트는 각각에 해당 테이블과 동급이다

그렇다면 엑셀시트를 query를 사용하여 쓸수 있을까? 쓸수 있다

사이트에서 일하다보면 엑셀로 무수히 많은 엑셀자료를 만들기는 하는데 이걸 참조해서 개발하는 개발자는 너무많은 자료에 치여사는경우가 많다 그래서 생각한것이 하나의 만들어놓은 엑셀에서 관련되어 있는 엑셀을 query를 실행하여 조회하는 메크로를 작성해보았다

전에 Database를 사용하기 위해서는 ODBC드라이버가 있어야된다고 했는데 ODBC드라이버를 확인해보자

 

1) ODBC설치 확인(기본으로 OFFICE를 설치하면 설치된는것을 알수 있다)

2) 참조에 Microsoft ActiveX DataObject 2.8 Library를 추가 : ADODB 객체를 사용하려구 

3) 일단 엑셀을 sql로 조회하기 위한 엑셀을 하나 준비한다

 

 

4) 엑셀을 DataBase처럼 Connection을 실행해서 잘 연결되는지 확인해보자

    특이하게 Provider를 사용하여 쓰고 뒤에 Properties가 더 붙는다

Public dbcon As ADODB.Connection

Public dbcon As ADODB.Connection 

Public Sub ExcelCon()    '=>실행시 문제가 없는지 확인

    Dim strCon  As String '연결String
    Dim driver, dsrc
   
    dsrc = "D:\엑셀DB테스트.xlsx"    '파일명
    
    '엑셀파일을 DataBase처럼 연결
    strCon = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & dsrc & ";Extended Properties=Excel 12.0;"
    Set dbcon = New ADODB.Connection
   
    dbcon.Open strCon      '연결

End Sub

 

5) 연결이 잘되었으면 RecordSet으로 받아 엑셀에 출력을 해보자

Public Sub getExcelEtcSel()

    Dim rs, sql, colCnt, wRow, i
   
    ExcelCon     
    sql = "select * from [Sheet2$] "  '->조건없이 전부 조회
    Debug.Print sql
   
    'Set rs = CreateObject("ADODB.RecordSet")
    Set rs = New ADODB.Recordset
   
    rs.Open sql, dbcon
   
    wRow = ActiveSheet.Range("B4")  '작성시작 row
    colCnt = rs.Fields.Count
    '컬럼에 head를 시작에 달아줌
      For i = 0 To colCnt - 1
          ActiveSheet.Cells(wRow, i + 1) = rs.Fields(i).Name
      Next
      setHeaderStyle wRow     'header 스타일 적용
      wRow = wRow + 1
   
    If rs.EOF = False Then
   

        Do While rs.EOF = False
       
            For i = 0 To colCnt - 1
                ActiveSheet.Cells(wRow, i + 1) = rs(rs.Fields(i).Name)    '레코드셋에 이름으로 매핑하여 표시
            Next
           
            wRow = wRow + 1
            rs.MoveNext
        Loop
    End If

End Sub

 

6) 엑셀에 특정영역중에 query를 사용할경우와 컬럼명을 기술할때 일반 query와 상이함

 sql = "select [컬럼1],[컬럼2] from [Sheet2$A2:G5] "

- 시트전체조회시 [시트명$]

- 시트에일부영역시 [Sheet2$A2:G5] -> sheet2에 A2:G5 영역중 조회

- 컬럼은 위처럼 중괄호를 해야되고 중복된 컬럼명이 있으면 임의로 넘버링을 붙임

 

중복컬럼이 있는경우

조회결과

 

엑셀에서 중요한 기능중 하나가 파일을 READ 하고 WRITE하고 이긴 한데

단독적으로 쓸일은 많지는 않았다 그보다 현재 많은 정보들이 있다보니 각종 소스들에 대해서 목록으로 처리해야될일이 많아졌다 생각 되어진다.

프로젝트에서 말하자면 현황파악

제일먼저 특정경로에 소스를 가져왔을때 해당 소스하위까지 포함하여 폴더에 목록을 엑셀로 작성해보자

 

1) 엑셀시트 화면 구성 

   B1에는 검색하려는 기본경로 기입

   B2에는 기존 목록을 삭제하고 다시 작성할건지 여부

   B3에는 전체작성된 건수를 엑셀함수를 써서 기입 =COUNT(A9:A1048576)

 

2) 소스작성

   먼저 파일을 사용하기 위해 참조를 하자

   직접 CreationObject를 사용하여도 되지만 ctrl+space로 자동완성기능을 사용하기 위하여

   참조를 통하여 객체를 넣는 작업을 한다

 

 

 

다음은 엑셀 코딩을 하자

Option Explicit   '명시적으로 항상 어떤변수를 사용했는지 확인하는게 신상에좋다

Dim wRow        '파일을 엑셀시트에 저장하기 위해 선언==> 말하자면 전역변수선언

Public Sub getFileList()   '==>실행하는 함수
    Dim rc
   
    wRow = 9        '기본은 9부터
    If ActiveSheet.Range("B2") = "Y" Then    '삭제여부를 보고 삭제작업
        rc = MsgBox("삭제해도 될까요?", vbYesNo, "삭제경고")
        If rc = vbYes Then
            Rows(wRow & ":" & wRow).Select
            Range(Selection, Selection.End(xlDown)).Select
            Range(Selection, Selection.End(xlDown)).Select
            Selection.Delete Shift:=xlUp
        Else
            Exit Sub
        End If

        '타이틀을 작성한다
        ActiveSheet.Cells(wRow, 1) = "NO"
        ActiveSheet.Cells(wRow, 2) = "파일명"
        ActiveSheet.Cells(wRow, 3) = "경로"
        ActiveSheet.Cells(wRow, 4) = "타입"
        ActiveSheet.Cells(wRow, 5) = "Size"
        ActiveSheet.Cells(wRow, 6) = "비고"
       
        '이건별도 나만에 함수로 생략 setHeaderStyle wRow     'header 스타일 적용
        wRow = wRow + 1
    Else
        wRow = ActiveSheet.Range("B3") + 10 '삭제를 안하고 추가하는경우 헤더포함하여 다음써야될행

    End If
    
    'b1에 입력된 기본 경로하위 폴더 및 파일목록을 작성시작
    FolderFile ActiveSheet.Range("B1")
   
End Sub


Function FolderFile(fn As String)


 Dim fs As FileSystemObject
 Set fs = New FileSystemObject

 Dim foldeer As Folder
 Dim fileinfo
 Dim Filnavn() As String
 Set foldeer = fs.GetFolder(fn)

 '해당폴더에 파일이 있는경우
 For Each fileinfo In foldeer.Files

        ActiveSheet.Cells(wRow, 1) = wRow - 9  '기본자릿수
        ActiveSheet.Cells(wRow, 2) = fileinfo.Name  '파일명
        ActiveSheet.Cells(wRow, 3) = Mid(fileinfo.path, 1, Len(fileinfo.path) - Len(fileinfo.Name)) 'path에 파일명까지 같이 들어오므로 파일명 길이만큼 잘라path만입력
        ActiveSheet.Cells(wRow, 4) = fileinfo.Type
        ActiveSheet.Cells(wRow, 5) = fileinfo.Size
        wRow = wRow + 1   '작성후 다음위치 + 1
        Debug.Print "F " & fileinfo
 Next

 For Each Folder In foldeer.SubFolders  'sub폴더가 있는경우

        Debug.Print "D " & Folder
        FolderFile (Folder)             '재귀함수로 자신을 다시 부름
 Next

End Function 

파일처리 목록완성 예시

 

3) 하이퍼링크를 활용하여 클릭시 자동열리게 하자

   요즘은 하도 참조하는 문서가 많아 헷갈리는경우가 많다 저같은경우 목록을 작성하고

뒤에 비고란에 확인한 내용 및 주요 참고내용등을 적어놓고 다시 열때는 클리하여 자동열기를 주로 사용하고 있다

파일을 write할때 하이퍼링크 코딩을 넣어주면 된다.

 

'#하이퍼 링크 추가
ActiveSheet.Cells(wRow, 2).Select     '해당위치를 select
'address에는 전체파일명포함 경로, textToDisplay는 파일명
ActiveSheet.Hyperlinks.Add Anchor:=Selection, Address:=fileinfo.path, TextToDisplay:=fileinfo.Name 

 

추가하고 처리시 하이퍼링크건은 파란색 밑줄로 표시가 되고 클리하면 해당소스를 바로 읽게 됨

 

 

버튼 생성

개발도구->삽입->버튼

 

매크로를 매번 실행시 Viaul Basic 에디터에서 실행하기 귀찮기 때문에 실행버튼이 필요한 경우 있다

최초 버튼 생성시

만들고 버튼에 매크로를 변경시(마우스를 이름에 한번클릭시 이름변경가능)

버튼 생성

매크로 지정화면 : 매크로 지정후 확인하면 앞으로 해당 매크로 실행됨

매크로 연결

 

ㅁ 계정관련

▶ root계정로그인
   $mysql -u root -p
   Enter password:[패스워드]
  ※ Mysql(MariaDB동일)은 command나 Sql툴로 접근 command같은 내용이 처리됨 
  
▶ 계정관련
   select host, user, password from user;		               :조회
   create user [계정아이디]@'[접속지제한]' identified by '비밀번호';  :생성
     ※ 접속지제한  % : 전체, localhost : 해당서버만, ip인경우 특정 ip 에서만 접근제어
     ※ 접속지제한에 싱글따옴표 필수, MariaDB는 패스워드 정책에 따라 10글자 필수
   다른 방법으로는

   INSERT INTO user (Host, User, Password) VALUES ('localhost', '계정아이디', password('비밀번호'));
   FLUSH privileges;
   
   delete from user where user='[계정아이디]';
   다른 방법으로는
   drop user '사용자ID'@localhost;

ㅁ 데이터베이스 관리(생성,권한, 권한반영)

▶ DataBase변경
   use mysql
   ※ command 모드에만 적용
   
▶ DataBase(스키마) 관리
   show databases;        : 조회
   create schema DB명;    : 생성
   옵션예) create database DB명 default character set utf8;
   drop database DB명;    : 삭제  
    
▶ 설정변경에 대한 반영 command
     flush privileges

ㅁ 테이블 관리

▶ 테이블 관련 
   - database 테이블조회
     show tables;           
   - 권한 추가: localhost접속시만 처리가능
     grant all privileges on '스키마명'.'테이블명' to '계정명'@'호스트' identified by '계정비밀번호' with grant option;   
       ※스키마명.*  는 해당 스키마에 전부
   - 권한조회
     show grants for '계정명'@'호스트';                          
   - 권한 삭제
     revoke all on '스키마명'.'테이블명' from '계정명'@'호스트';  
     
▶ primary key 관리
   alter table 테이블명 drop primary key;
   alter table 테이블명 add primary key(컬럼명, 컬럼명);

 

ㅁ 테이블 조회

SELECT  
       TABLE_SCHEMA 스키마
      ,TABLE_NAME    테이블영문명 
      ,TABLE_COMMENT 테이블한글명
      ,TABLE_TYPE      테이블타입
      ,TABLE_COLLATION 테이블구조  
      ,TABLE_ROWS      레코드건수
       FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA like '${schema}%'
  AND (TABLE_NAME LIKE '${var}' 
   OR TABLE_COMMENT LIKE '${var}')"
   
스키마명, 테이블명(한글)   

 

ㅁ 컬럼조회

 SELECT ORDINAL_POSITION AS NO
     , (CASE WHEN COLUMN_KEY !='' THEN 'Y' 
               ELSE '' END) PK
     , COLUMN_NAME 영문명
     , COLUMN_COMMENT 한글명 
     ,IS_NULLABLE AS NULLYN
     , DATA_TYPE 데이터타입
     , (case when DATA_TYPE='int' 
             then NUMERIC_PRECISION 
             else CHARACTER_MAXIMUM_LENGTH end) 자릿수
     , NUMERIC_SCALE 소수점
     , ' ' 데이터
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA= '{$schema}'
    AND TABLE_NAME = '${var}'
 ORDER BY ORDINAL_POSITION"

 

 

ㅁ 이름정의

    영역을 선택하고 왼쪽 상단에 정의할 이름을 정의함

 

이름정의 방법

ㅁ 이름정의 활용

    1) 엑셀에 콤보 만들기

   

엑셀콤보

             왼쪽에 콤보를 만들 셀을 선택하고 데이터 유효성 검사 선택

            해당 콤보내용이 나옴

      2) VBA userForm에서 활용

          폼에 콤보 생성

       폼에 이름정의

                         

 

 

ㅁ 테이블스페이스 생성전 점검

SQL>SELECT * FROM DBA_DATA_FILES;                                                        : 테이블스페이스 정보 조회

SQL>SELECT TABLESPACE_NAME, STATUS, CONTENTS FROM DBA_TABLESPACES;  : 테이블스페이스 목록

SQL>SELECT FILE_NAME, BYTES, STATUS FROM DBA_DATA_FILES;                        :테이블스페이스 파일 목록

SQL>SELECT TABLESPACE_NAME, BYTES, BLOCKS FROM DBA_FREE_SPACE;            :테이블스페이스 잔여 공간

 

 

ㅁ 테이블스페이스 생성/삭제 권한설정

SQL>CREATE TABLESPACE work DATAFILE 'work.dat' SIZE 50M AUTOEXTEND ON NEXT 10M;   : tablespace 생성
SQL>ALTER USER [계정명] DEFAULT TABLESPACE work;                                   : user tablespace 할당
SQL>DROP TABLESPACE work INCLUDING CONTENTS AND DATAFILES CASCADE CONSTRAINTS;    : tablespace 삭제

※ 테이블스페이스명 work

※ 참고 사항

더보기
CREATE TABLESPACE  [테이블스페이스명]
DATAFILE 
 '[파일 위치]'
SIZE 
1G (파일 크기 G, M 이런식으로 작성)
AUTOEXTEND 
ON (자동 확장)
NEXT
 10M (확장 크기)
MAXSIZE 
2G; (최대크기)

 

테이블스페이스 online/offline

ALTER TABLESPACE info_data offline;

ALTER TABLESPACE info_data online;

 

생성된 테이블스페이스의 추가하기 공간 늘여주기

ALTER TABLESPACE info_data

ADD DATAFILE '/DATA/oracle/oradata/ORCL/dbf'

SIZE 100m;

 

생성된 테이블스페이스 크기 변경하기

ALTER DATABASE DATAFILE '/DATA/oracle/oradata/ORCL/infodata.dbf'

RESIZE 200M;

 

기존 테이블스페이스에 자동확장 변경하기

ALTER DATABASE DATAFILE '/DATA/oracle/oradata/ORCL/infodata.dbf'

AUTOEXTEND ON NEXT 10m

MAXSIZE 100m;

 

테이블스페이스 삭제

DROP TABLESPACE info_data

INCLUDING CONTENTS

CASCADE CONSTRAINTS;

 

테이블스페이스의 물리적 파일까지 삭제하기

DROP TABLESPACE info_data INCLUDING CONTENTS AND DATAFILES;

 

데이터베이스 사용자 아이디 생성 및 수정

CREATE USER scbyun IDENTIFIED BY scbyun;

 

생성한 유저에 권한주고 연결하기

GRANT RESOURCE, CONNECT TO scbyun;

GRANT DBA TO scbyun;



출처: https://sangchul.kr/468 [변군이글루]

 

ㅁ 테이블 생성 예제

-- 테이블 생성
CREATE TABLE BOARD (
      IDX        NUMBER          NOT NULL PRIMARY KEY
    , NAME       VARCHAR2(50)    NOT NULL
    , EMAIL      VARCHAR2(50)    NOT NULL
    , PASSWD     VARCHAR2(50)    NOT NULL
    , CONTENT    VARCHAR2(1000)  NOT NULL
    , POST_DATE  DATE DEFAULT SYSDATE
);

-- 시퀀스
CREATE SEQUENCE BOARD_SEQ
    START WITH 1
    INCREMENT BY 1
    NOMAXVALUE 
    NOCACHE; 
 
 -- 데이터 입력
INSERT INTO BOARD (
      IDX
    , NAME
    , EMAIL
    , PASSWD
    , CONTENT
) VALUES ( 
      BOARD_SEQ.NEXTVAL
    , 'james'
    , 'james@gmail.com'
    , '1111'
    , '안녕하세요. 제임스입니다.'
);

--테이블 COMMENT설정
COMMENT ON TABLE [태이블명]  IS 'COMMENT내용';
EX) COMMENT ON TABLE EX_TABLE IS '예제테이블';


--컬럼 COMMENT설정
COMMENT ON COLUMN [테이블명].[컬럼명] IS 'COMMENT내용';
EX) COMMENT ON COLUMN EX_TABLE.DEPT IS '부서';

--컬럼 추가 1
ALTER TABLE emp ADD email VARCHAR(25);

--컬럼 추가 2 (기본 값, NOT NULL 지정)
ALTER TABLE emp ADD email VARCHAR(25) DEFAULT 'test@test.com' NOT NULL;


--컬럼 숨김
ALTER TABLE emp MODIFY job INVISIBLE;
--컬럼 보이기
ALTER TABLE emp MODIFY job VISIBLE;

▷ PRIMARY KEY DROP
ALTER TABLE [TABLE 명] DROP PRIMARY KEY
▷ PRIMARY KEY CREATE
ALTER TABLE [TABLE 명] ADD PRIMARY KEY (COL1, COL2, COL3 ...)

+ Recent posts