2021년 12월 18일 토요일

WPF 캔버스(WPF Canvas), WPF동영상교육, WPF교육, WPF학원

 















WPF 캔버스(WPF Canvas)

  • 엘리먼트가 어디에 위치할지 좌표로 지정하는 전통적인 방법이다.
  • WPF의 다른 부분과 마찬가지로 이 좌표계도 좌측 상단을 기준으로 1/96인치의 장치 독립적인 단위를 사용한다.
  • 엘리먼트에는 X, Y, Left, Top과 같은 프로퍼티는 없으며 Canvas 패널을 사용할 때는 Canvas.SetLeft, Canvas.SetTop과 같은 정적메소드를 사용하여 자식엘리먼트의 위치를 지정한다. DockPanel의 SetDock 메소드처럼 SetLeft, SetTop은 Canvas 클래스에 정의되어 있는 첨부 프로퍼티와 연결되어 있다.
  • Canvas의 우측하단을 기준으로 자식 엘리먼트의 오른쪽 또는 하단의 위치를 지정하려면 Canvas.SetRight, Canvas.SetBottom을 사용한다.
  • 몇 가지 Shape 클래스(Line, Path, Polygon, PolyLine등)에는 이미 좌표 데이터가 저장되어 있는데 이런 엘리먼트를 Canvas 패널의 Children 컬렉션에 추가하고 좌표를 지정하지 않으면 엘리먼트에 있는 좌표 데이터를 이용하여 위치를 잡는다.
  • 컨트롤과 같은 엘리먼트는 Canvas 위에서 적절하게 크기가 조절되지만 Rectangle, Ellipse 엘리먼트는 그렇지 않으므로 명시적으로 Width, Height를 대입하는 것이 좋고 Canvas 패널 자체의 Width, Height 프로퍼티에도 값을 지정하는 것이 일반적이다.
  • Example Canvas XAML Code

<Window x:Class="WpfApplication1.MainWindow"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        Title="Canvas Test1" Height="300" Width="300">

    <Canvas>

        <Button Canvas.Left="40">Top left</Button>

        <Button Canvas.Right="80">Top right</Button>

        <Label Content="Label Text" Canvas.Bottom="110" Canvas.Left="110"/>

        <Button Canvas.Left="20" Canvas.Bottom="10">Bottom left</Button>

        <Button Canvas.Right="40" Canvas.Bottom="10">Bottom right</Button>

    </Canvas>

</Window>

  • 비주얼 스튜디오 -> WPF 응용프로그램 -> CanvasTest1
  • MainWindow.xaml

<Window x:Class="CanvasTest1.MainWindow"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

        xmlns:local="clr-namespace:CanvasTest1"

        mc:Ignorable="d"

        Title="Canvas Test1" Height="350" Width="525"

        Loaded="WindowOnLoaded">

    <Grid>

        <Canvas HorizontalAlignment="Left" Height="319" Margin="0"

VerticalAlignment="Top" Width="517"

Name="canvas1"/>

    </Grid>

</Window>

  • MainWindow.xaml.cs

using System.Collections.Generic;

using System.Windows;

using System.Windows.Controls;

using System.Windows.Documents;

using System.Windows.Media;

using System.Windows.Shapes;


namespace CanvasTest1

{

    class MyRectangle

    {

        public int Width { getset; }

        public int Height { getset; }

        public int Left { getset; }

        public int Top { getset; }

        public SolidColorBrush Color { getset; }

    }


    public partial class MainWindow : Window

    {

        public MainWindow()

        {

            InitializeComponent();

        }


        private void WindowOnLoaded(object sender, RoutedEventArgs e)

        {

            // MyRectangle을 담기위한 ArrayList

            List<MyRectangle> rects = new List<MyRectangle>();


            // MyRectangle을 담는다.

            rects.Add(new MyRectangle()

            {

                Width = 100,

                Height = 100,

                Left = 0,

                Top = 0,

                Color = Brushes.MediumSpringGreen

            });

            rects.Add(new MyRectangle()

            {

                Width = 50,

                Height = 50,

                Left = 100,

                Top = 100,

                Color = Brushes.YellowGreen

            });

            rects.Add(new MyRectangle()

            {

                Width = 25,

                Height = 25,

                Left = 150,

                Top = 150,

                Color = Brushes.PowderBlue

            });


            foreach (MyRectangle rect in rects)

            {

                // Rectangle 객체생성

                Rectangle r = new Rectangle();

                r.Width = rect.Width;

                r.Height = rect.Height;

                r.Fill = rect.Color;


                // Canvas내 위치를 기본적인 MyRectangle의 위치로 설정

                Canvas.SetLeft(r, rect.Left);

                Canvas.SetTop(r, rect.Top);


                // Canvas에 추가

                canvas1.Children.Add(r);

            }

        }

    }

}

  • 실행결과


#WPF캔버스, #WPFCanvas, #WPF강좌, #WPF교육, #WPF강의, #WPF학원, #닷넷학원, #시샵교육, #닷넷교육, WPF캔버스, WPFCanvas, WPF강좌, WPF교육, WPF강의, WPF학원, 닷넷학원, 시샵교육, 닷넷교육,



(ORACLE교육동영상)오라클 SQL문 실행과정, 하드파싱, 소프트파싱, 최적화, Optimizer, Row Source Generation, 파싱트리, 오라클학원, 자바학원, 오라클자바동영상

 

(ORACLE교육동영상)오라클 SQL문 실행과정, 하드파싱, 소프트파싱, 최적화, Optimizer, Row Source Generation, 파싱트리, 오라클학원, 자바학원, 오라클자바동영상


http://ojc.asia/bbs/board.php?bo_table=LecSQLnPlSql&wr_id=704 


(ORACLE교육동영상)오라클 SQL문 실행과정, 하드파싱, 소프트파싱, 최적화, Optimizer, Row Source Generation

(ORACLE교육동영상)오라클 SQL문 실행과정, 하드파싱, 소프트파싱, 최적화, Optimizer, Row Source Generation, 파싱트리오라클 SQL문 처리과정파싱, 최적화, 행 소스 생성, 실행(Parsing, Optimization, Row Source Genera

ojc.asia


https://youtu.be/e9lZ0oZNZDo

https://youtu.be/QPf_zMPShZg

https://youtu.be/oR_UKxk_HO4

https://youtu.be/b-IxbRmwpGE

https://youtu.be/32YaMykHAbc

https://youtu.be/BVeBkyIWUrU


오라클 SQL문 처리과정

 

파싱, 최적화, 행 소스 생성, 실행

(Parsing, Optimization, Row Source Generation, Execution)





SQL구문의 실행은 파싱, 최적화(Optimization), Row Source Generation, 그리고 최종 실행과정을 거칩니다. 





  • 사용자가 SQL문장(select)을 실행

- 오라클 서버측 리스너가  요청을 받아 디스패처를 경우하여 서버 프로세스로 SQL문장을 전달 합니다.




 

  • SQL 파싱(구문 분석 단계)

- 클라이언트에서 보내온 SQL 구문이 서버프로세스 PGA 내부의 Private SQL Area에서 문법체크(Syntax Check)를 우선 진행하고, 테이블 및 컬럼이 있는지, 해당 USER가  테이블 및 컬럼을 SELECT할 권한이 있는지(Semantic Check)를 Data Dictionary를 통해 체크한다. 


Shared Pool Check : Shared Pool의 Library Cache를 조회해서 동일한 SQL문장이 있는지 확인하는데 문자 하나하나 공백, 대소문자까지 비교하여 동일한 SQL문장이 있다면 이를 Soft Parsing 이라고 하고 기 생성된 Library Cache의 Query Execution Plan, parse-tree를 가지고 와서 실행 합니다. 동일한 SQL 문장이 없다면 이후 parse-tree를 만들고 추후 사용을 위해 Library Cache에 저장하는데 이를 하드 파싱 이라고 합니다. 소프트 파싱은 optimization, row source generation 과정을 생략하고 직접 execution 단계로 가서 처리를 하게 됩니다.

                                   [SQL문 실행시의 Shared Pool Check]




  • SQL 최적화(Optimization)



  • [그림 : SQL문 처리과정]


Query Transformer : 쿼리블록으로 나누어 변형된 몇가지 종류의 쿼리문을을 생산해서 Estimator에 넘깁니다. 서브쿼리를 조인으로 변경, 뷰의 해체작업, 인라인뷰의 해체작업,                              FROM절의 테이블 제거작업, 조인조건 푸시, 뷰 조건 푸시, 서브쿼리를 조인으로 변경, 조인을 서브쿼리로 변경등 쿼리를 변형 합니다.


Estimator : 주어진 SQL문장의 모든 Cost를 측정한다. Selectivity(선택도), Cardinality, Cost 등 세 가지 다른 측정방법을 이용하며 최소의 비용을 갖는 SQL문장을 Plan Generator에게 넘긴다.     


Plan Generator : 선택된 저비용 SQL문의 실행계획을 생성하여 Row Source Generator에게 넘긴다. 이렇게 생성한 실행계획도 나중을 위해 Library Cache에 저장해 둡니다.


  • Row Source Generation

- 옵티마이저에게 최적의 실행계획을 수신하여 SQL 명령문이 참조하는 테이블의 순서, 테이블에 대한 액세스방법, 조인방법, 필터, 정렬방법등이 기록되어 있는 Row Source Tree와 이를 SQL엔진이 실행 할 수 있도록 실행가능한 바이너리 코드로 생성 합니다. 












SELECT e.last_name, j.job_title, d.department_name 

FROM   hr.employees e, hr.departments d, hr.jobs j

WHERE  e.department_id = d.department_id

AND    e.job_id = j.job_id

AND    e.last_name LIKE 'A%';

실행계획

Execution Plan

----------------------------------------------------------

Plan hash value: 975837011


-----------------------------------------------------------

| Id| Operation                     | Name        |Rows|Bytes|Cost(%CPU)|Time  |

-----------------------------------------------------------

| 0 | SELECT STATEMENT              |             |  3 | 189 | 7(15)| 00:00:01 |

|*1 |  HASH JOIN                    |             |  3 | 189 | 7(15)| 00:00:01 |

|*2 |   HASH JOIN                   |             |  3 | 141 | 5(20)| 00:00:01 |

| 3 |    TABLE ACCESS BY INDEX ROWID| EMPLOYEES   |  3 |  60 | 2 (0)| 00:00:01 |

|*4 |     INDEX RANGE SCAN          | EMP_NAME_IX |  3 |     | 1 (0)| 00:00:01 |

| 5 |    TABLE ACCESS FULL          | JOBS        | 19 | 513 | 2 (0)| 00:00:01 |

| 6 |   TABLE ACCESS FULL           | DEPARTMENTS | 27 | 432 | 2 (0)| 00:00:01 |

-----------------------------------------------------------

해시조인은 드라이빙 테이블을 읽어 메모리에 해시테이블 형태로 생성하고 이것과 후행 테이블의 데이터를 해시함수로 한방에 조인하는 형태로 해시조인을 하는 부분에서 Access Predicate가 발생합니다.

Predicate Information (identified by operation id):

---------------------------------------------------

   1 - access("E"."DEPARTMENT_ID"="D"."DEPARTMENT_ID")

   2 - access("E"."JOB_ID"="J"."JOB_ID")

   4 - access("E"."LAST_NAME" LIKE 'A%')

       filter("E"."LAST_NAME" LIKE 'A%')


Predicate란? 인덱스 접근시 컬럼액세스정보, 조인정보, Filter정보를 실행계획의 각 Operation 단위로 나타낸것 입니다.

access predicate : Data Block을 어떤 방식으로 Access해서 읽었는지를 나타냅니다.

filter predicate : Data Block을 읽고나서 데이터를 어떻게 필터링 했는지를 나타냅니다.


[그림 : Row Source Tree]


출처  https://docs.oracle.com/database/121/TGSQL/tgsql_sqlproc.htm#TGSQL186



  • 실행(Execution)

SQL실행 엔진이 Row Source Tree에 의해 생성된 트리의 각 Row Source를 실행 합니다. 일반적으로 실행 단계의 순서는 실행계획의 순서와 반대이므로 아래에서 위로 읽으면서 SQL결과를 만들어 냅니다. 이미 한번이상 SQL구문이 실행되었다면 Database Buffer Cache에 데이터가 있으므로 메모리 I/o를 통해 빠르게 데이터를 추출하는데, 그렇지 않다면 하드디스크의 Datafile에서 블록 단위로 데이터를 읽어 Database Buffer Cache에 적재후 클라이언트로보내게 됩니다. 


  • 추출(Fetch)

서버 프로세스가 Database Buffer Cache에 저장된 데이터를 읽어 User Process에게 결과를 넘겨준다.(DML인 경우에는 수행하지 않습니다.)



 


#ORACLE교육, #오라클동영상, #SQL문실행과정, #SQL실행순서, #하드파싱, #소프트파싱, #최적화, #Optimizer, #RowSourceGeneration, #파싱트리, #오라클교육, #ORACLE교육, #SQL교육, #SQL학원, #오라클학원, #ORACLE학원, ORACLE교육, 오라클동영상, SQL문실행과정, SQL실행순서, 하드파싱, 소프트파싱, 최적화, Optimizer, RowSourceGeneration, 파싱트리, 오라클교육, ORACLE교육, SQL교육, SQL학원, 오라클학원, ORACLE학원,  

[JDK PROXY예제,자바프록시예제]InvocationHanlder를 이용한 프록시메소드의 리턴값 가로채기, 자바교육, JAVA교육, 자바동영상, JAVA학원

 







Target Class의 프록시 메소드인 sayHello의 리턴값이 InvocationHandler구현 클래스 HelloWorldHandler의 invoke 메소드의 리턴값으로 대체됨을 확인 할 수 있는데 예제를 이해하자.


InvocationHandler 인터페이스는 java.lang.reflect 패키지의 인터페이스이며 JDK1.3 이후에 나온 것 인데 프록시 호출 핸들러에 의해 구현되어야 하는 메소드 이다.


이 프록시 기반 프로그래밍의 구조를 이해하는 것은 Spring AOP 프로그래밍을 이해하는데 도움이 된다.


package onj.edu.jdkproxy;


//jdk.lanf.Proxy를 이용하는 방법은 Proxy 인터페이스를 이용하여

//객체를 생성하므로 반드시 인터페이스 필요, 인테페이스가 없는 경우 CGLIB이용

public interface HelloWorld {

public String sayHello(String msg);

}



package onj.edu.jdkproxy;


public class HelloWorldImpl implements HelloWorld{

public String sayHello(String msg) {

return "오라클자바에 오신것을 환영 합니다.... " + msg;

}

}



package onj.edu.jdkproxy;


import java.lang.reflect.InvocationHandler;

import java.lang.reflect.Method;


public class HelloWorldHandler implements InvocationHandler {

private Object targetObj = null;


public HelloWorldHandler(Object target) {

this.targetObj = target;

}


public Object invoke(Object obj, Method method, Object[] args)

throws Throwable {


System.out.println("method name : " + method.getName());

Object o = method.invoke(targetObj, args);

System.out.println("method.invoke return값 : " + o);

return "이걸로 리턴....";

}

}




package onj.edu.jdkproxy;


import java.lang.reflect.Proxy;


/**

* 객체의 메쏘드를 호출할 때 직접 객체를 호출하는 방식이 아니라,

* HelloHandler라는 프록시 객체를 이용하는 방식이다.

* HelloHandler는 invoke라는 메쏘드를 통해서 지정된 객체의 함수를 실행하는데

*/

public class JdkProxyClient {

public static void main(String[] args) {

try {

Class[] arrClass = {HelloWorld.class};

//HelloWorldHandler에는 target 객체를 인자로 넣어준다.

HelloWorldHandler handler = new HelloWorldHandler(new HelloWorldImpl());

HelloWorld proxy = (HelloWorld)Proxy.newProxyInstance

(HelloWorld.class.getClassLoader(), arrClass, handler);

String s = proxy.sayHello("your name...");

System.out.println("Proxy 호출 후 ==> " + s);

} catch(Exception e) {

e.printStackTrace();

}

}

}




[결과]


method name : sayHello

method.invoke return값 : 오라클자바에 오신것을 환영 합니다.... your name...

Proxy 호출 후 ==> 이걸로 리턴....



#자바프록시, #프록시란, #자바교육, #자바학원, #JAVA교육, #JAVA학원, #InvocationHanlder, 자바프록시, 프록시란, 자바교육, 자바학원, JAVA교육, JAVA학원, InvocationHanlder,

(C#교육동영상)C# ADO.NET 실습 ODP.NET/ODAC 설치 오라클 함수 호출 실습, C#학원, WPF학원, 닷넷학원, 자바학원

  (C#교육동영상)C# ADO.NET 실습  ODP.NET/ODAC 설치  오라클 함수 호출 실습, C#학원, WPF학원, 닷넷학원, 자바학원 https://www.youtube.com/watch?v=qIPU85yAlzc&list=PLxU-i...