<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
	<channel>
		<title>xylosper&#039;s notebook</title>
		<link>http://xylosper.net/</link>
		<description></description>
		<language>ko</language>
		<pubDate>Wed, 28 Oct 2009 17:30:47 +0900</pubDate>
		<generator>Textcube 1.7.8 : Con moto</generator>
		<image>
		<title>xylosper&#039;s notebook</title>
		<url>http://xylosper.net/attach/1/1308911695.jpg</url>
		<link>http://xylosper.net/</link>
		<width>155</width>
		<height>80</height>
		<description></description>
		</image>
		<item>
			<title>파동을 나타내는 식</title>
			<link>http://xylosper.net/136</link>
			<description>고등학생 떄 살짝 물리 공부좀 많이 했다 하면 &#039;파동 방정식&#039;이라는 걸 들어보았을 것이다.&lt;br&gt;사실, 일반적으로 &#039;파동 방정식&#039;이라고 하면 다음과 같은 2계 편미분 방정식을 가리킨다.&lt;br&gt;&lt;p class=&quot;XyLaTeXEquationParagraph&quot; style=&quot;text-align:center; padding:0px; margin:0px;&quot;&gt;&lt;img class=&quot;XyLaTeXEquationImage&quot; src=&quot;http://www.codecogs.com/gif.latex?\small \frac{\partial^2 }{\partial t^2} u(x,t)=c^2 \frac{\partial^2 }{\partial x^2}u(x,t)&quot; alt=&quot;\frac{\partial^2 }{\partial t^2} u(x,t)=c^2 \frac{\partial^2 }{\partial x^2}u(x,t)&quot; /&gt;&lt;/p&gt;&lt;br&gt;고등학교의 파동에서는 파동방정식이란 이름으로 다음과 같은 식이 소개된다.&lt;br&gt;&lt;p class=&quot;XyLaTeXEquationParagraph&quot; style=&quot;text-align:center; padding:0px; margin:0px;&quot;&gt;&lt;img class=&quot;XyLaTeXEquationImage&quot; src=&quot;http://www.codecogs.com/gif.latex?\small u(x,y)=A\sin(kx-\omega t +\phi)&quot; alt=&quot;u(x,y)=A\sin(kx-\omega t +\phi)&quot; /&gt;&lt;/p&gt;&lt;br&gt;이식은 그 위에 적은 파동방정식의 기본해이다.&lt;br&gt;이것이 해가 된다는 것은 직접 대입해보면 간단하게 확인 할 수 있지만, 진동을 사인파로 나타냈을 때, 그것을 평행 이동시킴으로써 간단히 이 식을 도출하는 것도 가능하다.&lt;br&gt;&lt;br&gt;우선 &lt;img class=&quot;XyLaTeXEquationImage&quot; src=&quot;http://www.codecogs.com/gif.latex?\small t=0&quot; alt=&quot;t=0&quot; /&gt;일 때, 각 위치 &lt;img class=&quot;XyLaTeXEquationImage&quot; src=&quot;http://www.codecogs.com/gif.latex?\small x&quot; alt=&quot;x&quot; /&gt;에서의 진동의 변위가 다음과 같이 주어졌다고 하자.&lt;br&gt;&lt;p class=&quot;XyLaTeXEquationParagraph&quot; style=&quot;text-align:center; padding:0px; margin:0px;&quot;&gt;&lt;img class=&quot;XyLaTeXEquationImage&quot; src=&quot;http://www.codecogs.com/gif.latex?\small u(x)=A\sin\left(\frac{2\pi}{\lambda}x+\phi\right)&quot; alt=&quot;u(x)=A\sin\left(\frac{2\pi}{\lambda}x+\phi\right)&quot; /&gt;&lt;/p&gt;&lt;br&gt;여기서 &lt;img class=&quot;XyLaTeXEquationImage&quot; src=&quot;http://www.codecogs.com/gif.latex?\small \lambda&quot; alt=&quot;\lambda&quot; /&gt;는 파동의 파장을 나타내고, &lt;img class=&quot;XyLaTeXEquationImage&quot; src=&quot;http://www.codecogs.com/gif.latex?\small \phi&quot; alt=&quot;\phi&quot; /&gt;는 초기위상을 나타낸다.&lt;br&gt;파동은 진동이 시간에 따라서 전파된다.&lt;br&gt;파동의 전파 속도를 &lt;img class=&quot;XyLaTeXEquationImage&quot; src=&quot;http://www.codecogs.com/gif.latex?\small v&quot; alt=&quot;v&quot; /&gt;라고 하면, 시간이 &lt;img class=&quot;XyLaTeXEquationImage&quot; src=&quot;http://www.codecogs.com/gif.latex?\small t&quot; alt=&quot;t&quot; /&gt;만큼 흘렀을 때 이 파동은 &lt;img class=&quot;XyLaTeXEquationImage&quot; src=&quot;http://www.codecogs.com/gif.latex?\small vt&quot; alt=&quot;vt&quot; /&gt;만큼 전파된다.&lt;br&gt;따라서, 시간&lt;img class=&quot;XyLaTeXEquationImage&quot; src=&quot;http://www.codecogs.com/gif.latex?\small t&quot; alt=&quot;t&quot; /&gt;후의 파동은, 처음의 파동을 진행방향으로 &lt;img class=&quot;XyLaTeXEquationImage&quot; src=&quot;http://www.codecogs.com/gif.latex?\small vt&quot; alt=&quot;vt&quot; /&gt;만큼 평행이동시키면 된다.&lt;br&gt;만약 파동이 &lt;img class=&quot;XyLaTeXEquationImage&quot; src=&quot;http://www.codecogs.com/gif.latex?\small +x&quot; alt=&quot;+x&quot; /&gt;방향으로 전파된다면, &lt;img class=&quot;XyLaTeXEquationImage&quot; src=&quot;http://www.codecogs.com/gif.latex?\small vt&quot; alt=&quot;vt&quot; /&gt;만큼 평행이동 시킨 식은&lt;br&gt;&lt;p class=&quot;XyLaTeXEquationParagraph&quot; style=&quot;text-align:center; padding:0px; margin:0px;&quot;&gt;&lt;img class=&quot;XyLaTeXEquationImage&quot; src=&quot;http://www.codecogs.com/gif.latex?\small u(x,t)=u(x-vt)=A\sin\left[\frac{2\pi}{\lambda}(x-vt)+\phi\right]&quot; alt=&quot;u(x,t)=u(x-vt)=A\sin\left[\frac{2\pi}{\lambda}(x-vt)+\phi\right]&quot; /&gt;&lt;/p&gt;&lt;br&gt;가 될 것이다.&lt;br&gt;이것으로 &#039;고등학교의&amp;nbsp; 파동방정식&#039;이 유도되었다.&lt;br&gt;처음에 제시한 식과 비교하면 사인 안의 모양이 전혀 다르게 보인다.&lt;br&gt;모양을 같게 하는 건 단순히 몇가지 변수를 새로 넣기만 하면된다.&lt;br&gt;우선, 이 파동의 진동 주기를 &lt;img class=&quot;XyLaTeXEquationImage&quot; src=&quot;http://www.codecogs.com/gif.latex?\small T&quot; alt=&quot;T&quot; /&gt;라고 하면, &lt;img class=&quot;XyLaTeXEquationImage&quot; src=&quot;http://www.codecogs.com/gif.latex?\small v=\lambda/T&quot; alt=&quot;v=\lambda/T&quot; /&gt;이므로, &lt;br&gt;&lt;p class=&quot;XyLaTeXEquationParagraph&quot; style=&quot;text-align:center; padding:0px; margin:0px;&quot;&gt;&lt;img class=&quot;XyLaTeXEquationImage&quot; src=&quot;http://www.codecogs.com/gif.latex?\small u(x,t)=A\sin\left[\frac{2\pi}{\lambda}\left(x-\frac{\lambda}{T}t\right)+\phi\right]&quot; alt=&quot;u(x,t)=A\sin\left[\frac{2\pi}{\lambda}\left(x-\frac{\lambda}{T}t\right)+\phi\right]&quot; /&gt;&lt;/p&gt;&lt;br&gt;라고 바꿔 쓸수 있다.&lt;br&gt;여기서,  다음 두가지 변수를 도입한다.&lt;br&gt;&lt;p class=&quot;XyLaTeXEquationParagraph&quot; style=&quot;text-align:center; padding:0px; margin:0px;&quot;&gt;&lt;img class=&quot;XyLaTeXEquationImage&quot; src=&quot;http://www.codecogs.com/gif.latex?\small k=\frac{2\pi}{\lambda},\quad \omega=\frac{2\pi}{T}&quot; alt=&quot;k=\frac{2\pi}{\lambda},\quad \omega=\frac{2\pi}{T}&quot; /&gt;&lt;/p&gt;&lt;br&gt;식의 사인안의 괄호를 전개하여 위 두 변수를 대입하면&lt;br&gt;&lt;p class=&quot;XyLaTeXEquationParagraph&quot; style=&quot;text-align:center; padding:0px; margin:0px;&quot;&gt;&lt;img class=&quot;XyLaTeXEquationImage&quot; src=&quot;http://www.codecogs.com/gif.latex?\small u(x,y)=A\sin(kx-\omega t +\phi)&quot; alt=&quot;u(x,y)=A\sin(kx-\omega t +\phi)&quot; /&gt;&lt;/p&gt;&lt;br&gt;라는, 원하던 식이 나오게 된다.&lt;br&gt;&lt;br&gt;마지막에 도입한 두 변수는 각각 &#039;파수(혹은 전파수)&#039;, &#039;각진동수(혹은 각주파수)&#039;라고 불리는 물리량이다.&lt;br&gt;사실 고등학교의 물리에서는 이 두 물리량이 가지는 의미는 그리 크지 않다.&lt;br&gt;그나마 각진동수정도는 원운동의 각속도와 연관지어 생각할 수 있지만, 파수는  특히나 1차원 문제에서는 별 의미가 없어서 보이고, 단순히 식을 간단하게 하기 위한 물리량으로 보일 것이다.&lt;br&gt;파수는 사실 파장보다 더 많은 정보를 포함하는 물리량으로, 대학물리를 배우게 되면 파수가 가지는 의미를 알게 될 것이다.&lt;br&gt;</description>
			<category>Physics</category>
			<author>(xylosper)</author>
			<guid>http://xylosper.net/136</guid>
			<comments>http://xylosper.net/136#entry136comment</comments>
			<pubDate>Mon, 19 Oct 2009 01:26:59 +0900</pubDate>
		</item>
		<item>
			<title>Qt에 대하여 - 13. 실전! - 텍스트 에디터(4) : 디자이너로 메인윈도우 만들기</title>
			<link>http://xylosper.net/134</link>
			<description>디자이너를 이용하면 메인윈도우도 간단히 만들수 있습니다.&lt;br&gt;특히 많은 메뉴들과 툴바아이콘들을 배치해야 할 경우 보면서 할수있기에 편리합니다.&lt;br&gt;&lt;br&gt;디자이너로 메인윈도우를 만들려면, 디자이너를 실행시키고 메인윈도우를 선택합니다.&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;img src=&quot;http://xylosper.net/attach/1/1338382056.png&quot; alt=&quot;&quot; height=&quot;386&quot; width=&quot;530&quot; /&gt;&lt;p class=&quot;cap1&quot;&gt;메인 윈도우 만들기&lt;/p&gt;&lt;/div&gt;&lt;br&gt;메인윈도우를 생성하고 나면 메뉴바 위치에 Type Here 라는 문구가 보입니다. 여기서부터 메뉴와 액션들을 추가해 갈수 있습니다.&lt;br&gt;&lt;br&gt;참고로 여기서부터는 메뉴와 각종 텍스트는 영어로 작성하도록 하겠습니다.&lt;br&gt;이유는 기본 언어를 영어로 하고, 번역판으로 한국어를 제공하는 방식으로 하기 위해서 입니다.&lt;br&gt;물론 기본 언어를 한국어로 해도 되고, 국내이용자만을 대상으로 하는 경우라면 그걸로도 충분 할 것입니다.&lt;br&gt;이에 따른 차이는 나중에 또 별도로 설명하겠습니다.&lt;br&gt;&lt;br&gt;한번 파일 메뉴와 새 파일 액션을 추가해보세요. Type Here 라는 곳을 더블 클릭하여 &amp;amp;File 이라고 입력한 후 엔터를 누르면 파일 메뉴가 생성됩니다.&lt;br&gt;이상태에서 파일 메뉴를 클릭하면 메뉴창이 열리고 그 아래에는 또 Type Here 이라는 문구와, Add Seperator 라는 문구가 보입니다.&lt;br&gt;Type Here를 더블 클릭하고 메뉴를 생성할 때와 같은 요령으로 &amp;amp;New File 이라고 입력하면 새 파일 액션이 생성됩니다.&lt;br&gt;그런데 새 파일 액션의 오랜쪽에 + 같은 모양의 아이콘이 보일 것입니다.&lt;br&gt;이 아이콘은 액션을 메뉴로 확장하는 아이콘으로, 하위 메뉴를 만들 때 이용합니다.&lt;br&gt;&lt;br&gt;메뉴와 액션의 문자열을 고치고 싶을 때는 메뉴상에서 더블 클릭하여 고치면되며, 그외의 속성들을 수정할 때는, 다른 위젯들과 동일하게 Object Inspector와 Property Editor를 이용하여 수정할 수 있습니다.&lt;br&gt;또한, 액션의 경우 액션만을 위한 Action Editor 라는 것이 제공됩니다.&lt;br&gt;Action Editor는 디자이너의 기본 레이아웃이라면 오른쪽 하단의 Signal/Slot Editor와 겹쳐져 있으니, Action Editor 탭을 눌러서 표시할 수 있습니다.&lt;br&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;img src=&quot;http://xylosper.net/attach/1/1069691648.png&quot; alt=&quot;&quot; height=&quot;294&quot; width=&quot;400&quot; /&gt;&lt;p class=&quot;cap1&quot;&gt;Action Editor&lt;/p&gt;&lt;/div&gt;Action Editor를 보면 방금 만든 새 파일 액션이 보입니다.&lt;br&gt;한번 더블 클릭해보면, Edit Action이라는 다이얼로그가 나타납니다.&lt;br&gt;이 다이얼로그는 Property Editor에서 특히 액션의 경우 자주 편집되는 부분만 모아 놓은 것이라고 생각하면 됩니다.&lt;br&gt;ToolTip외에는 별도로 항목에 대한 설명은 필요 없어 보입니다.&lt;br&gt;&lt;br&gt;우선 아이콘을 지정해봅시다.&lt;br&gt;이전과 마찬가지로 로컬 파일을이용할 수 도 있고, Qt의 리소스를 이용할 수도 있습니다.&lt;br&gt;Qt의 리소스를 이용하는 경우, 디자이너를 이용하여 리소스를 쉽게 관리할 수 있습니다.&lt;br&gt;여기서는 Qt 리소스를 이용하는 법도 배울 겸, 리소스를 이용하여 아이콘을 지정해보겠습니다.&lt;br&gt;Icon 항목의 오른쪽의 ... 버튼을 클릭해보면 Select Resource 다이얼로그가 나타납니다.&lt;br&gt;하지만 현재 불러온 리소스 파일이 없기 때문에 아무것도 선택할 수 없습니다.&lt;br&gt;여기서 상단의 연필 모양 버튼을 클릭하면 Edit Resources 다이얼로그가 나타납니다.&lt;br&gt;이 창의 하단을 보면 왼쪽에 두개의 버튼이 활성화되있는데요, 왼쪽은 새로운 리소스 파일(.qrc)파일을 만드는 버튼이고, 오른쪽은 기존의 리소스 파일을 여는 버튼입니다.&lt;br&gt;&lt;br&gt;이전에 만들었던 리소스 파일을 열어 보면 이전에 넣어 둔 아이콘 파일이 하나 표시될 것입니다.&lt;br&gt;여기서는 연습 삼아 새로운 리소스 파일을 만들어 보겠습니다.&lt;br&gt;열린 리소스 파일을, 왼쪽의 X 버튼으로 닫고, 새 리소스 파일을 만듭니다.&lt;br&gt;여기서는 이전에 만든 resources.qrc 파일에 덮어 씌우겠씁니다.&lt;br&gt;이제 오른쪽 버튼들이 활성화 됩니다.&lt;br&gt;우선 + 버튼을 눌러서 prefix를 추가합니다.&lt;br&gt;prefix는 리소스에 접근 할때의 최상위 경로로 보통은 / 로 하면됩니다.&lt;br&gt;그후 오른쪽에서 두번째 버튼으로 리소스를 엽니다.&lt;br&gt;이전에 첨부한 소스 파일을 보면, img 디렉토리 안에 두개의 이미지 파일이 있습니다.&lt;br&gt;두개 모두 선택하여 추가 한후 OK 버튼을 누르면 리소스 파일이 편집되어 저장됩니다.&lt;br&gt;참고로 리소스를 삭제할 때는 제일 오른쪽의 - 버튼을 이용하면 됩니다.&lt;br&gt;또, 리소스는 Action Editor의 오른쪽 탭에 있는 Resource Browser를 통해서도 열람/편집이 가능합니다.&lt;br&gt;&lt;br&gt;다시 Select Resource 창으로 돌아왔습니다,&lt;br&gt;이제 방금 추가한 두개의 이미지를 선택할 수 있습니다.&lt;br&gt;적당한 이미지를 선택한 후, OK를 누르면 아이콘이 선택된 것을 확인 할 수 있습니다.&lt;br&gt;&lt;br&gt;그외에 Object name은 원하는 이름으로(저는 newFileAction)으로 입력하시고, Shortcut으로 단축키를지정합니다(저는 Ctrl+N).&lt;br&gt;단축키는 오른쪽의 화살표 버튼을 클릭한후 실제로 키보드로 원하는 단축키를 누르면 자동으로 입력됩니다.&lt;br&gt;&lt;br&gt;이것으로 액션편집이 끝났습니다.&lt;br&gt;이번에는 툴바를 만들어 보겠습니다.&lt;br&gt;메인 윈도우의 적당히 가운데에서 오른쪽 클릭을 해보면 Add Tool Bar라는 메뉴가 제일 상단에 나타납니다.&lt;br&gt;이 메뉴를 선택하면 메뉴바 밑에 가느다란 툴바가 추가 됩니다.&lt;br&gt;툴바가 가느다란 이유는 아직 아무것도 안들어 있기 때문입니다.&lt;br&gt;여기에 방금 만든 새파일 메뉴를 추가해보겠습니다.&lt;br&gt;Action Editor에서 추가할 액션을 드래그 하여 툴바에 드랍하면 됩니다.&lt;br&gt;&lt;br&gt;마지막으로 메인 윈도우의 central widget을 지정해봅시다.&lt;br&gt;정확히 말하면, 디자이너에서 만든 메인윈도우의 경우 central widget은 무조건 평범한 QWidget이 들어가게됩니다.&lt;br&gt;그대신 디자이너에서는 그 위젯 안에 다른 위젯을 넣어서 표시할 수가 있습니다.&lt;br&gt;우리는 텍스트 에디터를 만들고 있으므로 왼쪽에서 Text Edit 위젯을 가져오서 메인 윈도우의 가운데에 놓고, Object Name을 edit로 지정합니다.&lt;br&gt;그후 방금 내려놓은 Text Edit 외의 적당히 다른 부분을 클릭하면 상단의 레이아웃 툴바가 활성화됩니다.&lt;br&gt;이상태에서 적당한 레이아웃(여기서는 다른 위젯을 배치하지는 않으므로 아무거나 상관없습니다).&lt;br&gt;여기서 레이아웃을 지정해야 하는 이유는 자동으로 크기가 조절되도록 하기 위해서 입니다.&lt;br&gt;저는 Lay Out Horizontally 를 선택하였습니다.&lt;br&gt;그런데 이상태로는 Text Edit 상하좌우로 여백이 들어가 버립니다.&lt;br&gt;이 여백은, 레이아웃을 넣은 위젯의 property에서 없앨 수가 있습니다.&lt;br&gt;Object Inspector에서 방금 레이아웃을 넣은 위젯(아마도 특별히 수정하지 않았으면 centralwidget이라고 되어있는 위젯)을 선택한 후, Property Editor의 가장 아래쪽을 보면 Layout 이라는 항목이 보일 것입니다.&lt;br&gt;여기서 LayoutLeftMargin, LayoutRightMargin, LayoutTopMargin, LayoutBottomMargin을 0으로 입력해주면 Text Edit 주변의 여백이 없어질 것입니다.&lt;br&gt;&lt;br&gt;마지막으로 메인윈도우의 프로퍼티에서 윈도우 아이콘으로 리소스의 document-edit.png 파일을 선택해주고, 윈도우 타이틀도 적당히 적어줍시다(저는 Text Editor라고 해주었습니다).&lt;br&gt;이상태에서 Ctrl+R을 눌러 미리보기를 해봅시다.&lt;br&gt;겉모습만 보면 이전에 만든 texteditor 프로그램과 동일 할 것입니다.&lt;br&gt;이 상태에서 한번 툴바의 버튼에 마우스 커서를 올려놓고 가만히 둬보세요.&lt;br&gt;New File이라는 작은 텍스트가 표시됩니다.&lt;br&gt;이것이 아까 설명하지 않고 지나간 액션의 ToolTip입니다.&lt;br&gt;기본적으로는 액션의 Text가 그대로 표시되지만, ToolTip을 적당히 수정하여 원하는 텍스트가 표시되게 할 수도 있습니다.&lt;br&gt;&lt;br&gt;여기서 작성한 파일을 mainwindow.ui라는 이름으로 저장한 후, 실제 코드에서 불러와서 적용합니다.&lt;br&gt;우선 새로운 ui파일을 만들었으므로 프로필 파일(texteditor.pro)에 다음과 같이 FORMS 항목을 추가해줍니다.&lt;br&gt;&lt;br&gt;FORMS += mainwindow.ui&lt;br&gt;&lt;br&gt;그리고 mainwindow.cpp를 대대적으로 수정해줍니다.&lt;br&gt;&lt;br&gt;[code]#include &quot;mainwindow.h&quot;&lt;br&gt;#include &quot;ui_mainwindow.h&quot;&lt;br&gt;&lt;br&gt;struct MainWindow::Data {&lt;br&gt;&amp;nbsp; &amp;nbsp; Ui::MainWindow ui;&lt;br&gt;};&lt;br&gt;&lt;br&gt;MainWindow::MainWindow(QWidget *parent)&lt;br&gt;: QMainWindow(parent), d(new Data) {&lt;br&gt;&amp;nbsp; &amp;nbsp; d-&amp;gt;ui.setupUi(this);&lt;br&gt;&amp;nbsp; &amp;nbsp; &lt;br&gt;&amp;nbsp; &amp;nbsp; connect(d-&amp;gt;ui.newFileAction, SIGNAL(triggered()), this, SLOT(newFile()));&lt;br&gt;}&lt;br&gt;&lt;br&gt;MainWindow::~MainWindow() {&lt;br&gt;&amp;nbsp; &amp;nbsp; delete d;&lt;br&gt;}&lt;br&gt;&lt;br&gt;void MainWindow::newFile() {&lt;br&gt;&amp;nbsp; &amp;nbsp; d-&amp;gt;ui.edit-&amp;gt;clear();&lt;br&gt;}&lt;br&gt;[/code]&lt;br&gt;기본적인 요령은 이전에 설명한 폼 디자인 적용하기와 마찬가지로, setupUi() 함수를 호출 하여 줍니다.&lt;br&gt;이전 소스와 비교해보면 아시겠지만 메인 윈도우에서 메뉴바나 툴바를 생성하는 과정이 디자이너를 이용함으로서 생략되어 훨씬 간략한 소스가 되었습니다.&lt;br&gt;그리고 액션이나 Text Edit는 이제 Ui::MainWindow의 멤버이기 때문에 d-&amp;gt;edit 등은 d-&amp;gt;ui.edit 등으로 수정해주었습니다.&lt;br&gt;&lt;br&gt;마지막으로 소스파일을첨부하고  디자이너를 이용한 메인윈도우 만들기를 마칩니다.&lt;br&gt;첨부한 소스파일에는, 이외에도 별도의 설명없이 간단히 구현할 수 있는 몇가지 메뉴가 더 추가되어있습니다.&lt;br&gt;소스코드를 보시고 이해가 안되시면 질문해주세요.&lt;br&gt;&lt;br&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;a class=&quot;extensionIcon&quot; href=&quot;http://xylosper.net/attachment/1040521573.gz&quot;&gt;&lt;img src=&quot;http://xylosper.net/image/extension/gz.gif&quot; alt=&quot;&quot; /&gt; texteditor.tar.gz&lt;/a&gt;&lt;p class=&quot;cap1&quot;&gt;예제 소스코드&lt;/p&gt;&lt;/div&gt;&lt;br&gt;</description>
			<category>Qt</category>
			<category>Designer</category>
			<category>main window</category>
			<category>QAction</category>
			<category>QMainWindow</category>
			<category>Qt</category>
			<category>디자이너</category>
			<author>(xylosper)</author>
			<guid>http://xylosper.net/134</guid>
			<comments>http://xylosper.net/134#entry134comment</comments>
			<pubDate>Tue, 08 Sep 2009 09:42:42 +0900</pubDate>
		</item>
		<item>
			<title>근황</title>
			<link>http://xylosper.net/133</link>
			<description>어느새 방학도 끝나고 4학년이 되어 연구실 배정까지 끝났습니다.&lt;br&gt;&lt;br&gt;어떻게 본격적으로 시작하기 전에 CMPlayer도 마이너 버전업이 가능했고...&lt;br&gt;학교 다니면서 여유가 있을지 없을지 모르기에, CMPlayer는 일단 여기서 일단락 짓고, 당분간은 0.3.x에서 버그패치나 하게 될듯합니다.&lt;br&gt;&lt;br&gt;사실 GStreamer용 재생엔진을 이전부터 준비해왔었는데, 아무래도 GStreamer는 버그가 너무 많아서 이쪽은 당분간 접을 듯합니다.&lt;br&gt;거의 반년전부터 준비해온 것이라 만든게 아까워서라도 어떻게 해볼려고 했는데, 좀더 GStreamer가 안정적으로 작동하게 될때로 미루어야겠습니다.&lt;br&gt;대신 VLC를 이용해볼까 해서 이리저리 보고는 있는데 어떻게 될지 모르곘네요.&lt;br&gt;&lt;br&gt;연구실은 들어갔지만 아직 연구 테마는 정해지지 않았습니다.&lt;br&gt;대충 생각하고 있는 것은 있지만 좀더 선생님과 상담을 해보고 결정해야겠지요.&lt;br&gt;뭐 사실상 1학기는 &#039;공부&#039;가 중점이기 떄문에 어쩌면 2학기가 되고서야 결정하게 될지도 모르겠습니다.&lt;br&gt;&lt;br&gt;4월도 어느덧 하순에 들어가고, 다른 동네는 벚꽃도 지고 있지만, 이동네는 아직 피지도 않았습니다.&lt;br&gt;기온도 아직 아침 밤으로는 꽤 쌀쌀하네요.&lt;br&gt;그래도 이불은 살짝 얇은 이불로 바꿨습니다. 그래도 솜이불이지만요.&lt;br&gt;&lt;br&gt;그나저나 거의 수업이 없거나 오후에나 있다보니 방학이 끝났음에도 불구하고 아직도 주침야활의 생활에서 벗어나지 못하고 있습니다.&lt;br&gt;오늘은 주침을 생략하고 야침을 할 수 있도록 노력해보겠지만 어떻게 될지 모르겠네요.&lt;br&gt;</description>
			<category>Trivia</category>
			<category>CMPlayer</category>
			<category>근황</category>
			<category>대학</category>
			<category>연구실</category>
			<author>(xylosper)</author>
			<guid>http://xylosper.net/133</guid>
			<comments>http://xylosper.net/133#entry133comment</comments>
			<pubDate>Sun, 19 Apr 2009 07:24:36 +0900</pubDate>
		</item>
		<item>
			<title>Qt에 대하여 - 12. 실전! - 텍스트 에디터(3) : 리소스</title>
			<link>http://xylosper.net/132</link>
			<description>실제로 어플리케이션을 만들다보면, 모든 것이 소스코드만으로 해결되지 않는 경우가 많습니다.&lt;br&gt;그 대표적인 예가 어플리케이션에서 이용하는 아이콘들입니다.&lt;br&gt;이번 회에서는 어플리케이션과 액션에 아이콘을 적용해보고, Qt의 리소스에 대해서 알아보겠습니다.&lt;br&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;a class=&quot;extensionIcon&quot; href=&quot;http://xylosper.net/attachment/1002676955.gz&quot;&gt;&lt;img src=&quot;http://xylosper.net/image/extension/gz.gif&quot; alt=&quot;&quot; /&gt; texteditor.tar.gz&lt;/a&gt;&lt;p class=&quot;cap1&quot;&gt;예제 파일&lt;/p&gt;&lt;/div&gt;이번회에서는 mainwindow.cpp에 다음 두줄을 생성자의 마지막에 추가합니다.&lt;br&gt;[code]&lt;br&gt;...&lt;br&gt;MainWindow::MainWindow(QWidget *parent)&lt;br&gt;: QMainWindow(parent), d(new Data) {&lt;br&gt;...&lt;br&gt;&amp;nbsp; &amp;nbsp; setWindowIcon(QIcon(&quot;img/document-edit.png&quot;));&lt;br&gt;&amp;nbsp; &amp;nbsp; d-&amp;gt;newFileAction-&amp;gt;setIcon(QIcon(&quot;:/img/document-new.png&quot;));&lt;br&gt;}&lt;br&gt;[/code]&lt;br&gt;그리고 소스코드와 같은 위치에 다음과 같은 내용의 resources.qrc 파일을 작성합니다.&lt;br&gt;[code]&lt;br&gt;&amp;lt;RCC&amp;gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;lt;qresource prefix=&quot;/&quot; &amp;gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;lt;file&amp;gt;img/document-new.png&amp;lt;/file&amp;gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;lt;/qresource&amp;gt;&lt;br&gt;&amp;lt;/RCC&amp;gt;&lt;br&gt;[/code]&lt;br&gt;마지막으로 texteditor.pro파일에 다음 한줄을 추가합니다.&lt;br&gt;[code]&lt;br&gt;RESOURCES += resources.qrc&lt;br&gt;[/code]&lt;br&gt;먼저 mainwindow.cpp의 추가된 라인을 살펴보겠습니다. setWindowIcon()이라는 함수가 호출되고 있는데, 이것은 QWidget::setWindowIcon()으로, 모든 위젯이 가지고 있는 함수입니다.&lt;br&gt;이를 이용하여 해당 위젯이 최상위 위젯일때 표시되는 아이콘을 지정할 수 있습니다.&lt;br&gt;이 함수는 QIcon의 객체를 인자로 받는데, QIcon은 딱 보면 알수 있듯이 아이콘에 대한 클래스입니다.&lt;br&gt;가장 간단한 사용방법은, 위와 같이 QIcon(이미지파일 경로)와 같이 생성하는 것입니다.&lt;br&gt;이미지 경로가 img/document-edit.png로 되어있는데, 이것은 작업경로에 대한 상대경로로, 당연히 절대경로도 가능합니다.&lt;br&gt;&lt;br&gt;첨부된 예제소스를 받아보면, 소스코드가 있는곳에 img라는 디렉토리가 추가되어있고 그 안에 이미지 파일이 들어있는 것을 확인 할수 있습니다. 현재는 소스코드가 있는 곳에서 빌드하고 실행하기 때문에, 이 경로로 이미지의 위치를 제대로 인식하지만, 만약 실행파일이 다른 곳으로 옮겨지는등 작업경로가 변경되면 이미지를 인식 할 수 없게됩니다.&lt;br&gt;또한 실제 배포시에는 이미지를 각 시스템에 맞게 별도로 제공해야 할 수도 있습니다.&lt;br&gt;그럼 절대 경로를 이용하면 되지 않느냐? 라고 생각 할수도 있겠지만, 이경우는 배포시의 경로를 강제해야 하고, 이것은 합리적이지 못합니다.&lt;br&gt;&lt;br&gt;이럴 때, &#039;리소스&#039;를 이용할 수 있습니다.&lt;br&gt;Qt의 리소스 시스템이란, 바이너리 파일을 실행파일에 포함시켜버리는 것을 말합니다.&lt;br&gt;즉, 애시당초 이미지를 별도로 다루지 않고, 실행파일에 붙여버리는 것입니다.&lt;br&gt;이러면 배포할때 이미지 경로를 신경쓰지 않아도 될 뿐만 아니라, 실행파일과 이미지를 함께 배포해야 하는 수고를 덜수 있습니다.&lt;br&gt;&lt;br&gt;리소스로 이용하고 싶은 파일들은 위에 적은 resources.qrc파일처럼 형식에 맞게 목록을 작성하여 qrc의 확장자로 목록을 저장한후, texteditor.pro파일 처럼 프로필 파일에 &#039;RESOURCES += 리소스 목록 파일&#039;과 같이 리소스 목록 파일을 지정해주어야 합니다.&lt;br&gt;qrc파일의 형식은 매우 간단하므로 별도 설명은 하지 않습니다. 좀더 다양한 활용법에 대해서는 assistant를 참고하시기 바랍니다.&lt;br&gt;&lt;br&gt;생성자에 추가된 마지막 줄은 이 리소스 파일로부터 아이콘을 만들고 있는 코드입니다.&lt;br&gt;QIcon의 생성자로 넘긴 이미지 파일의 경로를 보면 :/ 로 시작하고 있습니다. :/로 시작하는 경로는 리소스 파일에 대한 경로입니다. 이와 같이 리소스로 추가된 파일을, 실제 소스코드내에서 불러올때는 반드시 :로 시작하는 경로를 입력해야 합니다. /는 리소스 목록 파일에서 prefix로 지정된 경로로, 만약 prefix=&quot;/rsc&quot;와 같이 지정했었다면 :/img/document-new.png가 아니라 :/rsc/img/document-new.png 와 같이 해야 할 것입니다.&lt;br&gt;QAction::setIcon()함수는 해당 액션에 아이콘을 지정하는 함수입니다. 액션의 아이콘은, 다음과 같은 역할을 합니다.&lt;br&gt;1. 툴바에 표시된 액션의 아이콘&lt;br&gt;2. 메뉴에 표시된 액션의 아이콘&lt;br&gt;&lt;br&gt;이리하여 실행해보면 두가지 아이콘이 적용된 모습을 볼 수 있습니다.&lt;br&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;img src=&quot;http://xylosper.net/attach/1/1375948207.png&quot; alt=&quot;실행화면&quot; height=&quot;254&quot; width=&quot;266&quot; /&gt;&lt;p class=&quot;cap1&quot;&gt;실행화면&lt;/p&gt;&lt;/div&gt;이번회에서는 리소스의 예로 이미지 파일을 들었지만, 그외에도 여러가지 활용법이 있습니다.&lt;br&gt;예를 들면 소스코드에 직접 적어 넣기 힘든 문서내용을, 텍스트파일로 저장하여 불러올수 있습니다.&lt;br&gt;혹은 특정 동작에 대한 소리를 리소스로 집어 넣을 수도 있습니다.&lt;br&gt;</description>
			<category>Qt</category>
			<category>icon</category>
			<category>QIcon</category>
			<category>qrc</category>
			<category>Qt</category>
			<category>resource</category>
			<category>리소스</category>
			<category>아이콘</category>
			<author>(xylosper)</author>
			<guid>http://xylosper.net/132</guid>
			<comments>http://xylosper.net/132#entry132comment</comments>
			<pubDate>Wed, 15 Apr 2009 19:17:50 +0900</pubDate>
		</item>
		<item>
			<title>CMPlayer 0.3.0 릴리즈</title>
			<link>http://xylosper.net/131</link>
			<description>CMPlayer 0.3.0버전을 릴리즈하였습니다.&lt;br&gt;0.2.5이후부터 재생 엔진을 통합하여 CMPlayer는 현재 &#039;다양한 재생엔진을 지원하는 엔드 유저를 위한 리눅스용 멀티미디어 플레이어&#039;라는 컨셉으로 개발하고 있습니다.&lt;br&gt;&lt;br&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;img src=&quot;http://xylosper.net/attach/1/1144097056.png&quot; alt=&quot;CMPlayer 0.3.0&quot; height=&quot;454&quot; width=&quot;530&quot; /&gt;&lt;p class=&quot;cap1&quot;&gt;CMPlayer 0.3.0&lt;/p&gt;&lt;/div&gt;다음 페이지에서 다운로드 할 수 있습니다.&lt;br&gt;&lt;a href=&quot;http://kldp.net/frs/?group_id=1243&quot; target=&quot;_blank&quot;&gt;http://kldp.net/frs/?group_id=1243&lt;/a&gt;&lt;br&gt;&lt;br&gt;CMPlayer로는 다음과 같은 것들이 가능합니다.&lt;br&gt;&lt;br&gt;* 다양한 재생엔진의 지원(현재 MPlayer와 xine 이용가능, 차후 GStreamer 지원 예정)&lt;br&gt;* 파일/URL/DVD 재생 지원&lt;br&gt;* DVD 메뉴 지원(xine only)&lt;br&gt;* 화면 크기/종횡비 설정 및 잘라내기 지원&lt;br&gt;* 스냅샷 지원&lt;br&gt;* 재생 속도 변경 가능&lt;br&gt;* 복수의 오디오 스트림을 포함한 미디어 지원&lt;br&gt;* 파일명으로부터 재생목록 자동 생성&lt;br&gt;* 단일 어플리케이션 지원&lt;br&gt;* 시스템 트레이 아이콘 지원&lt;br&gt;* 최소화 및 복귀시 자동 일시정지 및 자동 재생 시작&lt;br&gt;* 재생중 화면 보호기 끄기&lt;br&gt;* 구간 반복 기능&lt;br&gt;* 상하단 여백 존재시 자동으로 자막 출력위치가 조절됨&lt;br&gt;* Sami(smi), SubRip(srt), MicroDVD, TMPlayer 자막 포맷 지원&lt;br&gt;* 통합 자막지원&lt;br&gt;* 포맷에 상관없이 복수의 자막들의 동시 표시 가능&lt;br&gt;* 자막 인코딩 자동 탐지(libchardet 이용)&lt;br&gt;* SAMI포맷의 컬러 자막 지원(xine only)&lt;br&gt;* 전 메뉴 단축키 설정 가능&lt;br&gt;* 마우스 조작으로 동작 설정 가능&lt;br&gt;&lt;br&gt;이외에도 여러가지 편리한 기능이 포함되어있습니다.&lt;br&gt;</description>
			<category>CMPlayer</category>
			<category>CMPlayer</category>
			<category>동영상</category>
			<category>동영상플레이어</category>
			<category>리눅스</category>
			<category>멀티미디어</category>
			<author>(xylosper)</author>
			<guid>http://xylosper.net/131</guid>
			<comments>http://xylosper.net/131#entry131comment</comments>
			<pubDate>Fri, 10 Apr 2009 06:36:38 +0900</pubDate>
		</item>
		<item>
			<title>Xy LaTeX Editor - 텍스트큐브용 LaTeX 편집기 플러그인</title>
			<link>http://xylosper.net/130</link>
			<description>Hybrid님이 만드신 &lt;a class=&quot;entry-title&quot; title=&quot;SitmoLaTeX Display - Tattertools/Textcube Plugin&quot; href=&quot;http://www.hybrid.pe.kr/tt/321&quot; rel=&quot;bookmark&quot;&gt;SitmoLaTeX Display&lt;/a&gt;를 보고, 플러그인을 한번 열어보니, 고정된 주소로 렌더링해주는 거라면 뭐든지 가능하겠다 싶어서 CodeCogs의 LaTeX Equation Editor를 이용하여 Xy LaTeX Editor라는 이름으로 텍스트큐브용 LaTeX편집기 플러그인을 만들었습니다.&lt;br&gt;&lt;br&gt;이 플러그인은 LaTeX 수식을 표시해줄 뿐만 아니라, 글을 작성하고 편집할때 수식의 미리보기와 수식 입력을 도와주는 툴바를 제공합니다.&lt;br&gt;&lt;br&gt;플러그인을 설치하면 다음과 같이 글 작성창 하단에 두개의 버튼이 생깁니다.&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;img src=&quot;http://xylosper.net/attach/1/1238151846.png&quot; alt=&quot;사용자 삽입 이미지&quot; height=&quot;27&quot; width=&quot;400&quot; /&gt;&lt;/div&gt;&lt;ol&gt;
&lt;li&gt;새 수식 삽입하기&lt;br&gt;본문에 새 수식을 삽입하기 위해 수식 에디터를 엽니다.&lt;/li&gt;&lt;li&gt;선택된 수식 고치기&lt;br&gt;본문에서 선택된 수식을 고치기 위해 수식 에디터를 엽니다.&lt;/li&gt;&lt;/ol&gt;어느 버튼을 누르던 다음과 같은 수식 에디터 창이 열립니다.&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;img src=&quot;http://xylosper.net/attach/1/1046960794.png&quot; alt=&quot;사용자 삽입 이미지&quot; height=&quot;223&quot; width=&quot;400&quot; /&gt;&lt;/div&gt;버튼에 따른 차이는, 새 수식 삽입하기 버튼은 아무것도 입력되지 않은 창을 띄우고, 선택된 수식 고치리 버튼은 선택된 수식의 내용이 미리 입력되어있다는 점입니다.&lt;br&gt;&lt;br&gt;적당히 편집후 확인 버튼을 누르면, 새 수식 삽입되거나 수정될 수식이 갱신됩니다.&lt;br&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;img src=&quot;http://xylosper.net/attach/1/1003364746.png&quot; alt=&quot;사용자 삽입 이미지&quot; height=&quot;86&quot; width=&quot;400&quot; /&gt;&lt;/div&gt;참고로 글 작성시에 보이는 것은 어디까지나 &#039;미리보기&#039;입니다. 실제로는 수식내용이 그대로 저장되고, 나중에 다시 글을표시할때 이미지로 치환됩니다.&lt;br&gt;&lt;br&gt;또한 본문에 직접 [tex*]...[tex*](실제론 tex*가 아니라 tex)사이에 수식을 입력해도 실제로 표시될때 이미지로 치환됩니다.&lt;br&gt;&lt;br&gt;몇가지 설정가능한 부분이 있는데, 그중 다음 두가지는 약간의 설명이 필요할듯 하여 소개합니다.&lt;br&gt;
&lt;ol&gt;
&lt;li&gt;자동업데이트 시간&lt;br&gt;위에서 설명한 수식 입력후 자동으로 이미지를 갱신해주기 까지의 시간 간격을 밀리초단위로 설정합니다. 0보다 작은 수가 입력되면 자동업데이트기능을 끕니다. 
&lt;/li&gt;&lt;li&gt;본문 렌더링 여부&lt;br&gt;렌더링 설정부분에서 &#039;글 표시할 때&#039;라는 부분이 있는데, 이부분을 체크해제하면 Xy LaTeX Editor의 미리보기 및 편집기 기능만을 이용하게됩니다. 본문의 수식을 실제로 표시하는 것은 다른 방법을 이용하고 싶은 경우에 체크를 해제하면 됩니다.&lt;/li&gt;&lt;/ol&gt;마지막으로 사이드바에 CodeCogs 배너를 추가할 수 있는 기능이 있습니다.&lt;br&gt;플러그인을 적용하면 사이드바 위젯에 CodeCogs배너가 선택가능해집니다.&lt;br&gt;Xy LaTeX Editor의 수식 렌더링은 전부 CodeCogs에 의해서 생성된 것이며, 실제 이미지또한 CodeCogs에 의해서 제공됩니다.&lt;br&gt;CodeCogs는 이미지를 제공하는 대신, 다음과 같은 배너를 웹사이트에 달아줄것을 &#039;부탁&#039;하고 있습니다.&lt;br&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;http://www.codecogs.com/&quot;&gt;&lt;img title=&quot;CodeCogs - An Open Source Numerical Library&quot; alt=&quot;CodeCogs - An Open Source Numerical Library&quot; src=&quot;http://www.codecogs.com/images/poweredbycc.gif&quot; border=&quot;0&quot;&gt;&lt;/a&gt; &lt;/div&gt;어디까지나 부탁이므로 이를 따를 의무는 없습니다만, 도리로서 되도록이면 본 플러그인을 이용하시는 분들은 (특히 글 표시할때에도 이 플러그인을 이용하시는 경우에는) 사이드바에 배너를 추가해주길 저도 &#039;부탁&#039;드립니다.&lt;br&gt;실제로 배너가 달린 모습은 제 블로그의 사이드바에서 볼수 있습니다.&lt;br&gt;&lt;br&gt;한가지 주의사항이 있는데요, 글 표시할때 렌더링을 CodeCogs로 하는 경우, 과다하게 이미지를 가져다 쓰는 경우 블록될수 있다고 경고하고 있습니다. 일일 10,000번이상의 이미지 요청이 예상될경우는 따로 연락을 달라고 합니다. 자세한 것은 &lt;a href=&quot;http://www.codecogs.com/components/equationeditor/equation_install.php&quot; target=&quot;_blank&quot;&gt;CodeCogs홈페이지의 LaTeX Editor Usage Policy&lt;/a&gt;를 참고해주세요.&lt;br&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;a class=&quot;extensionIcon&quot; href=&quot;http://xylosper.net/attachment/1199227905.gz&quot;&gt;&lt;img src=&quot;http://xylosper.net/image/extension/gz.gif&quot; alt=&quot;&quot; /&gt; XyLaTeXEditor.tar.gz&lt;/a&gt;&lt;p class=&quot;cap1&quot;&gt;Xy LaTeX Editor 다운로드&lt;/p&gt;&lt;/div&gt;마지막으로 LaTeX 글이면서 수식이 하나도 없기에, 테스트도 겸해서 몇가지 식을 끄적이고 마칩니다.&lt;br&gt;&lt;br&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;XyLaTeXEquationImage&quot; src=&quot;http://www.codecogs.com/gif.latex?\small \left\{-\frac{\hbar^2}{2m}\nabla^2+V(\vec{r}, t)\right\}\psi(\vec{r}, t) = ih \frac{\partial}{\partial t}\psi(\vec{r},t)&quot; alt=&quot;\left\{-\frac{\hbar^2}{2m}\nabla^2+V(\vec{r}, t)\right\}\psi(\vec{r}, t) = ih \frac{\partial}{\partial t}\psi(\vec{r},t)&quot; /&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;XyLaTeXEquationImage&quot; src=&quot;http://www.codecogs.com/gif.latex?\small \oint \vec{H}\cdot d\vec{r} = \int \left(\vec{i} + \frac{\partial \vec{D}}{\partial t} \right)\cdot d\vec{S}&quot; alt=&quot;\oint \vec{H}\cdot d\vec{r} = \int \left(\vec{i} + \frac{\partial \vec{D}}{\partial t} \right)\cdot d\vec{S}&quot; /&gt;&lt;br&gt;&lt;br&gt;&lt;img class=&quot;XyLaTeXEquationImage&quot; src=&quot;http://www.codecogs.com/gif.latex?\small u(x,y,z) = -\frac{i}{\lambda}\frac{e^{ikz}}{z} \iint u_0(x_0,y_0)e^{\frac{ik}{2z}\left\{(x-x_0)^2 + (y-y_0)^2\right\}}dx_0dy_0&quot; alt=&quot;u(x,y,z) = -\frac{i}{\lambda}\frac{e^{ikz}}{z} \iint u_0(x_0,y_0)e^{\frac{ik}{2z}\left\{(x-x_0)^2 + (y-y_0)^2\right\}}dx_0dy_0&quot; /&gt;&lt;br&gt;&lt;br&gt;&lt;img class=&quot;XyLaTeXEquationImage&quot; src=&quot;http://www.codecogs.com/gif.latex?\small \begin{align*} E &amp;amp;= \int _0 ^{\infty} f_B(\omega)\hbar \omega D(\omega) d\omega \simeq \frac{3V\hbar}{2\pi^2 v^3}\int_0^{\omega_D} \frac{\omega^3}{e^{\beta \hbar \omega}-1}d\omega \\ C_V &amp;amp;=\frac{\partial E}{\partial T} = 9Nk_B\left(\frac{T}{\Theta}\right)^3\int_0^{\Theta /T}\frac{x^4e^x}{(e^x - 1)^2}dx \\ &amp;amp;\simeq\left\{\begin{matrix} 3Nk_B &amp;amp; (T \gg \Theta)\\ \frac{12}{5}\pi^4Nk_B\left(\frac{T}{\Theta}\right)^3 \propto T^3 &amp;amp; (T \ll \Theta) \end{matrix}\right. \end{align*}&quot; alt=&quot;\begin{align*} E &amp;amp;= \int _0 ^{\infty} f_B(\omega)\hbar \omega D(\omega) d\omega \simeq \frac{3V\hbar}{2\pi^2 v^3}\int_0^{\omega_D} \frac{\omega^3}{e^{\beta \hbar \omega}-1}d\omega \\ C_V &amp;amp;=\frac{\partial E}{\partial T} = 9Nk_B\left(\frac{T}{\Theta}\right)^3\int_0^{\Theta /T}\frac{x^4e^x}{(e^x - 1)^2}dx \\ &amp;amp;\simeq\left\{\begin{matrix} 3Nk_B &amp;amp; (T \gg \Theta)\\ \frac{12}{5}\pi^4Nk_B\left(\frac{T}{\Theta}\right)^3 \propto T^3 &amp;amp; (T \ll \Theta) \end{matrix}\right. \end{align*}&quot; /&gt;&lt;/div&gt;</description>
			<category>and so on</category>
			<category>editor</category>
			<category>LaTeX</category>
			<category>LaTeX 렌더러</category>
			<category>renderer</category>
			<category>수식</category>
			<category>에디터</category>
			<category>텍스트큐브</category>
			<category>편집기</category>
			<category>플러그인</category>
			<author>(xylosper)</author>
			<guid>http://xylosper.net/130</guid>
			<comments>http://xylosper.net/130#entry130comment</comments>
			<pubDate>Fri, 27 Feb 2009 21:56:29 +0900</pubDate>
		</item>
		<item>
			<title>2차원 Ising모델 시뮬레이터</title>
			<link>http://xylosper.net/129</link>
			<description>2차원 Ising모델을 메트로폴리스 알고리즘을 이용한 몬테카를로법으로 시뮬레이션해주는 프로그램입니다.&lt;br&gt;&lt;br&gt;이번 방학에 연구실 인턴쉽 과제로 &#039;상전이 시뮬레이션&#039;을 받아서, 선생님이 준 자료를 일단 공부해보고, 3월부터 본격적으로 시작하자는 취지였는데, 그냥 심심하고 할일도 없어서 만들어 버렸습니다.&lt;br&gt;&lt;br&gt;나중에 선생님께 보여드렸을 때, &#039;이게 아니야~&#039;라는 반응이 나오지 않을까 좀 걱정됩니다만...&lt;br&gt;&lt;br&gt;아무튼 모처럼 만들었으니 공개해봅니다.&lt;br&gt;&lt;br&gt;1. 온도(J/kT)에 따른 2차원 격자의 상태 시각화 및 스냅샷 기능&lt;br&gt;2. 온도(1/kT)에 따른 장거리 질서도(평균자화의 절대값), 자화율, 내부 에너지, 비열의 변화 플롯 및 파일 출력 기능&lt;br&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;img src=&quot;http://xylosper.net/attach/1/1098640265.png&quot; alt=&quot;상태 시각화 이미지&quot; height=&quot;378&quot; width=&quot;530&quot; /&gt;&lt;p class=&quot;cap1&quot;&gt;격자 상태의 시각화&lt;/p&gt;&lt;/div&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;img src=&quot;http://xylosper.net/attach/1/1035625233.png&quot; alt=&quot;그래프&quot; height=&quot;378&quot; width=&quot;530&quot; /&gt;&lt;p class=&quot;cap1&quot;&gt;각종 상태값의 그래프&lt;/p&gt;&lt;/div&gt;이상의 것이 가능합니다. 처음엔 자기장도 고려해서짜볼려고 했는데, 인터페이스도 번잡해지고, 자기장이 들어간다고해서 뭔가 재미있는 결과가 보이지도 않길래 그냥 자기장은 0으로 고정시켜버리고 짰습니다.&lt;br&gt;
&lt;br&gt;
참고로 단순히 수치연산을 한게 아니라, 확률적으로 시뮬레이션 한 것이기 때문에 매끄러운 그래프가 나오진 않습니다.&lt;br&gt;&lt;br&gt;마지막으로 라이센스는 GPL을 따르므로 수정 및 재배포시 소스공개의 의무가 있다는 점 이외에는 자유롭게 이용가능하며, 당연합니다만, 시뮬레이션 결과에 대해서는 어떠한 보장도 하지 않습니다.&lt;br&gt;&lt;br&gt;다운로드 파일에는 소스코드 및 윈도우용 바이너리가 포함되어있고, Qt를 이용할수 있는 대부분의 플랫폼에서 빌드할 수있습니다(상황에 따라서 ising.pro파일의 INCLUDEPATH 및 LIBS 옵션을 바꿔주세요).&lt;br&gt;컴파일하기 위해서는 Qt4.4이상 및 Qwt5이상이 필요합니다.&lt;br&gt;&lt;br&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;a class=&quot;extensionIcon&quot; href=&quot;http://xylosper.net/attachment/1232285897.gz&quot;&gt;&lt;img src=&quot;http://xylosper.net/image/extension/gz.gif&quot; alt=&quot;&quot; /&gt; ising.tar.gz&lt;/a&gt;&lt;p class=&quot;cap1&quot;&gt;tar.gz 압축 파일&lt;/p&gt;&lt;/div&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;a class=&quot;extensionIcon&quot; href=&quot;http://xylosper.net/attachment/1109440035.zip&quot;&gt;&lt;img src=&quot;http://xylosper.net/image/extension/zip.gif&quot; alt=&quot;&quot; /&gt; ising.zip&lt;/a&gt;&lt;p class=&quot;cap1&quot;&gt;zip 압축 파일&lt;/p&gt;&lt;/div&gt;&lt;br&gt;</description>
			<category>Physics</category>
			<category>Ising</category>
			<category>Metropolis</category>
			<category>Mote Carlo</category>
			<category>메트로폴리스</category>
			<category>몬테카를로</category>
			<category>시뮬레이션</category>
			<author>(xylosper)</author>
			<guid>http://xylosper.net/129</guid>
			<comments>http://xylosper.net/129#entry129comment</comments>
			<pubDate>Sat, 21 Feb 2009 15:51:00 +0900</pubDate>
		</item>
		<item>
			<title>MBTI 유형테스트</title>
			<link>http://xylosper.net/128</link>
			<description>&lt;a href=&quot;http://ani2life.egloos.com/3926525&quot; target=&quot;_blank&quot;&gt;A2공간의 재미로 해보는 MBTI 검사글&lt;/a&gt;&lt;a name=&quot;3926525&quot; title=&quot;재미로 해보는 MBTI 검사&quot;&gt;이라는 글을 보고, 심심풀이로 &lt;/a&gt;&lt;a href=&quot;http://user.chol.com/%7Eilovehrl/mbti/mbti1.html&quot; target=&quot;_blank&quot;&gt;테스트&lt;/a&gt;해보았습니다.&lt;br&gt;참고로 MBTI는 성격유형검사라고 하네요.&lt;br&gt;&lt;br&gt;&lt;blockquote&gt;▩ ISTP 백과사전형 ▩
&lt;br&gt;&lt;br&gt;조용하고 과묵하고 절제된 호기심으로 인생을 관찰하며 상황을 파악하는 민감성과 도구를 다루는 뛰어난 능력이 있다.&lt;br&gt;
말이 없으며, 객관적으로 인생을 관찰하는 형이다.
필요 이상으로 자신을 발휘하지 않으며, 일과 관계되지 않는 이상 어떤 상황이나 인간 관계에 직접 뛰어들지 않는다.
가능한 에너지 소비를 하지 않으려 하며, 사람에 따라 사실적 자료를 정리, 조직하길 좋아하며 기계를 만지거나 인과 관계나 객관적 원리에 관심이 많다.
연장, 도구, 기계를 다루는데 뛰어나며 사실들을 조직화하는 재능이 많으므로 법률, 경제, 마케팅, 판매, 통계 분야에 능력을 발휘한다.
민첩하게 상황을 파악하는 능력이 있다.
느낌이나 감정, 타인에 대한 마음을 표현하기 어려워한다.  &lt;br&gt;
&lt;br&gt;▒ 일반적인 특성 ▒
&lt;ul&gt;&lt;li&gt;소비성 경향이 많다&lt;/li&gt;&lt;li&gt;마음에 없는 얘기를 상대방 기분 때문에 하지 않는다&lt;/li&gt;&lt;li&gt;일반적으로 조용한 편이나 필요에 따라 사교적이다&lt;/li&gt;&lt;li&gt;손재주가 뛰어 나다&lt;/li&gt;&lt;li&gt;개인주의적 성향이 강하다&lt;/li&gt;&lt;li&gt;충동에 따라 행동하기 때문에 언제라도 일자리를 박차고 떠날 수 있다&lt;/li&gt;&lt;li&gt;틀에 박힌 생활을 싫어한다&lt;/li&gt;&lt;li&gt;고집이 있고 주장이 강하다&lt;/li&gt;&lt;li&gt;말이 없고 내색을 않는다&lt;/li&gt;&lt;li&gt;객관적 원리에 관심이 많다&lt;/li&gt;&lt;li&gt;도구를 다루는데 관심이 있다&lt;/li&gt;&lt;li&gt;느낌과 감정, 타인에 대한 마음을 표현하기 어려워한다&lt;/li&gt;&lt;li&gt;정의감이 있으나 직설적인 말로 타인의 감정을 상하게 할 수 있다&lt;/li&gt;&lt;li&gt;충동에 따라 행동하기 때문에 언제라도 일자리를 박차고 떠날 수 있다&lt;/li&gt;&lt;li&gt;정밀을 요하는 일을 잘 해낸다&lt;/li&gt;&lt;li&gt;타인의 일에 무관심한 편이다&lt;/li&gt;&lt;li&gt;모험과 스릴을 즐긴다&lt;/li&gt;&lt;li&gt;관심분야가 아니면 처다 보지도 않는다&lt;/li&gt;&lt;li&gt;생각은 적극적인데 행동은 소극적&lt;/li&gt;&lt;li&gt;노력을 절약하면서(게으르다는 소리를 들음) 일의 능률을 높인다&lt;/li&gt;&lt;/ul&gt; &lt;br&gt;
▒ 개발해야할 점 ▒&lt;ul&gt;&lt;li&gt;타인에 대해서 의도적으로 관심을 갖는 것이 필요&lt;/li&gt;&lt;li&gt;화가 난 얼굴이 창백하게 보일 수 있으므로 얼굴 관리에 신경 쓰는 것이 필요&lt;/li&gt;&lt;li&gt;함께 하는 일을하는 오락시간을 갖는 것이 필요 &lt;/li&gt;&lt;/ul&gt;&lt;/blockquote&gt;&lt;a name=&quot;3926525&quot; title=&quot;재미로 해보는 MBTI 검사&quot;&gt;이런 결과가...&lt;br&gt;음...전반적으론 맞는 것 같지만 부분부분 납득되지 않는 것도 있네요.&lt;br&gt;뭐 질문에 답하면서 이런 결과가 나올 것같은 생각은 들었지만요.&lt;br&gt;&lt;/a&gt;</description>
			<category>Trivia</category>
			<category>MBTI</category>
			<author>(xylosper)</author>
			<guid>http://xylosper.net/128</guid>
			<comments>http://xylosper.net/128#entry128comment</comments>
			<pubDate>Sat, 11 Oct 2008 00:25:13 +0900</pubDate>
		</item>
		<item>
			<title>static 변수를 이용한 싱글톤 구현시 주의할 점</title>
			<link>http://xylosper.net/127</link>
			<description>어제 하루 종일 낑낑대던 문제가 있었습니다.&lt;strongr&gt;&lt;br&gt;싱글톤(singleton)을 이용한 객체를 가져다 쓰는 부분에서 자꾸 segmentation fault가 발생하는 것입니다.&lt;br&gt;&lt;br&gt;싱글톤의 구현 자체는 다음과 같이 C++에서 극히 일반적인 static변수를이용한 구현입니다.&lt;br&gt;&lt;br&gt;class Singleton {&lt;br&gt;public:&lt;br&gt;&amp;nbsp; &amp;nbsp; static Singleton *get() {static Singleton self; return &amp;amp;self;}&lt;br&gt;private:&lt;br&gt;&amp;nbsp; &amp;nbsp; Singleton() {}&lt;br&gt;};&lt;br&gt;&lt;br&gt;싱글톤 자체는 공유라이브러리에 들어있고, 이것을 서로 다른 두 바이너리에서 동시에 가져다 쓰는 형태인데요, 딱히 서로 다른 쓰레드에서 가져다 쓰는 것도 아니기 때문에, 멀티쓰레딩 환경에서의 static변수로 인한 문제도 없을 것이라 생각하여 별 신경 안썼었습니다.&lt;br&gt;&lt;br&gt;그런데 이부분에 죽어대니 도대체 원인을 알수 없더군요...&lt;br&gt;&lt;br&gt;그러던중 구글링 하다가 다음과 같은 글을 발견하였습니다.&lt;br&gt;&lt;br&gt;&lt;a href=&quot;http://www.gpgstudy.com/forum/viewtopic.php?t=2941&quot; target=&quot;_blank&quot;&gt;function static 스타일의 Singleton 버그? &lt;/a&gt;&lt;br&gt;&lt;br&gt;결론은, Singleton::get()함수가 인라이닝되는 바람에, 싱글톤이 싱글톤이 아니게 된 것이었습니다.&lt;br&gt;&lt;br&gt;Singleton::get()함수의 구현을 cpp파일로 뺐더니 잘 돌아가네요-_-;&lt;br&gt;&lt;br&gt;오늘의 교훈: static변수를 이용한 싱글톤 구현은 반드시 해더파일과 분리하자!&lt;br&gt;&lt;/strongr&gt;</description>
			<category>and so on</category>
			<category>singleton</category>
			<category>static</category>
			<category>싱글톤</category>
			<author>(xylosper)</author>
			<guid>http://xylosper.net/127</guid>
			<comments>http://xylosper.net/127#entry127comment</comments>
			<pubDate>Wed, 17 Sep 2008 16:28:53 +0900</pubDate>
		</item>
		<item>
			<title>CMPlayer 0.2.1 공개</title>
			<link>http://xylosper.net/126</link>
			<description>0.2.1을 릴리즈하였습니다.&lt;br&gt;&lt;br&gt;다음 두가지 버그 수정외에는 바뀐점이 없습니다.&lt;br&gt;&lt;br&gt;파일 변경시 전체 시간이 갱신되지 않던 문제 수정&lt;br&gt;Clearlooks 테마(Gnome 기본 테마)환경에서 재생 정보가 표시되지 않던 문제 수정&lt;br&gt;&lt;br&gt;상당히 불편한 버그이기 때문에 두가지 버그 수정 뿐이지만 새 버전을 릴리즈합니다.&lt;br&gt;&lt;br&gt;&lt;a href=&quot;http://kldp.net/frs/?group_id=1243&quot; target=&quot;&quot;&gt;CMPlayer 프로젝트 홈페이지의 다운로드 페이지&lt;/a&gt;에서 다운받을수 있습니다.&lt;br&gt;</description>
			<category>CMPlayer</category>
			<author>(xylosper)</author>
			<guid>http://xylosper.net/126</guid>
			<comments>http://xylosper.net/126#entry126comment</comments>
			<pubDate>Fri, 05 Sep 2008 18:02:53 +0900</pubDate>
		</item>
		<item>
			<title>Qt 팁 - 2. Qt로 만든 프로그램을 배포할 때의 주의점</title>
			<link>http://xylosper.net/124</link>
			<description>프로그램이라는게 혼자쓸려고 만드는 경우도 있지만, 처음부터 배포를 목적으로 하거나, 혼자쓰다가 배포하고 싶어지기도 하죠.&lt;br&gt;&lt;br&gt;Qt로 짠 프로그램을 배포할때 몇가지 주의해야할 사항을 적어봅니다.&lt;br&gt;&lt;br&gt;1. 라이센스 표시&lt;br&gt;&lt;br&gt;상용 라이센스를 구입한 경우라면 해당되지 않지만, 오픈소스에디션의 Qt를 이용한 경우에는 반드시 GPL에 따라서 배포해야합니다(따르지 않을 경우 라이센스 위반입니다).&lt;br&gt;우선 GPL 영어 전문을 포함시켜야합니다. 그리고 소스배포가 아니라 바이너리 배포인 경우, 소스를 함께 배포하거나 소스를 제공받을 수 있는 방법을 명시해야합니다. 보통 온라인상에서 소스와 바이너리를 함께 다운 받을수 있도록 하는 경우가 많습니다.&lt;br&gt;이부분은, 라이센스를 지키겠다는 의지와 노력을 보이는 것이 중요하니, 너무 라이센스의 법적인 부분에 대해서 얽메여서 어떻게 해야하나 전전긍긍할 필요는 없습니다.&lt;br&gt;&lt;br&gt;2. 라이브러리&lt;br&gt;&lt;br&gt;당연한 이야기이지만, Qt로 만든 프로그램은 Qt 라이브러리가 있어야 실행 할 수 있습니다. 리눅스등에서 KDE환경이라면 보통 기본적으로 Qt가 깔려있으니 문제 없지만, 그렇지 않은 경우(윈도우, Gnome환경 등)에는 상대방에게 Qt 라이브러리를 설치하도록 하거나 이쪽에서 제공해줘야겠죠.&lt;br&gt;리눅스의 경우는 대부분 저장소에서 설치하면 되므로 큰 문제가 되지 않습니다만, 윈도우(맥은 잘 모르겠네요)의 경우는 좀 귀찮아집니다.&lt;br&gt;이에 대한 해결법으로 보통 두가지 방법이 있습니다.&lt;br&gt;&lt;br&gt;1) 정적 라이브러리 이용&lt;br&gt;&lt;br&gt;빌드시에 정적 라이브러리를 이용하면, 실행파일에 라이브러리 내용도 전부 포함되므로, 따로 Qt라이브러리 파일을 배포할 필요가 없어집니다. 다만, 이경우 여러개의 실행파일을 이용하는 어플리케이션이라면, 각각의 실행파일에 중복되어 Qt가 들어가 용량이 너무 커질수 있습니다.&lt;br&gt;Qt로 정적빌드하는 법은 &lt;a href=&quot;http://xylosper.net/entry/Qt-%C6%C1-1-Qt%B7%CE-%C1%A4%C0%FBstatic-%BA%F4%B5%E5%C7%CF%B1%E2&quot; target=&quot;&quot;&gt;팁1편&lt;/a&gt;을 참고하세요.&lt;br&gt;&lt;br&gt;2) 동적 라이브러리 이용&lt;br&gt;&lt;br&gt;동적 라이브러리를 이용하기 위해서는, 윈도우에서는 같은 폴더내의 dll파일을 인식하므로, 실행파일과 라이브러리 파일들을 복사해서 함께 배포하면 됩니다.&lt;br&gt;이때 모든 파일을 배포할 필요는 없고, 빌드시에 링크된 라이브러리 파일만 복사하면 됩니다.&lt;br&gt;예를들어 네트워크 관련 모듈을 이용하지 않았다면, QtNetwork라이브러리 파일은 필요없겠죠.&lt;br&gt;&lt;br&gt;마지막으로, VC++을 이용하여 빌드된 경우,&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt; 재배포용 패키지(VCRedist)가 필요한 경우가 있습니다.&lt;br&gt;이것은 Qt로인한 것이 아니라 VC++(아마도 2005이후?)로 빌드된 모든 프로그램에 해당되는 것입니다.&lt;br&gt;&lt;/span&gt;관련패키지는 마이크로소프트 홈페이지에서 다운 받을 수 있습니다.&lt;br&gt;&lt;br&gt;그외에도 더 자세한 설명이 어시스턴트의 &#039;Deploying an Application on Qt/Windows&#039;항목에 적혀있으므로 이쪽도 참고하시기 바랍니다.</description>
			<category>Qt</category>
			<category>Qt</category>
			<category>배포</category>
			<author>(xylosper)</author>
			<guid>http://xylosper.net/124</guid>
			<comments>http://xylosper.net/124#entry124comment</comments>
			<pubDate>Wed, 03 Sep 2008 17:52:56 +0900</pubDate>
		</item>
		<item>
			<title>Qt 팁 - 1. Qt로 정적(static) 빌드하기</title>
			<link>http://xylosper.net/125</link>
			<description>Qt로 짠 프로그램을 배포할 때, 특히 윈도우나 맥에서, 사용자 측에서 Qt 라이브러리가 없어서 실행하지 못하는 경우가 많습니다.&lt;br&gt;이런 경우 해결책으로 Qt를 정적링크하여 실행파일에 넣어버리는 방법이 있는데요, Qt를 정적 링크(static link)하여 이용하기위해서는, 당연히, 정적 라이브러리 파일(.a)이 필요합니다.&lt;br&gt;Qt를 설치할때, 기본값으로 동적 라이브러리를 빌드하도록 되어있기 때문에, 정적 라이브러리 파일을 이용하기 위해서는 configure단계에서 -static 옵션을 주고 Qt를 설치하여야합니다.&lt;br&gt;&lt;br&gt;다만 -static옵션을 주고 그대로 make를 쳐버릴 경우, 라이브러리 파일 뿐만 아니라, 각종 툴들과 예제 및 데모까지, Qt의 모든 바이너리 파일들이 정적 링크되어 빌드되므로 Qt의 용량이 어마어마하게 늘어납니다(끝까지 해본 적이 없어서 모르겠습니다. 10기가는 넘어갑니다).&lt;br&gt;&lt;br&gt;(저도 다른 데서 본거긴 하지만) 제가 추천하는 방법은, 개발할때는 동적 링크된 Qt를 이용하고, 배포할때만 Qt를 정적링크하는 것입니다.&lt;br&gt;이렇게 하기 위해서는 두가지 Qt를 빌드해야합니다.&lt;br&gt;&lt;br&gt;우선 개발용으로 동적 링크해서 쓸 Qt는 일반적인 방법(-static 옵션 없이)으로 빌드하여 이용하면 됩니다.&lt;br&gt;그리고 배포용으로 정적링크해서 쓸 Qt는 우선 -static 옵션을 주고 configure한후, make할때, &#039;make sub-src&#039;를 이용하는 것입니다.&lt;br&gt;이렇게 할 경우, 라이브러리만 빌드하기 때문에 빌드 시간도 짧고 용량도 그리 크게 차지하지 않습니다.&lt;br&gt;다만 이 경우엔 정말 라이브러리 외에는 아무것도 빌드하지 않기 때문에, 예를 들어 디자이너나 어시스턴트 등도 빌드되지 않습니다.&lt;br&gt;그러므로 이러한 툴이나 예제들은 위에서 말한 개발용 Qt에 포함된 녀석을 이용해야겠지요.&lt;br&gt;참고로 이렇게 빌드한 정적링크 Qt는 &#039;make install&#039;을 하지 말고 복사해서 쓰거나 직접 경로를 지정해서 써야합니다.&lt;br&gt;만약 make install을 실행하면, 빌드하지 않은 모든 것들을 빌드한후 복사될 것입니다.&lt;br&gt;&lt;br&gt;정리하면,&lt;br&gt;&lt;br&gt;&lt;ol&gt;&lt;li&gt;일반적인 방법으로(-static옵션 없이) Qt를 빌드&lt;/li&gt;&lt;li&gt;정적 링크용 Qt를 빌드&lt;/li&gt;&lt;ol&gt;&lt;li&gt;configure -static [기타 옵션]&lt;/li&gt;&lt;li&gt;make sub-src&lt;/li&gt;&lt;li&gt;빌드된 것을 복사해서 이용&lt;/li&gt;&lt;/ol&gt;&lt;/ol&gt;</description>
			<category>Qt</category>
			<category>Qt</category>
			<category>정적 링크</category>
			<category>정적 빌드</category>
			<author>(xylosper)</author>
			<guid>http://xylosper.net/125</guid>
			<comments>http://xylosper.net/125#entry125comment</comments>
			<pubDate>Wed, 03 Sep 2008 11:06:17 +0900</pubDate>
		</item>
		<item>
			<title>Qt에 대하여 - 11. 실전! - 텍스트 에디터(2) : 메뉴 만들기</title>
			<link>http://xylosper.net/123</link>
			<description>이번에는 메뉴를 작성하고 툴바를 생성하는 방법을 살펴보겠습니다.&lt;br&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;a class=&quot;extensionIcon&quot; href=&quot;http://xylosper.net/attachment/1361566826.gz&quot;&gt;&lt;img src=&quot;http://xylosper.net/image/extension/gz.gif&quot; alt=&quot;&quot; /&gt; texteditor.tar.gz&lt;/a&gt;&lt;p class=&quot;cap1&quot;&gt;예제 소스 코드&lt;/p&gt;&lt;/div&gt;일단 &#039;새 파일&#039;메뉴를 만들어 봅시다.&lt;br&gt;&lt;br&gt;mainwindow.h&lt;br&gt;[code]&lt;br&gt;...&lt;br&gt;class MainWindow : public QMainWindow {&lt;br&gt;...&lt;br&gt;private slots:&lt;br&gt;&amp;nbsp; &amp;nbsp; void newFile();&lt;br&gt;private:&lt;br&gt;...&lt;br&gt;};&lt;br&gt;[/code]&lt;br&gt;해더파일에는 위와 같이 &#039;새 파일&#039;메뉴가 실행되었을때 새파일을 만들어주기 위해 호출할 슬롯함수 newFIle()을 선언해두었습니다(슬롯으로 선언한 이유는 곧 나옵니다).&lt;br&gt;&lt;br&gt;mainwindow.cpp&lt;br&gt;[code]&lt;br&gt;#include &quot;mainwindow.h&quot;&lt;br&gt;#include &amp;lt;QTextEdit&amp;gt;&lt;br&gt;#include &amp;lt;QMenuBar&amp;gt;&lt;br&gt;#include &amp;lt;QToolBar&amp;gt;&lt;br&gt;&lt;br&gt;struct MainWindow::Data {&lt;br&gt;&amp;nbsp; &amp;nbsp; QTextEdit *edit;&lt;br&gt;&amp;nbsp; &amp;nbsp; QAction *newFileAction;&lt;br&gt;};&lt;br&gt;&lt;br&gt;MainWindow::MainWindow(QWidget *parent)&lt;br&gt;: QMainWindow(parent), d(new Data) {&lt;br&gt;&amp;nbsp; &amp;nbsp; d-&amp;gt;edit = new QTextEdit(this);&lt;br&gt;&amp;nbsp; &amp;nbsp; setCentralWidget(d-&amp;gt;edit);&lt;br&gt;&amp;nbsp; &amp;nbsp; &lt;br&gt;&amp;nbsp; &amp;nbsp; QMenuBar *mb = menuBar();&lt;br&gt;&amp;nbsp; &amp;nbsp; &lt;br&gt;&amp;nbsp; &amp;nbsp; QMenu *fileMenu = mb-&amp;gt;addMenu(trUtf8(&quot;파일(&amp;amp;F)&quot;));&lt;br&gt;&amp;nbsp; &amp;nbsp; d-&amp;gt;newFileAction = fileMenu-&amp;gt;addAction(trUtf8(&quot;새 파일(&amp;amp;N)&quot;));&lt;br&gt;&amp;nbsp; &amp;nbsp; d-&amp;gt;newFileAction-&amp;gt;setShortcut(QKeySequence(&quot;Ctrl+N&quot;)); &lt;br&gt;&amp;nbsp; &amp;nbsp; &lt;br&gt;&amp;nbsp; &amp;nbsp; QToolBar *fileBar = addToolBar(trUtf8(&quot;파일 도구막대&quot;));&lt;br&gt;&amp;nbsp; &amp;nbsp; fileBar-&amp;gt;addAction(d-&amp;gt;newFileAction);&lt;br&gt;&amp;nbsp; &amp;nbsp; &lt;br&gt;&amp;nbsp; &amp;nbsp; connect(d-&amp;gt;newFileAction, SIGNAL(triggered()), this, SLOT(newFile()));&lt;br&gt;}&lt;br&gt;&lt;br&gt;MainWindow::~MainWindow() {&lt;br&gt;&amp;nbsp; &amp;nbsp; delete d;&lt;br&gt;}&lt;br&gt;&lt;br&gt;void MainWindow::newFile() {&lt;br&gt;&amp;nbsp; &amp;nbsp; d-&amp;gt;edit-&amp;gt;clear();&lt;br&gt;}&lt;br&gt;[/code]&lt;br&gt;mainwindow.cpp 가 변한 점을 하나씩 집어가도록 하겠습니다.&lt;br&gt;&lt;br&gt;우선 해더파일이 늘었는데, 메뉴바 클래스인 QMenuBar나 툴바 클래스인 QToolBar를 이용하기위해서포함시킨 것들입니다.&lt;br&gt;그외에도 QMenu나 QAction등이 필요합니다만, QMenuBar안에 이미 포함되어있기 때문에 생략했습니다.&lt;br&gt;&lt;br&gt;데이터클래스에 QAction *newFileAction 이라는 멤버가 추가되었습니다.&lt;br&gt;여기서 한가지 분명히 해두어야 할게 있습니다.&lt;br&gt;우리가 보통 &#039;메뉴&#039;라고 하면, 예를 들어, &quot;&#039;파일&#039;메뉴의 &#039;새 파일&#039;메뉴&quot;라고 하듯이, 목록(파일 메뉴)과 그 아래의 항목(새파일 메뉴)을 모두 메뉴라고 칭합니다.&lt;br&gt;Qt에서는, 그러한 목록은 QMenu 클래스로, 그리고 하위 항목들은 QAction 클래스로 구현합니다.&lt;br&gt;따라서 앞으로 메뉴 라고 하면 QMenu 클래스로 구현되는 목록을, 액션이라고 하면 메뉴의 하위 항목을 지칭하는 것으로 정하겠습니다.&lt;br&gt;&lt;br&gt;그런데, 예를 들어 파일 메뉴의 하위항목으로 최근 파일 목록 같은 메뉴가 들어가 있어서, 메뉴가 메뉴를 포함하고 있는 경우도 많습니다.&lt;br&gt;
그래서, 메뉴 자체도 거기에 대응하는 하나의 액션을 가지고 있고, 위젯으로서의 속성외의 것들은 액션으로 관리됩니다.&lt;br&gt;메뉴에 대응되는 액션은, QMenu::menuAction()으로 얻을수 있습니다.&lt;br&gt;반대로, 액션의 경우, 메뉴에 대응된 액션이라면, QAction::menu()가 널이 아닌 포인터를 반환합니다.&lt;br&gt;
예를 들어, 메뉴항목을 숨기고 싶다면 QMenu::hide()가 아니라, 그 메뉴에 대응되는 액선의, QAction::setVisible(false)를 이용해야합니다.&lt;br&gt;&lt;br&gt;newFileAction은 새파일을 만들기 위한 액션입니다. 액션의 사용법은 생성자를 살펴볼때 설명하겠습니다.&lt;br&gt;&lt;br&gt;이제 생성자를 살펴보겠습니다.&lt;br&gt;&lt;br&gt;QMenuBar *mb = menuBar();&lt;br&gt;&lt;br&gt;이 한줄이 메뉴바를 생성하는 한줄입니다. 메뉴바는 QMainWindow::menuBar()가 처음으로 호출 될때 생성되며, 그이후로 menuBar()함수가 호출되면 이미 생성된 메뉴바에 대한 포인터를 반환합니다.&lt;br&gt;이제 메뉴바에 메뉴를 추가합시다.&lt;br&gt;&lt;br&gt;QMenu *fileMenu = mb-&amp;gt;addMenu(trUtf8(&quot;파일(&amp;amp;F)&quot;));&lt;br&gt;&lt;br&gt;trUtf8()가 뭔지 기억이 안나신다면 &lt;a href=&quot;http://xylosper.net/entry/Qt%BF%A1-%B4%EB%C7%CF%BF%A9-4-Hello-world-advanced&quot; target=&quot;_blank&quot;&gt;4편&lt;/a&gt;을 참고하세요.&lt;br&gt;&lt;br&gt;QMenu는, 위에서 설명했듯이 메뉴 목록을 나타내기위한 클래스로, 실제로 메뉴바에서 클릭했을때 표시되는 &#039;창&#039;이기때문에, QMenu도 역시 QWidget을 상속받아서 구현되어있습니다.&lt;br&gt;&lt;br&gt;QMenuBar::addMenu()함수는 다음의 세가지 형태로 오버로드되어있습니다.&lt;br&gt;&lt;br&gt;1. QAction *addMenu(QMenu *menu)&lt;br&gt;이미 존재하는 QMenu 인스턴스를 메뉴바에 추가할때 이용합니다.&lt;br&gt;여기서 반환되는 QAction*은, menu 메뉴에 대응되는 액션에 대한 포인터로, menu-&amp;gt;menuAction()과 동일한 값입니다.&lt;br&gt;&lt;br&gt;2. QMenu *addMenu(const QString &amp;amp;title)&lt;br&gt;메뉴바에 title이란 타이틀의 메뉴를 추가하여, 그 메뉴를 가리키는 포인터를 반환합니다.&lt;br&gt;타이틀은 메뉴바에서 표시되는 메뉴의 이름이며, 메뉴가 다른 메뉴에 포함되는 경우에는 해당 메뉴의 항목에 표시되는 이름입니다.&lt;br&gt;참고로, 이 항목이름도 메뉴에 대응되는 액션에 의해서 관리됩니다.&lt;br&gt;&lt;br&gt;3. QMenu *addMenu(const QIcon &amp;amp;icon, const QString &amp;amp;title)&lt;br&gt;icon으로 지정된 아이콘을 설정해준다는 점 이외에는 2번과 다를바없습니다.&lt;br&gt;메뉴바에 추가된 메뉴에 대해서는 아이콘을 표시하지 않기 때문에 의미가 없습니다만, 메뉴의 하위 항목으로 메뉴가 들어가있는 경우에 타이틀 옆에 아이콘을 표시해줍니다.&lt;br&gt;타이틀과 마찬가지로, 메뉴에 대응되는 액션에의해 관리됩니다.&lt;br&gt;&lt;br&gt;여기서는 2번을 이용하여, &#039;파일&#039;이라는 타이틀의 메뉴를 생성하였습니다.&lt;br&gt;참고로, (&amp;amp;F) 라는 것은, 이미 GUI프로그래밍 경험이 있으신분이라면 설명하지 않아도 아실 듯한데요, 보통 알트키와 함께 눌렀을떄 메뉴나 액션이 실행되는 단축키(정확한 명칭은 모르겠네요)입니다.&lt;br&gt;이경우 알트+F를 누르면 파일메뉴목록이 표시되는 것이죠.&lt;br&gt;&lt;br&gt;d-&amp;gt;newFileAction = fileMenu-&amp;gt;addAction(trUtf8(&quot;새 파일(&amp;amp;N)&quot;));&lt;br&gt;이제 메뉴를 생성하였으니, 하위 항목으로 액션을 생성합니다.&lt;br&gt;일반적으로 모든 위젯은 액션 리스트를 가지고 있고, 여기에 액션을 추가하기위해서는 QWidget::addAction(QAction *)함수를 이용합니다만, QMenu클래스의 경우는 편의를 몇가지 오버로드된 addAction()함수를 제공합니다.&lt;br&gt;위 함수는 QAction *QMenu::addAction(const Qstring &amp;amp;text)의 원형을 가지고 있고, text라는 이름으로 표시되는 QAction인스턴스를 생성하여, 그 포인터를 반환해줍니다.&lt;br&gt;이걸로 파일 메뉴에 새 파일 액션이 생성되었습니다.&lt;br&gt;&lt;br&gt; d-&amp;gt;newFileAction-&amp;gt;setShortcut(QKeySequence(&quot;Ctrl+N&quot;)); &lt;br&gt;액션의 단축키(shortcut)를 지정해줍니다. 단축키는 필수사항은 아니지만 자주이용하는 액션이라면 단축키가 있는 것이 편리하겠죠. 단축키는 QKeySequence 클래스를 이용하여 지정할 수 있습니다.&lt;br&gt;QKeySequence를 생성하는 데에는 몇가지 방법이 있는데, 다음 두가지가 가장 자주 이용됩니다.&lt;br&gt;QKeySequence(const QString &amp;amp;key);&lt;br&gt;QKeySequence(int k1, int k2 = 0, int k3 = 0, int k4 = 0);&lt;br&gt;&lt;p style=&quot;margin: 0px; text-indent: 0px; color: rgb(0, 0, 0);&quot;&gt;이경우 전자를 이용하였는데, 바로 키를 문자열로 적는 방법입니다. 간단하죠? 후자의 경우는, 키코드를 입력하는 방법입니다. 후자를 이용하면, QKeySequence(Qt::CTRL + Qt::Key_N)과 같이 적을수 있습니다.&lt;br&gt;&lt;/p&gt;&lt;br&gt; QToolBar *fileBar = addToolBar(trUtf8(&quot;파일 도구막대&quot;));&lt;br&gt;QMainWindow::addToolBar()함수는 주어진 이름으로 툴바를 추가해줍니다. 툴바도 하나의 위젯이며 도킹윈도우처럼 자유롭게 메인윈도우에 붙였다 땔수 있고, 떨어져있을 경우 여기서 지정된 창이름으로 표시되고, 툴바에서 오른쪽 마우스 버튼을 클릭했을때 나타나는 툴바 목록에도 같은 이름으로 표시됩니다.&lt;br&gt;&lt;br&gt;fileBar-&amp;gt;addAction(d-&amp;gt;newFileAction);&lt;br&gt;앞에서 설명했듯이, 모든 위젯은 자체의 액션 리스트를 가지고 있습니다. QToolBar클래스의 경우, 액션리스트를 툴바의 형태로 표시해줍니다. QToolBar클래스도 QMenu클래스와 마찬가지로 편의를 위해 다양한 형태로 오버로드된 addAction()함수를 제공하지만, 이경우는 이미 생성되어있는 액션을 추가하는 것이므로, addAction(QAction*)을 이용합니다.&lt;br&gt;이것으로 파일 툴바를 추가하고 거기에 새 파일 액션이 추가되었습니다.&lt;br&gt;&lt;br&gt;connect(d-&amp;gt;newFileAction, SIGNAL(triggered()), this, SLOT(newFile()));&lt;br&gt;QAction클래스에는 몇가지 시그널이 있는데 그중 다음 두개가 가장 자주 쓰입니다.&lt;br&gt;void QAction::triggered(bool checked = false);&lt;br&gt;void QAction::toggled(bool checked);&lt;br&gt;전자는 액션이 유저에의해서 활성화될때(클릭하거나 단축키를 누르거나 등...) 이 시그널이 발생합니다. 그리고 액션을 체크가능하게 설정했을 경우(setCheckable), check되있는 상태가 checked변수로 전달됩니다. 예제에서는 체크할수 있는 액션이 아니므로, 이변수는 무시하였습니다(디폴트 인자가 주어져있으므로 무시할수 있습니다).&lt;br&gt;후자는 체크가능한 액션에 대해서, 체크된 상태가 변했을때 발생합니다.&lt;br&gt;예제에서는 전자의 시그널을 이용하여, newFile()슬롯으로 연결하였습니다. 이처럼 액션은, triggered()나 toggled()시그널을, 원하는 동작을 하는 슬롯으로 연결하여 이용하는 것이 보통입니다.&lt;br&gt;이제 d-&amp;gt;newFileAction이 실행될떄마다 newFile()함수가 호출됩니다.&lt;br&gt;&lt;br&gt;그러면 마지막으로 newFile()함수를 살펴보겠습니다.&lt;br&gt;void MainWindow::newFile() {&lt;br&gt;&amp;nbsp; &amp;nbsp; d-&amp;gt;edit-&amp;gt;clear();&lt;br&gt;}&lt;br&gt;간단합니다. QTextEdit::clear()함수는 내용을 모두 비워버리는 함수입니다. 지금 작성하고있는 어플리케이션은 SDI이므로, 현재 창을 깨끗이 비워주면 곧 새파일을 만드는 셈입니다. 물론 보통은 지금 작성중인 문서를 저장하겠냐는 둥 뭔가 추가로 작업을 해주어야 하지만, 일단은 이번편은 메뉴와 툴바를 만드는 법을 설명하는 것이 목표이므로 일단 간단하게 구현하였습니다.&lt;br&gt;&lt;br&gt;이제 컴파일하고 실행해봅시다.&lt;br&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;img src=&quot;http://xylosper.net/attach/1/1052431393.png&quot; alt=&quot;실행화면&quot; height=&quot;257&quot; width=&quot;266&quot; /&gt;&lt;p class=&quot;cap1&quot;&gt;실행화면&lt;/p&gt;&lt;/div&gt;파일 메뉴가 추가되었고, 툴바도 생성된 것을 확인할수 있습니다.&lt;br&gt;적당히 몇글자 적어보고 툴바의 새 파일 버튼을 눌러보거나, 메뉴에서 새 파일을 클릭하거나, Ctrl+N을 눌러보면 작성된 내용이 모두 지워지는 것을 알수 있습니다.&lt;br&gt;그런데 뭔가 어색합니다. 보통 툴바에는 액션자체의 이름보다는, 아이콘이 표시되는데, 여기선 이름이 바로 표시되고있습니다.&lt;br&gt;아이콘을 지정해주면 되는데, 이건 매우 간단합니다. 하지만 여기서 함께 설명하지 않은 것은, 아이콘을 지정하는 것과 함께 &#039;리소스&#039;를 이용하는 방법을, 다음에 같이 설명하기 위해서입니다.&lt;br&gt;다음편에서는 리소스를 이용하는 법과, 리소스를 이용하여 아이콘을 설정하는 법을 알아보겠습니다.&lt;br&gt;</description>
			<category>Qt</category>
			<category>QAction</category>
			<category>QMenu</category>
			<category>Qt</category>
			<category>QToolBar</category>
			<category>메뉴</category>
			<category>액션</category>
			<category>툴바</category>
			<author>(xylosper)</author>
			<guid>http://xylosper.net/123</guid>
			<comments>http://xylosper.net/123#entry123comment</comments>
			<pubDate>Tue, 02 Sep 2008 09:52:34 +0900</pubDate>
		</item>
		<item>
			<title>삽질</title>
			<link>http://xylosper.net/122</link>
			<description>오랜만에 Qt에 대하여를 썼는데, 이전편을 참조할게 있어서 열어놨다가, 실수로 새로 쓴 글을 갱신한다는게 오래된 글(6번)을 갱신해버렸다-_-;&lt;br&gt;결국 고민 끝이 6번이후의 글을 전부 갱신해서 순서를 맞추는 삽질을 했다...&lt;br&gt;새벽에 뭐하는건지...&lt;br&gt;</description>
			<category>Trivia</category>
			<category>삽질</category>
			<author>(xylosper)</author>
			<guid>http://xylosper.net/122</guid>
			<comments>http://xylosper.net/122#entry122comment</comments>
			<pubDate>Mon, 25 Aug 2008 05:12:51 +0900</pubDate>
		</item>
		<item>
			<title>Qt에 대하여 - 10. 실전! - 텍스트 에디터(1)</title>
			<link>http://xylosper.net/121</link>
			<description>원래 이번편은 폼디자인할때 자주쓰이는 위젯들에 대해서 설명할려고 했는데, &lt;del&gt;생각해보니 한둘도 아니고&lt;/del&gt; 자주쓰인다는 기준도 좀 모호하고, 그냥 함수설명하는 거라면 assistant찾아보면 다 나오는 것들이니, 별 영양가있는 내용이 나올것 같지않아서, 방향을 바꾸고, 이번편 부터는 직접 어플리케이션을 짜보도록 하겠습니다.&lt;br /&gt;&lt;br /&gt;만들 어플리케이션은 텍스트 에디터입니다.&lt;br /&gt;이미 assistant에서도 application이라는 이름의 예제로 텍스트 에디터를 제시할만큼, Qt로 어플리케이션을 만드는 방법을 설명하는데 있어서 그럴듯하면서도 이보다 간단한 예제는 드물듯 합니다.&lt;br /&gt;&lt;br /&gt;텍스트 에디터라고 해도, 우리가 직접 인코딩 디코딩을 해주거나 할 필요는 없습니다.&lt;br /&gt;Qt에는 QTextEdit라는, 텍스트 에디터로 바로 써도 손색없는 훌률한 위젯이 있습니다.&lt;br /&gt;그러므로, 이 예제는 텍스트를 편집하는 방법 그 자체가 아니라, 어플리케이션이 일반적으로 지니고 있는 메뉴나 상태바, 툴바등을 어떻게 다룰지를 설명하는데 그 중점이 놓여질 것입니다.&lt;br /&gt;&lt;br /&gt;또한, 일반적으로 문서를 다루는 어플리케이션에는 SDI와 MDI 두가지가 있다는 것 알고 계시죠?&lt;br /&gt;&lt;p id=&quot;more121_0&quot; class=&quot;moreless_fold&quot;&gt;&lt;span style=&quot;cursor: pointer;&quot; onclick=&quot;toggleMoreLess(this, &#039;121_0&#039;,&#039;모르는데?&#039;,&#039;접기&#039;); return false;&quot;&gt;모르는데?&lt;/span&gt;&lt;/p&gt;&lt;div id=&quot;content121_0&quot; class=&quot;moreless_content&quot; style=&quot;display: none;&quot;&gt;SDI는 Single Document Interface의 약자로, 하나의 어플리케이션 내에서 하나의 문서만 편집 가능한 형태입니다. 윈도우의 그림판 같이, 새로운 문서로 작업 할려면 기존에 열려진 문서는 닫아야 하는 인터페이스이죠.&lt;br /&gt;반면에 MDI는 Multiple Documents Interface의 약자로, 하나의 어플리케이션에서, 동시의 여러개의 문서를 열고 편집할수 있는 인터페이스입니다. 포토샵과 같이, 이미 열린 문서가 있어도, 동시에 다른 문서를 열어서 편집할수 있습니다.&lt;/div&gt;간편을 위해서 일단 처음은 SDI로 시작하겠지만, 최종적으로는 MDI로 확장할 예정입니다.&lt;br /&gt;&lt;br /&gt;1. QMainWindow&lt;br /&gt;보통 어플리케이션을 만들때, 최상위 윈도우는 QMainWindow 클래스를 상속받아서 구현합니다.&lt;br /&gt;QMainWindow 클래스에는, 일반적인 어플리케이션이 갖추고 있는 메뉴바, 툴바, 상태바들이 구현되어있고, 위젯들을 도킹시키기 위한 영역도 가지고 있기 때문에 매우 간단하게 어플리케이션을 만드는 것이 가능합니다.&lt;br /&gt;QMainWindow를 상속받아서 MainWindow라는 클래스를 만들어 보겠습니다.&lt;br /&gt;&lt;br /&gt;mainwindow.h&lt;br /&gt;[code]&lt;br /&gt;#ifndef MAINWINDOW_H&lt;br /&gt;#define MAINWINDOW_H&lt;br /&gt;&lt;br /&gt;#include &amp;lt;QMainWindow&amp;gt;&lt;br /&gt;&lt;br /&gt;class MainWindow : public QMainWindow {&lt;br /&gt;&amp;nbsp; &amp;nbsp; Q_OBJECT&lt;br /&gt;public:&lt;br /&gt;&amp;nbsp; &amp;nbsp; MainWindow(QWidget *parent = 0);&lt;br /&gt;&amp;nbsp; &amp;nbsp; ~MainWindow();&lt;br /&gt;private:&lt;br /&gt;&amp;nbsp; &amp;nbsp; struct Data;&lt;br /&gt;&amp;nbsp; &amp;nbsp; Data *d;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;#endif&lt;br /&gt;[/code]&lt;br /&gt;mainwindow.cpp&lt;br /&gt;
[code]&lt;br /&gt;
#include &quot;mainwindow.h&quot;&lt;br /&gt;&lt;br /&gt;struct MainWindow::Data {&lt;br /&gt;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;MainWindow::MainWindow(QWidget *parent)&lt;br /&gt;: QMainWindow(parent), d(new Data) {&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;MainWindow::~MainWindow() {&lt;br /&gt;&amp;nbsp; &amp;nbsp; delete d;&lt;br /&gt;}&lt;br /&gt;
[/code]&lt;br /&gt;QMainWindow를 상속받아 MainWindow를 만들었습니다.&lt;br /&gt;private 멤버로 Data *d를 선언하고 있는데, 이건 필자의 프로그래밍 스타일입니다.&lt;br /&gt;이렇게 함으로써, 해더파일을 수정할 필요없이, 멤버들을 자유롭게 추가할수가 있기때문에, 이경우 처럼 해더파일의 의존성이 거의 0나 마찬가지인 클래스에서도 습관적으로 private영역에 데이터 전용 클래스를 선언하여 이용합니다. 이 데이터 클래스의 정의는 mainwindow.cpp에 있는데, 이로써 실제로 데이터 클래스의 구현을 숨기는 효과도 있습니다.&lt;br /&gt;데이터 클래스에 지금은 아무것도 안들어있지만, 앞으로 추가할 멤버가 필요하면 여기에 추가해가게 될 것입니다.&lt;br /&gt;&lt;br /&gt;이제 메인함수와 프로필파일을 만들어서 컴파일해보겠습니다.&lt;br /&gt;main.cpp&lt;br /&gt;[code]&lt;br /&gt;#include &amp;lt;QApplication&amp;gt;&lt;br /&gt;#include &quot;mainwindow.h&quot;&lt;br /&gt;&lt;br /&gt;int main(int argc, char **argv) {&lt;br /&gt;&amp;nbsp; &amp;nbsp; QApplication app(argc, argv);&lt;br /&gt;&amp;nbsp; &amp;nbsp; MainWindow w;&lt;br /&gt;&amp;nbsp; &amp;nbsp; w.show();&lt;br /&gt;&amp;nbsp; &amp;nbsp; return app.exec();&lt;br /&gt;}&lt;br /&gt;[/code]&lt;br /&gt;&lt;br /&gt;texteditor.pro&lt;br /&gt;[code]&lt;br /&gt;TEMPLATE = app&lt;br /&gt;CONFIG += warn_on &lt;br /&gt;TARGET = texteditor&lt;br /&gt;&lt;br /&gt;HEADERS += mainwindow.h&lt;br /&gt;&lt;br /&gt;SOURCES += main.cpp \&lt;br /&gt;&amp;nbsp; &amp;nbsp; mainwindow.cpp&lt;br /&gt;[/code]&lt;br /&gt;&lt;br /&gt;처음으로 어플리케이션을 만들어 보는 것이므로 프로필 파일까지 처음부터 작성해보았습니다.&lt;br /&gt;어플리케이션 이름은 texteditor로 하였습니다.&lt;br /&gt;이상의 네 파일을 한 디렉토리안에 작성하고, 컴파일(qmake &amp;amp;&amp;amp; make)해주면, 실행파일이 튀어나옵니다.&lt;br /&gt;한번 실행해봅시다.&lt;br /&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;img src=&quot;http://xylosper.net/attach/1/1361370704.png&quot; alt=&quot;메인윈도우&quot; height=&quot;130&quot; width=&quot;210&quot; /&gt;&lt;p class=&quot;cap1&quot;&gt;썰렁하기 그지없는 모습&lt;/p&gt;&lt;/div&gt;위 그림과 같이 아무것도 없는 창하나가 뜰 것입니다.&lt;br /&gt;뭐야~ 메뉴바같은거 다 구현되있다며~ 라고 따지실 분이 계실지도 모르겠지만, &#039;구현&#039;되어있는 것과 객체를 만드는 것은 다릅니다.&lt;br /&gt;OOP인 만큼, 메뉴바도 상태바도 다 객체이고, 이것들은 생성해주어야 합니다.&lt;br /&gt;이것들을 생성하는 것은 곧 보게될 것입니다.&lt;br /&gt;&lt;br /&gt;이제 하나씩 만들어 갑시다.&lt;br /&gt;일단은 텍스트를 편집할 부분이 필요합니다.&lt;br /&gt;처음에 말했듯이, QTextEdit라는 클래스를 이용합니다.&lt;br /&gt;mainwindow.cpp&lt;br /&gt;[code]&lt;br /&gt;#include &quot;mainwindow.h&quot;&lt;br /&gt;#include &amp;lt;QTextEdit&amp;gt;&lt;br /&gt;&lt;br /&gt;struct MainWindow::Data {&lt;br /&gt;&amp;nbsp; &amp;nbsp; QTextEdit *edit;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;MainWindow::MainWindow(QWidget *parent)&lt;br /&gt;: QMainWindow(parent), d(new Data) {&lt;br /&gt;&amp;nbsp; &amp;nbsp; d-&amp;gt;edit = new QTextEdit(this);&lt;br /&gt;&amp;nbsp; &amp;nbsp; setCentralWidget(d-&amp;gt;edit);&lt;br /&gt;}&lt;br /&gt;[/code]&lt;br /&gt;QTextEdit 클래스를 이용하기 위해 해더파일을 추가하고, 데이터 클래스에 QTextEdit *edit를 추가하였습니다.&lt;br /&gt;생성자로 가보면 edit에 객체를 생성하여 할당하고 있습니다.&lt;br /&gt;QTextEdit의 생성자로 this를 넘기는 것은 설명하지 않아도 될것이라고 믿습니다(왜인지 모르시는 분은 &lt;a href=&quot;http://xylosper.net/entry/Qt%BF%A1-%B4%EB%C7%CF%BF%A9-6-Meta-Object-System&quot; target=&quot;_blank&quot;&gt;6편&lt;/a&gt;을 복습하시기 바랍니다).&lt;br /&gt;그다음 줄을 보면 setCentralWidget(d-&amp;gt;edit); 라는 함수를 호출하고 있습니다.&lt;/p&gt;&lt;p style=&quot;margin: 0px; text-indent: 0px;&quot;&gt;QMainWIndow는, 위젯을 몇개의 영역으로 나누고 있습니다.&lt;/p&gt;&lt;p style=&quot;margin: 0px; text-indent: 0px;&quot;&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;img src=&quot;http://xylosper.net/attach/1/1072677405.png&quot; alt=&quot;사용자 삽입 이미지&quot; height=&quot;318&quot; width=&quot;350&quot; /&gt;&lt;p class=&quot;cap1&quot;&gt;QMainWindow의 영역(Qt assistant QMainWindow항목으로부터 인용)&lt;/p&gt;&lt;/div&gt;위 그림과 같이, 제일 상단에 메뉴바를, 제일 하단에 상태바를, 그 안쪽으로 툴바 영역을, 또 그안쪽으로는 도킹 영역을, 그리고 가장 안쪽에 &#039;Central Widget&#039;을 위한 영역이 있습니다.&lt;/p&gt;&lt;p style=&quot;margin: 0px; text-indent: 0px;&quot;&gt;이 Central Widget이 바로 어플리케이션에서 주된 기능(이경우는 텍스트 편집)을 담당하는 위젯이 될 것입니다.&lt;br /&gt;&lt;!--EndFragment--&gt;&lt;/p&gt;setCentralWidget함수는 이름 그대로 central widget을 지정하기 위한 함수입니다.&lt;br /&gt;이제 central widget에는 QTextEdit의 인스턴스인 d-&amp;gt;edit가 들어가있습니다.&lt;br /&gt;수정된 파일을 다시 컴파일하고 실행해보면 다음과 같은 창이 뜹니다.&lt;br /&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;img src=&quot;http://xylosper.net/attach/1/1289990956.png&quot; alt=&quot;사용자 삽입 이미지&quot; height=&quot;222&quot; width=&quot;266&quot; /&gt;&lt;/div&gt;우리는 central widget이외에 아무것도 생성하지 않았기 때문에, d-&amp;gt;edit외에 아무것도 안나옵니다.&lt;br /&gt;이 창에서 이것저것 글씨를 적을수 있습니다. 그뿐만 아니라 복사하기와 붙여넣기도 가능하고, 편집한 내용을 되돌리거나 다시 실행하기(undo/redo)도 가능합니다.&lt;br /&gt;이것들은 모두 이미 QTextEdit에서 구현되어있는 기능들입니다.&lt;br /&gt;따라서 우리는 사실상 텍스트자체를 편집하기 위해서 딱히 해줘야할 것들은 없고, 어플리케이션을 구현하는 만드는 방법에 집중할 수 있을 것입니다.&lt;br /&gt;&lt;br /&gt;내용이 길어지므로 이번편의 내용은 이쯤에서 마치겠습니다.&lt;br /&gt;마지막으로 이번편에 이용한 예제 소스파일을 첨부합니다.&lt;br /&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;a class=&quot;extensionIcon&quot; href=&quot;http://xylosper.net/attachment/1311819740.gz&quot;&gt;&lt;img src=&quot;http://xylosper.net/image/extension/gz.gif&quot; alt=&quot;&quot; /&gt; texteditor.tar.gz&lt;/a&gt;&lt;p class=&quot;cap1&quot;&gt;예제코드&lt;/p&gt;&lt;/div&gt;다음편에는 메뉴바작성을 해보겠습니다.&lt;br /&gt;&lt;br /&gt;</description>
			<category>Qt</category>
			<author>(xylosper)</author>
			<guid>http://xylosper.net/121</guid>
			<comments>http://xylosper.net/121#entry121comment</comments>
			<pubDate>Mon, 25 Aug 2008 05:09:59 +0900</pubDate>
		</item>
		<item>
			<title>CMPlayer 0.2.0을 릴리즈</title>
			<link>http://xylosper.net/120</link>
			<description>CMPlayer 0.2.0을 공개합니다.&lt;br&gt;이번 버전에서 가장큰 변화는, 백엔드가 MPlayer에서 xine으로 변경된 것입니다.&lt;br&gt;기존에 이용하시던 분은, xine을 설치하셔야 0.2.0을 이용할 수 있습니다.&lt;br&gt;&lt;br&gt;백엔드를 변경함으로써, 다음의 두가지가 가능해졌습니다.&lt;br&gt;&lt;br&gt;1. DVD메뉴지원&lt;br&gt;DVD메뉴를 조작하는 것이 가능해졌습니다.&lt;br&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;img src=&quot;http://xylosper.net/attach/1/1350989177.png&quot; alt=&quot;DVD 메뉴 스크린샷&quot; height=&quot;402&quot; width=&quot;530&quot; /&gt;&lt;p class=&quot;cap1&quot;&gt;메뉴 선택 화면&lt;/p&gt;&lt;/div&gt;당연히 이 메뉴를 통해서 장면 탐색이나 자막 선택도 가능합니다.&lt;br&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;img src=&quot;http://xylosper.net/attach/1/1128700286.png&quot; alt=&quot;DVD 장면 색인 스크린샷&quot; height=&quot;402&quot; width=&quot;530&quot; /&gt;&lt;p class=&quot;cap1&quot;&gt;장면 색인&lt;/p&gt;&lt;/div&gt;0.1.3에서는 컨텍스트메뉴로 챕터별로 탐색하도록 만들었는데, 이 챕터별 탐색은 순서도 뒤죽박죽이고 어떤 내용이 들어있는지도 알수 없기 때문에, DVD메뉴지원을 추가하고 챕터 탐색을 삭제하였습니다.&lt;br&gt;&lt;br&gt;2. 컬러 자막 지원&lt;br&gt;xine에서는 256색의 컬러 OSD를 그리는것이 가능합니다. 이것을 이용하여, 직접 자막파일을 파싱하여 뿌려주도록 하고, 색깔도 지정할 수 있습니다.&lt;br&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;img src=&quot;http://xylosper.net/attach/1/1140005601.png&quot; alt=&quot;컬러 자막 스크린샷&quot; height=&quot;424&quot; width=&quot;530&quot; /&gt;&lt;p class=&quot;cap1&quot;&gt;컬러 자막&lt;/p&gt;&lt;/div&gt;스샷은 굉장히 해상도가 높은 동영상 파일이기 때문에 자막이 굉장히 깨끗하게 나왔는데, 일반적인 동영상 해상도에서 자막의 품질 자체는 좀 떨어집니다. 컬러지원이 가능하다는데 의의를 두었습니다. 더불어 smi자막의 색깔지정 태그도 적용됩니다.&lt;br&gt;덤으로, san serif같은 fontconfig로 조합된 글꼴도 제대로 인식하기 때문에, 예를 들어 일본어 폰트와 한국어 폰트를 san serif에 매칭시켜놓고, 자막파일을 유니코드로 만들 경우, 동시에 일본어와 한글을 깨지지 않고 표시하는게 가능합니다.&lt;br&gt;위 스샷을 보면 会라는 會의 약자가 깨지지 않고 한글과 동시에 표시되는 것을 알수 있습니다.&lt;br&gt;&lt;br&gt;&lt;br&gt;xine으로 백엔드를 변경함으로 얻은 것도 있지만, 잃은 것도 있습니다.&lt;br&gt;1. 깔끔하지 못한 탐색&lt;br&gt;xine의 탐색 정책(seeking policy)때문에, 짧은 시간간격으로 앞으로 이동할경우, 반대로 뒤로가버리는 경우가 발생합니다.&lt;br&gt;이건 xine자체의 문제라 어떻게 할수가 없습니다. 대신에, 연속으로 탐색에 실패할경우 자동으로 탐색 시간을 늘려서 뛰어넘을수 있도록 만들었습니다.&lt;br&gt;&lt;br&gt;2. 여백 표시에따른 제한&lt;br&gt;여백으로 화면을 확장하여, 전체화면일때 상하 검은 여백에 자막을 표시하는 기능은 유지할 수 있었습니다(위 스샷참고).&lt;br&gt;다만, xine의 경우 영상을 확장하면 임의로 화면비율을 조절하는게 불가능한 단점이 있어, 여백에 표시하기를 활성화시키면 화면비율 변경 및 잘라내기가 불가능해집니다.&lt;br&gt;&lt;br&gt;마지막으로, 기본적으로 비활성화되어있습니다만, 자막 OSD 설정에 고품질 설정이란 것이 있습니다.&lt;br&gt;이부분을 활성화 시키면, 영상을 확대해도 자막이 늘어져서 품질이 떨어지는 현상은 없어지지만, 대신에 동영상을 제대로 보기가 힘들 정도로 버벅일수 있습니다.&lt;br&gt;최대한 속도를 올리고 올렸는데 이정도인지라, 일단 구현한게 아까워서 넣어두긴 했는데, 그다지 추천하진 않습니다.&lt;br&gt;한번 흥미있으신분은 적용해보세요.&lt;br&gt;&lt;br&gt;그외의 바뀐점들은, 릴리즈노트 및 변동 사항을 참고해주세요.&lt;br&gt;&lt;br&gt;릴리즈된 파일은 언제나처럼 &lt;a href=&quot;http://kldp.net/frs/?group_id=1243&quot; target=&quot;&quot;&gt;CMPlayer 프로젝트 페이지&lt;/a&gt;에서 다운받을수 있습니다.&lt;br&gt;&lt;br&gt;나름 혼자 써보면서 알아챈 부분은 다 고친다고 하긴 했지만, 혼자 테스트하는데에는 한계도 있고, 백엔드를 변경하면서 xine에 대한 이해부족으로 놓친 것들도 많을 듯합니다.&lt;br&gt;사용하시면서 문제점을 발견하신분은 여기나 &lt;a href=&quot;http://kldp.net/frs/?group_id=1243&quot; target=&quot;&quot;&gt;CMPlayer 프로젝트 페이지&lt;/a&gt;에 알려주시기 바랍니다.&lt;br&gt;</description>
			<category>CMPlayer</category>
			<category>CMPlayer</category>
			<category>xine</category>
			<category>동영상 플레이어</category>
			<author>(xylosper)</author>
			<guid>http://xylosper.net/120</guid>
			<comments>http://xylosper.net/120#entry120comment</comments>
			<pubDate>Sat, 16 Aug 2008 02:26:27 +0900</pubDate>
		</item>
		<item>
			<title>CMPlayer 0.1.3 릴리즈</title>
			<link>http://xylosper.net/119</link>
			<description>CMPlayer 0.1.3을 릴리즈하였습니다.&lt;br /&gt;&lt;br /&gt;DVD 재생기능이 추가되었습니다.&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://kldp.net/frs/?group_id=1243&quot; target=&quot;&quot;&gt;다운로드 페이지&lt;/a&gt;&lt;br /&gt;</description>
			<category>CMPlayer</category>
			<category>CMPlayer</category>
			<author>(xylosper)</author>
			<guid>http://xylosper.net/119</guid>
			<comments>http://xylosper.net/119#entry119comment</comments>
			<pubDate>Sun, 13 Jul 2008 06:02:19 +0900</pubDate>
		</item>
		<item>
			<title>CMPlayer 0.1.2 릴리즈</title>
			<link>http://xylosper.net/118</link>
			<description>CMPlayer 0.1.2를 릴리즈하였습니다.&lt;br /&gt;
&lt;br /&gt;
전체화면시에 상하단의 검은 여백에도 자막이 출력가능하도록 변경되었습니다.&lt;br /&gt;
환경설정-&amp;gt;자막에서 설정할 수 있습니다.&lt;br /&gt;
&lt;br /&gt;
그외 변경사항에 대해서는 릴리즈노트 및 변동사항을 참고해주세요.&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://kldp.net/frs/?group_id=1243&quot; target=&quot;_blank&quot;&gt;다운로드 페이지&lt;/a&gt;&lt;br /&gt;</description>
			<category>CMPlayer</category>
			<category>CMPlayer</category>
			<category>동영상플레이어</category>
			<author>(xylosper)</author>
			<guid>http://xylosper.net/118</guid>
			<comments>http://xylosper.net/118#entry118comment</comments>
			<pubDate>Sun, 01 Jun 2008 19:03:57 +0900</pubDate>
		</item>
		<item>
			<title>CMPlayer(구 CMP) 0.1.1 릴리즈</title>
			<link>http://xylosper.net/117</link>
			<description>CMPlayer 0.1.1을 릴리즈하였습니다.&lt;br /&gt;&lt;br /&gt;diff &amp;amp; cmp의 cmp(compare)와 겹치기 때문에 파일명을 cmplayer로 변경하고 이에 맞춰 프로젝트이름도 CMPlayer로 변경하였습니다.&lt;br /&gt;&lt;br /&gt;앞으로 릴리즈및 피드백은 &lt;a href=&quot;http://kldp.net/projects/cmplayer/&quot; target=&quot;_blank&quot;&gt;KLDP.net의 CMPlayer 프로젝트 페이지&lt;/a&gt;에서 하도록 할 예정입니다.&lt;br /&gt;&lt;br /&gt;cmplayer-0.1.1&lt;br /&gt;&lt;br /&gt;릴리즈 노트: 앞으로 설정파일 등 프로그램에서 생성하는 파일들은 ~/.cmplayer에 저장됩니다.&lt;br /&gt;&lt;br /&gt;변동사항:&lt;br /&gt;재생중에 중지된 파일 기억하기 추가&lt;br /&gt;마우스 메뉴를 메뉴로 명칭 변경&lt;br /&gt;시스템 종료를 위한 인증방법 변경 - 기존의 방식으로는 메모리상에 패스워드가 남아있게 되기 때문에 sudo를 이용하여 루트권한으로 프로그램을 재시작하도록 변경함&lt;br /&gt;재생 목록 열기/저장 추가 - pls 형식의 재생 목록 파일을 열고 저장할 수 있음&lt;br /&gt;윈도우 사이즈에 비해 파일명이 길 때 파일명 중간을 ... 으로 생략하도록 변경&lt;br /&gt;재생 속도 조절 기능 및 음조 자동 조절 옵션 추가&lt;br /&gt;간이 모드 삭제&lt;br /&gt;파일 경로 변경 - 사용자의 home 아래의 .cmplayer 디렉토리에 생성하도록 변경함&lt;br /&gt;&lt;br /&gt;버그 수정&lt;br /&gt;환경 설정후 새로운 파일을 재생하면 자막을 선택할 수 없는 버그를 수정&lt;br /&gt;환경 설정후 메뉴의 아이콘이 사라지는 버그를 수정</description>
			<category>CMPlayer</category>
			<category>CMPlayer</category>
			<author>(xylosper)</author>
			<guid>http://xylosper.net/117</guid>
			<comments>http://xylosper.net/117#entry117comment</comments>
			<pubDate>Wed, 16 Apr 2008 23:36:01 +0900</pubDate>
		</item>
		<item>
			<title>Qt에 대하여 - 9. Qt Designer - 폼 적용하기</title>
			<link>http://xylosper.net/116</link>
			<description>이번 시간엔 지난 시간에 작성한 ui파일을 이용하여 실제로 어떻게 프로그램에 적용하는지 알아보도록하겠습니다.&lt;br&gt;이번엔 ui파일을 포함한 소스파일도 첨부합니다.&lt;br&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;a class=&quot;extensionIcon&quot; href=&quot;http://xylosper.net/attachment/1045446795.gz&quot;&gt;&lt;img src=&quot;http://xylosper.net/image/extension/gz.gif&quot; alt=&quot;&quot; /&gt; testdialog.tar.gz&lt;/a&gt;&lt;p class=&quot;cap1&quot;&gt;예제 소스 파일&lt;/p&gt;&lt;/div&gt;&lt;br&gt;main.cpp&lt;br&gt;[code]#include &amp;lt;QApplication&amp;gt;&lt;br&gt;#include &quot;testdialog.h&quot;&lt;br&gt;&lt;br&gt;int main(int argc, char **argv) {&lt;br&gt;&amp;nbsp; &amp;nbsp; QApplication app(argc, argv);&lt;br&gt;&amp;nbsp; &amp;nbsp; TestDialog dlg;&lt;br&gt;&amp;nbsp; &amp;nbsp; dlg.show();&lt;br&gt;&amp;nbsp; &amp;nbsp; return app.exec();&lt;br&gt;}&lt;br&gt;[/code]testdialog.h&lt;br&gt;[code]&lt;br&gt;#ifndef TESTDIALOG_H&lt;br&gt;#define TESTDIALOG_H&lt;br&gt;&lt;br&gt;#include &amp;lt;QDialog&amp;gt;&lt;br&gt;#include &quot;ui_testdialog.h&quot;&lt;br&gt;&lt;br&gt;class QButtonGroup;&lt;br&gt;&lt;br&gt;class TestDialog : public QDialog {&lt;br&gt;&amp;nbsp; &amp;nbsp; Q_OBJECT&lt;br&gt;public:&lt;br&gt;&amp;nbsp; &amp;nbsp; enum Color {RGB = 0, CMYK, YUV};&lt;br&gt;&amp;nbsp; &amp;nbsp; TestDialog();&lt;br&gt;private slots:&lt;br&gt;&amp;nbsp; &amp;nbsp; void setColorChecked(int id);&lt;br&gt;private:&lt;br&gt;&amp;nbsp; &amp;nbsp; Ui::TestDialog ui;&lt;br&gt;&amp;nbsp; &amp;nbsp; QButtonGroup *buttons;&lt;br&gt;};&lt;br&gt;&lt;br&gt;#endif&lt;br&gt;[/code]testdialog.cpp&lt;br&gt;[code]&lt;br&gt;#include &amp;lt;QButtonGroup&amp;gt;&lt;br&gt;#include &quot;testdialog.h&quot;&lt;br&gt;&lt;br&gt;TestDialog::TestDialog() {&lt;br&gt;&amp;nbsp; &amp;nbsp; ui.setupUi(this);&lt;br&gt;&amp;nbsp; &amp;nbsp; buttons = new QButtonGroup(this);&lt;br&gt;&amp;nbsp; &amp;nbsp; buttons-&amp;gt;addButton(ui.rgb_radio, RGB);&lt;br&gt;&amp;nbsp; &amp;nbsp; buttons-&amp;gt;addButton(ui.cmyk_radio, CMYK);&lt;br&gt;&amp;nbsp; &amp;nbsp; buttons-&amp;gt;addButton(ui.yuv_radio, YUV);&lt;br&gt;&amp;nbsp; &amp;nbsp; connect(buttons, SIGNAL(buttonClicked(int)), ui.color_combo, SLOT(setCurrentIndex(int)));&lt;br&gt;&amp;nbsp; &amp;nbsp; connect(ui.color_combo, SIGNAL(currentIndexChanged(int)), this, SLOT(setColorChecked(int)));&lt;br&gt;}&lt;br&gt;&lt;br&gt;void TestDialog::setColorChecked(int id) {&lt;br&gt;&amp;nbsp; &amp;nbsp; buttons-&amp;gt;button(id)-&amp;gt;setChecked(true);&lt;br&gt;}&lt;br&gt;[/code]&lt;br&gt;지난번에 만든 ui파일(전 testdialog.ui 란 이름으로 저장하였습니다)과, 위의 세 파일을 작성한후, 여느때처럼 qmake -project를 이용하여 프로젝트파일을 생성해보면 평소와 다른게 하나 있을 것입니다.&lt;br&gt;&lt;br&gt;바로 FORMS += testdialog.ui 라는 항목인데요, 이렇게 생성한 ui파일을 프로젝트파일의 FORMS 항목에 추가해주면 컴파일시에 자동으로 ui파일로부터 소스코드를 생성해줍니다.&lt;br&gt;&lt;br&gt;그러므로, 만약 qmake -project를 이용하지 않고, 직접 프로젝트 파일을 만드시는 분은, FORMS 항목을 추가하는 걸 잊지 마시기 바랍니다.&lt;br&gt;&lt;br&gt;프로젝트 파일을 생성한후, qmake로 Makefile을 만들고, make를 실행해보면 지금까지 본적 없는 작업이 앞쪽에 추가된 것이 보일 것입니다.&lt;br&gt;&lt;br&gt;/usr/bin/uic-qt4 testdialog.ui -o ui_testdialog.h&lt;br&gt;&lt;br&gt;이런 작업이 처음에 실행됩니다(/usr/bin/uic-qt4 부분은 Qt의 설치 환경에 따라 다를수 있지만 거의 다 프로그램 이름에는 uic가 들어가 있을 것입니다).&lt;br&gt;&lt;br&gt;컴파일이 끝난후 작업 디렉토리를 보면 moc_*파일 이외에 ui_testdialog.h라는 파일이 생성된 것을 알 수 있습니다.&lt;br&gt;&lt;br&gt;이 파일이 실제로 소스코드에서 쓰이는 파일입니다.&lt;br&gt;&lt;br&gt;한번 살짝 열어보면...&lt;br&gt;[code]...&lt;br&gt;#include &amp;lt;QtGui/QRadioButton&amp;gt;&lt;br&gt;#include &amp;lt;QtGui/QSlider&amp;gt;&lt;br&gt;...[/code]이렇게 ui파일에서 이용한 클래스들을 위한 해더파일의 인클루드문이나[code]...&lt;br&gt;class Ui_TestDialog&lt;br&gt;{&lt;br&gt;public:&lt;br&gt;...&lt;br&gt;&amp;nbsp; &amp;nbsp; void setupUi(QDialog *TestDialog)&lt;br&gt;&amp;nbsp; &amp;nbsp; {&lt;br&gt;&amp;nbsp; &amp;nbsp; ...&lt;br&gt;&amp;nbsp; &amp;nbsp; } // setupUi&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; void retranslateUi(QDialog *TestDialog)&lt;br&gt;&amp;nbsp; &amp;nbsp; {&lt;br&gt;&amp;nbsp; &amp;nbsp; ...&lt;br&gt;&amp;nbsp; &amp;nbsp; } // retranslateUi&lt;br&gt;&lt;br&gt;};&lt;br&gt;&lt;br&gt;namespace Ui {&lt;br&gt;&amp;nbsp; &amp;nbsp; class TestDialog: public Ui_TestDialog {};&lt;br&gt;} // namespace Ui&lt;br&gt;...[/code]이러한 클래스 선언과 정의가 포함되어있습니다.&lt;br&gt;&lt;br&gt;이 ui_testdialog.h파일이야 말로 디자이너를 이용한 UI 구현의 본체인 것입니다.&lt;br&gt;&lt;br&gt;간단하게 이 파일이 만들어 지는 과정을 설명하자면, 우선 디자이너를 이용해서 xx.ui파일을 만듭니다.&lt;br&gt;&lt;br&gt;이 xx.ui파일은 수정 편집이 용이하도록 XML로 기술되어있기 때문에 소스로 바로 이용하는 것은 불가능합니다.&lt;br&gt;&lt;br&gt;여기서 uic라는 Qt와 함께 설치되는 툴을 이용하여, xx.ui파일을 ui_xx.h로 변환해주는 것입니다.&lt;br&gt;&lt;br&gt;그러므로 FORMS 항목을 적지 않더라도, uic로 .ui파일을 해더파일로 변환해주기만 하면 문제 없습니다만, 매번 수정할때마다 작업하는게 귀찮으므로, 프로젝트 파일의 FORMS항목에 적어두어서, make할때 자동으로 uic를 돌리도록 하는게 편합니다.&lt;br&gt;&lt;br&gt;이번엔 ui_testdialog.h파일에 선언된 클래스를 살펴보겠습니다.&lt;br&gt;&lt;br&gt;우선 Ui_TestDialog 입니다.&lt;br&gt;&lt;br&gt;이 클래스의 이름은 .ui파일에서 지정한 폼의 objectName으로 결정됩니다.&lt;br&gt;&lt;br&gt;지난 시간에 TestDialog란 이름으로 지었기 때문에, 앞에 Ui_가 붙어 Ui_TestDialog란 이름이 됩니다.&lt;br&gt;&lt;br&gt;폼을 만드는데 필요한 객체들이 선언되어있고, setupUi와 restranslateUi라는 두개의 함수가 선언되어있습니다.&lt;br&gt;&lt;br&gt;retranslateUi는 UI의 문자열들을 번역내용을 갱신하기 위한 함수인데, 여기선 번역을 이용하지 않으므로 이용할일이 없습니다.&lt;br&gt;&lt;br&gt;중요한건 setupUi라는 함수입니다.&lt;br&gt;&lt;br&gt;이 함수의 내용을 보면 전전시간에 설명한 레이아웃 시스템처럼 각종 레이아웃이 생성되고 위젯들이 배치되는 과정과, 디자이너에서 연결한 시그널/슬롯들이 연결되도록 되어있습니다.&lt;br&gt;&lt;br&gt;바로 이 setupUi가 UI를 위젯이나 다이얼로그등에 적용시켜주는 함수인 것입니다.&lt;br&gt;&lt;br&gt;Ui_TestDialog외에, Ui라는 네임스페이스 속에, Ui_TestDialog를 상속하기만 하고 아무것도 하지 않는 TestDialog란 클래스가 선언되어있습니다.&lt;br&gt;&lt;br&gt;결국 Ui_TestDialog와 Ui::TestDialog는 동등하므로 어느쪽을 쓰든 상관없습니다.&lt;br&gt;&lt;br&gt;이제 소스코드를 살펴보겠습니다.&lt;br&gt;&lt;br&gt;testdialog.h의 5번째 줄을 보면 ui_testdialog.h파일을 인클루드하고 있는 것을 알 수 있습니다. 이렇게 uic로 생성된 해더파일을 직접 인클루드하여 이용합니다.&lt;br&gt;&lt;br&gt;그리고 Ui용 클래스를 이용하는 방법에는 두가지가 있습니다.&lt;br&gt;&lt;br&gt;제가 이용한 것과 같은 private 멤버로 선언하는 방법과, priavte 상속을 이용하는 방법입니다.&lt;br&gt;&lt;br&gt;상속에 대해 공부하셨다면 아시겠지만, private 상속은 public 상속과 달리 A has B 의 관계이므로 결국 private 멤버로 선언하는 것과 다를바가 없습니다.&lt;br&gt;&lt;br&gt;17번째 줄을 보면 Ui::TestDialog ui; 와 같이 UI 클래스의 객체를 선언하고 있는 것을 알 수 있습니다.&lt;br&gt;&lt;br&gt;만약 private 상속을 이용한다면, 클래스 정의 부분이&lt;br&gt;[code]class TestDialog : public QDialog, private Ui::TestDialog {[/code]와 같이 바뀌고, ui선언은 없어지겠지요.&lt;br&gt;&lt;br&gt;그리고 보통 생성사에서 Ui::TestDialog::setupUi를 호출함으로써 UI를 적용합니다.&lt;br&gt;&lt;br&gt;이 예제처럼 새로운 위젯을 직접 정의하는 경우라면 두가지 방법이 차이가 없지만, 예를 들어 특별히 복잡한 함수나 슬롯/시그널이 필요없이 간단하게 값만 입력받거나 디스플레이하기 위한 폼의 경우라면&lt;br&gt;&lt;br&gt;QDialog dlg(this);&lt;br&gt;Ui::Form ui;&lt;br&gt;ui.setupUi(&amp;amp;dlg);&lt;br&gt;&lt;br&gt;와 같이 함으로써 폼만 만들고 특별히 새로운 클래스를 작성하지 않고 이용하는 방법도 있습니다.&lt;br&gt;&lt;br&gt;이경우는 새로운 클래스를 만들지 않으므로 다중 상속을 이용한 UI의 적용은 불가능하겠지요.&lt;br&gt;&lt;br&gt;또, QButtonGroup이라는 처음보는 클래스가 있는데요, 이 클래스는 이름 그대로 버튼들을 하나의 그룹으로 묶어서 관리할때 편리합니다.&lt;br&gt;&lt;br&gt;여기서 말하는 버튼은 QAbstractButton클래스를 상속받은 클래스들로, QPushButton이나 QRadioButton, QCheckBox, QToolButton 등이 해당합니다.&lt;br&gt;&lt;br&gt;특히, QRadioButton은 처음부터 여러개중에 하나를 선택하기 위한 목적으로 연관된 버튼들이 여러개 있는 경우가 많기 때문에, QButtonGroup이 유용합니다.&lt;br&gt;&lt;br&gt;testdialog.cpp파일을 보겠습니다.&lt;br&gt;&lt;br&gt;소스를 보면 ui의 멤버로 버튼들로 접근 하고 있는 것을 알 수 있습니다.&lt;br&gt;&lt;br&gt;각 멤버의 이름은 역시 전회에서 설명한대로 디자이너에서 objectName로 지정한 값이 이용됩니다.&lt;br&gt;&lt;br&gt;만약 private멤버로 ui를 선언하지 않고, Ui::TestDialog를 private 상속 받은 경우라면 ui.대신에 보통 private 멤버처럼 접근해서 이용하면 됩니다.&lt;br&gt;&lt;br&gt;여기서 7~9번째 줄을 보면 addButton을 이용하여 라디오 버튼들을 추가하고 있는데요, 버튼 포인터외에 인자를 하나 더 넘기고 있습니다.&lt;br&gt;&lt;br&gt;이 인자는 버튼을 구분하기 위한 &#039;id&#039;입니다.&lt;br&gt;&lt;br&gt;이 id로 버튼의 고유한 값을 지정하면 유용한 경우가 많습니다.&lt;br&gt;&lt;br&gt;예를 들어, 이경우에는 enum을 이용하여 RGB, CMYK, YUV라는 상수를 정의하였고, 각각을 0, 1, 2로 대응시켰습니다.&lt;br&gt;&lt;br&gt;이 값은 color_combo의 RGB, CMYK, YUV의 인덱스에 대응하기 때문에, id로 이 값들을 넘겨줌으로써 간단하게 10번째 줄과 같은 시그널/슬롯의 연결이 가능합니다.&lt;br&gt;&lt;br&gt;또한, 반대로 color_combo의 인덱스가 바뀔때마다 라디오 버튼의 선택이 바뀌도록&lt;span&gt;&lt;span&gt; setColorChecked라는 슬롯을 이용합니다.&lt;br&gt;&lt;br&gt;이경우도 역시 id와 인덱스를 대응시켜뒀기 때문에, QButtonGroup::button()에 인자로 인덱스를 넘겨주어서 거기에 해당하는 id의 버튼 포인터를 가져오고, 그 버튼이 체크되도록 합니다.&lt;br&gt;&lt;br&gt;한번 컴파일된 파일을 실행해보면, 라디오 버튼의 선택이 바뀔때마다 콤보박스의 값이 바뀌고, 반대로 콤보박스의 값을 바꿀때마다, 라디오 버튼의 선택이 바뀔 것입니다.&lt;br&gt;&lt;br&gt;이상으로 2회에걸쳐 디자이너의 사용 방법에 대해 알아보았습니다.&lt;br&gt;&lt;br&gt;&lt;/span&gt;일단 디자이너를 쓰는데 있어서 필요한 내용은 설명했다고 생각합니다. 액션이나 리소스에 대해서는 설명하지 않았는데, 차후에 메인윈도우에 대한 설명을 하게 되면 따로 설명하지 않더라도 어떻게 이용하는지 알 수 있게 될 것이라고 생각합니다.&lt;br&gt;&lt;br&gt;다음 시간에는 각종 위젯에 대해 소개하도록 하겠습니다.&lt;br&gt;&lt;/span&gt;</description>
			<category>Qt</category>
			<category>Qt</category>
			<category>디자이너</category>
			<author>(xylosper)</author>
			<guid>http://xylosper.net/116</guid>
			<comments>http://xylosper.net/116#entry116comment</comments>
			<pubDate>Mon, 07 Apr 2008 05:09:00 +0900</pubDate>
		</item>
		<item>
			<title>Qt에 대하여 - 8. Qt Designer - 폼 디자인</title>
			<link>http://xylosper.net/114</link>
			<description>복잡한 레이아웃, 일일이 손으로 짤려면 귀찮고 나중에 좀 수정하기도 어렵죠.&lt;br /&gt;&lt;br /&gt;이럴때 Qt Designer가 유용하게 쓰일 것입니다.&lt;br /&gt;&lt;br /&gt;Qt Designer는 Qt로 프로그램을 만들떄 GUI적인 부분을 쉽게 디자인 할 수 있도록 도와주는 프로그램입니다.&lt;br /&gt;&lt;br /&gt;소스로부터 컴파일 한경우는 자동으로 컴파일되어서 만들어지지만, 리눅스에서 패키지를 다운 받아서 Qt를 설치하신 분은 아마 designer는 별도로 설치하셔야 할겁니다(이부분은 배포판마다 다르므로 사용하시는 배포판의 패키지 저장소에서 검색해보세요).&lt;br /&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;img src=&quot;http://xylosper.net/attach/1/1318967654.png&quot; alt=&quot;Qt Designer&quot; height=&quot;430&quot; width=&quot;566&quot; /&gt;&lt;p class=&quot;cap1&quot;&gt;Qt Designer의 모습&lt;/p&gt;&lt;/div&gt;Qt Designer(앞으로 그냥 디자이너 라고 하겠습니다)를 실행하면, 뭔가 묻는 다이얼로그가 나옵니다만, 일단은 무시해보시고 창을 닫으면 위와같은 모습이 나타날 것입니다.&lt;br /&gt;&lt;br /&gt;혹시 위 스샷과 달리 여러개의 창이 따로따로 뜬다면 Multiple Top-Level Windows 모드이기 때문입니다. &lt;br /&gt;&lt;br /&gt;Edit-&amp;gt;Preferences 에서 User Interface Mode설정에 따라 인터페이스를 변경할 수 있습니다.&lt;br /&gt;&lt;br /&gt;개인적으로 Docked Window모드를 선호하기 때문에 앞으로도 이 화면으로 설명하겠습니다(아마 창이 따로 노는거 말곤 다른 점 없을 것같습니다).&lt;br /&gt;&lt;br /&gt;각 번호가 적혀있는 부분에 대해서 설명해보면..&lt;br /&gt;&lt;br /&gt;1: Widget Box입니다. 각종 위젯들이 등록되어있어서 이걸 끌어다가 놓는 것만으로 위젯을 생성할 수 있습니다.&lt;br /&gt;2. Object Inspector입니다. 객체들간의 포함관계가 트리형태로 제공됩니다. 객체의 갯수가 많아져서 찾기 힘들다거나, 객체가 겹쳐있어서 선택하기 힘든 경우에 유용합니다.&lt;br /&gt;3. Property Editor입니다. 선택된 객체의 프로퍼티를 설정할 수 있습니다.&lt;br /&gt;4. Signal/Slot Editor입니다. 연결된 시그널과 슬롯 페어가 표시되며, 여기서 시그널/슬롯 페어를 추가하는 것도 가능합니다.&lt;br /&gt;5. Resource Editor입니다. 간편하게 리소스 파일을 열고 편집할 수 있습니다.&lt;br /&gt;6. Action Editor입니다. 액션 클래스의 객체들을 편집할 수 있습니다.&lt;br /&gt;&lt;br /&gt;여기서 5, 6은 아직 설명하지 않은 리소스나 액션이 들어가기 떄문에 이번에는 이용하지 않습니다.&lt;br /&gt;&lt;br /&gt;뭐 암만 말로 열심히 설명해도, 직접 해보는 것만 못합니다.&lt;br /&gt;&lt;br /&gt;이번엔 여러가지 위젯으로 간단해보이지만 손으로 짤려면 귀찮은 레이아웃의 폼을 만들어보면서, 디자이너를 이용하면 얼마나 간단하게 폼디자인을 할수 있는지 알아보겠습니다.&lt;br /&gt;&lt;br /&gt;디자이너를 열면(혹은 위 화면에서 File-&amp;gt;New Form) New Form 다이얼로그가 나타납니다.&lt;br /&gt;&lt;br /&gt;왼쪽에 Dialog with Buttons Bottom 등의 몇가지 선택사항이 나타납니다.&lt;br /&gt;&lt;br /&gt;이것들은 기본적인 위젯의 템플릿을 나타냅니다.&lt;br /&gt;&lt;br /&gt;다이얼로그를 만들 것이라면 위의 셋중에 하나를, 위젯을 만들 것이라면 맨 아래의 Widget을 선택합니다(Main Window역시 아직 설명하지 않은 부분이므로 패스합니다).&lt;br /&gt;&lt;br /&gt;위젯은 다른 위젯의 일부로 포함될 수 있지만, 다이얼로그는 무조건 별도의 창으로 나타나게 됩니다.&lt;br /&gt;&lt;br /&gt;이번 예제는 다이얼로그를 선택하되, 직접 버튼을 추가할 예정이므로 Dialog without Buttons를 선택합니다.&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;img src=&quot;http://xylosper.net/attach/1/1405745979.png&quot; alt=&quot;사용자 삽입 이미지&quot; height=&quot;413&quot; width=&quot;566&quot; /&gt;&lt;/div&gt;위와 같이 가운데 부분에 새로운 창이 나타납니다.&lt;br /&gt;&lt;br /&gt;이 창이 우리가 앞으로 디자인해갈 부분입니다.&lt;br /&gt;&lt;br /&gt;먼저 오른쪽의 Object Inspector에서 위젯이 선택되어있는 것을 확인하고, Property Editor에서 이 위젯의 이름을 지정해줍니다.&lt;br /&gt;&lt;br /&gt;이 이름은 객체에 따라서 역할이 다릅니다.&lt;br /&gt;&lt;br /&gt;지금 수정하려는 최상위 위젯의 이름은, 나중에 생성될 C++코드에서 이 위젯의 클래스이름이 됩니다.&lt;br /&gt;&lt;br /&gt;반면에 이제부터 여기에 추가해갈 위젯들의 이름은, C++코드상에서 그 위젯을 가리키는 변수명이 됩니다.&lt;br /&gt;&lt;br /&gt;적당히 objectName란에 TestWidget이라고 적어줍니다.&lt;br /&gt;&lt;br /&gt;이제 왼쪽의 Widget Box에서 필요한 위젯들을 가져와서 아래와 같이 배치합니다.&lt;br /&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;img src=&quot;http://xylosper.net/attach/1/1090430776.png&quot; alt=&quot;위젯을 배치한 모습&quot; height=&quot;334&quot; width=&quot;530&quot; /&gt;&lt;p class=&quot;cap1&quot;&gt;위젯을 배치한 모습&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;위젯을 추가할때는 Widget Box에서 원하는 위젯을 선택하고 마우스로 위의 폼으로 끌고와서 적당한 위치에 놓습니다.&lt;br /&gt;&lt;br /&gt;이름이 적혀있는 위젯들은 이름을 보면 어떤 것인지 알수 있으므로 생략하고, 이름이 적혀있지 않은 위젯들만 무엇인지 적어보면, 첫째줄 두번째는 Line Edit, 두번쨰 줄의 가운데는 Horizontal Slider, 그 오른쪽은 Spin Box, 셋째줄의 스프링처럼 생긴것은 Horizontal Spacer, Group Box안의 가장 오른쪽 위젯은 Combo Box, 그리고 맨 아래의 OK/Cancel버튼은 Push Button이 아니라 Button Box 라는 녀석입니다.&lt;br /&gt;&lt;br /&gt;배치할때는 정확하게 위치를 정해서 할 필요없이 대강 위젯들간의 위치관계만 생각해서 놓으면 됩니다.&lt;br /&gt;&lt;br /&gt;추가가 끝났으면, 이번엔 아래 그림처럼 각 위젯의 텍스트를 수정합니다.&lt;br /&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;img src=&quot;http://xylosper.net/attach/1/1218128474.png&quot; alt=&quot;수정된 다이얼로그&quot; height=&quot;334&quot; width=&quot;530&quot; /&gt;&lt;p class=&quot;cap1&quot;&gt;수정된 다이얼로그&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;텍스트도 프로퍼티이므로 Property Editor에서 text 항목을 찾아서 수정하면됩니다만, text 프로퍼티를 가지고 있는 위젯들은 대게 더블 클릭하면 바로 text를 수정할 수 있게 되어있습니다.&lt;br /&gt;&lt;br /&gt;또 Combo Box에는 RGB, CMYK, YUV 세개의 항목이 들어가있습니다. 역시 더블클릭으로 쉽게 추가하고 수정할 수 있습니다.&lt;br /&gt;&lt;br /&gt;이외에도 각 위젯들의 각종 프로퍼티들은 거의다 Property Editor에서 수정가능합니다.&lt;br /&gt;&lt;br /&gt;예를 들어 위 그림을 보면 그룹박스에 체크표시가 있는 것을 알수 있는데요, 그룹박스의 checkable 항목을 true로 설정하면 그룹박스도 체크할수있도록 됩니다.&lt;br /&gt;&lt;br /&gt;다음으로 실제 소스코드에서 참조할 위젯들은 적당한 변수명을 정해줍니다.&lt;br /&gt;&lt;br /&gt;이경우는 디자인을 위한 예제이므로 대부분 실제 코드에서 참조할일이 없기 때문에 거의 다 그냥 두어도 됩니다만, RGB, CMYK, YUV 라디오버튼의 objectName을 각각 rgb_radio, cmyk_radio, yuv_radio라고 하고, 콤보박스는 color_combo라고 합니다((위에서 설명했듯 이 이름은 클래스 이름이 아니라 변수명입니다).&lt;br /&gt;&lt;br /&gt;이제 레이아웃을 짜봅니다.&lt;br /&gt;&lt;br /&gt;우선 색반전하기 체크박스와 그옆의 미리보기 버튼, 그리고 스프링(-_-;)을 쉬프트키를 누른 상태로 차례대로 선택하여 동시에 세개가 선택된 상태가 되게 합니다.&lt;br /&gt;&lt;br /&gt;그 후, 마우스 오른쪽 버튼을 클릭하고 Lay out -&amp;gt; Lay out Horizontal을 선택하면 이 셋이 하나의 레이아웃으로 묶이게 됩니다.&lt;br /&gt;&lt;br /&gt;참고로 선택후 툴바의 Lay out Horizontal 버튼을 이용해도 됩니다.&lt;br /&gt;&lt;br /&gt;이런식으로 위젯들을 선택해가면서 레이아웃을 눌러주면 됩니다.&lt;br /&gt;&lt;br /&gt;다음으로 그룹박스의 레이아웃을 만듭니다.&lt;br /&gt;&lt;br /&gt;당연히 Horizontal 레이아웃을 쓸것인데, 이경우는 그룹박스만 선택한 채로 Lay out Horizontal을 선택하면, 자동으로 그룹박스 내부의 위젯들이 Horizontal 레이아웃으로 배열됩니다.&lt;br /&gt;&lt;br /&gt;이렇게 한 위젯안에 다른 위젯이 들어있는 경우는, 그 위젯들을 포함하고 있는 위젯을 선택한 상태에서 레이아웃을 선택해줍니다.&lt;br /&gt;&lt;br /&gt;이번엔 슬라이더와 스핀박스를 선택하고 Horizontal 레이아웃을 짭니다.&lt;br /&gt;&lt;br /&gt;그리고 다음과 같이 적당히 위젯을 예쁘게(-_-;) 배치합니다.&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;img src=&quot;http://xylosper.net/attach/1/1030273226.png&quot; alt=&quot;재배치된 모습&quot; height=&quot;334&quot; width=&quot;530&quot; /&gt;&lt;p class=&quot;cap1&quot;&gt;재배치된 모습&lt;/p&gt;&lt;/div&gt;완벽할 필욘 없지만 가급적이면 줄이 맞게 배치하는게 좋습니다. 이번엔 Grid Lay out이란 것을 이용합니다.&lt;br /&gt;&lt;br /&gt;지난시간에 설명하지 않은 레이아웃인데요, QGridLayout이라는 클래스로 구현되며, 표와 같은 모습은 레이아웃을 짜줍니다.&lt;br /&gt;&lt;br /&gt;셀병합도 가능합니다.&lt;br /&gt;&lt;br /&gt;위의 그림처럼 위젯들을 선택하고, Lay out in a Grid 를 선택하면, 자동으로 가장 적합한 모양의 그리드가 생성됩니다.&lt;br /&gt;&lt;br /&gt;예를 들어 맨밑의 색반전하기 부분의 레이아웃은 자동으로 두칸을 병합하여 한줄을 다 차지하도록 됩니다.&lt;br /&gt;&lt;br /&gt;마지막으로 남은 부분을 전부 세로로 나열하기 위해서 TestDialog를 선택하고 Lay out Vertical을 선택한후 적당한 크기로 만들기 위해 Adjust Size를 선택하면 다음과 같은 모습이 될것입니다.&lt;br /&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;img src=&quot;http://xylosper.net/attach/1/1372454712.png&quot; alt=&quot;최종 모습&quot; height=&quot;253&quot; width=&quot;283&quot; /&gt;&lt;p class=&quot;cap1&quot;&gt;최종 모습&lt;/p&gt;&lt;/div&gt;이제 폼을 짜는건 끝났습니다. 하지만 디자이너의 기능은 이게 다가 아닙니다.&lt;br /&gt;&lt;br /&gt;디자이너상에서 기본적인 시그널/슬롯도 연결해주는게 가능합니다.&lt;br /&gt;&lt;br /&gt;예를 들어, 슬라이더를 움직이면 자동으로 스핀박스의 값도 바뀌고, 반대로 스핀박스의 값을 변경하면 자동으로 슬라이더가 움직이게 할려고 합니다.&lt;br /&gt;&lt;br /&gt;스핀박스와 슬라이더는 값이 변경되면 valueChanged(int)라는 시그널을 뱉고, 동시에 setValue(int)라는 값을 설정해주는 슬롯도 있습니다.&lt;br /&gt;&lt;br /&gt;그러므로 스핀박스의 valueChanged를 슬라이더의 setValue에, 슬라이더의 valueChanged를 스핀박스의 setValue로 연결해주면 됩니다.&lt;br /&gt;&lt;br /&gt;먼저 슬라이더를 움직이면 스핀박스의 값이 바뀌도록 해봅시다.&lt;br /&gt;&lt;br /&gt;우선 Edit 메뉴나 툴바에서 Edit Signals/Slots를 선택하여 시그널/슬롯 편집모드로 바꿉니다.&lt;br /&gt;&lt;br /&gt;그리고 시그널을 뱉는 슬라이더를 클릭한 상태에서 마우스를 드래그하면 화살표가 나타납니다.&lt;br /&gt;&lt;br /&gt;드래그 한채로 이 화살표를 시그널을 연결할 위젯위로 가져가서 놓으면 아래와 같이 연결할 시그널과슬롯을 묻는 다이얼로그(Configure Connection)가 나타납니다.&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;img src=&quot;http://xylosper.net/attach/1/1033304966.png&quot; alt=&quot;시그널/슬롯 연결 대화창&quot; height=&quot;533&quot; width=&quot;566&quot; /&gt;&lt;p class=&quot;cap1&quot;&gt;시그널/슬롯 연결 대화창&lt;/p&gt;&lt;/div&gt;위와같이 연결할 시그널(valueChanged)와 슬롯(setValue)를 선택하고 OK를 누르면 이들이 연결됩니다.&lt;br /&gt;&lt;br /&gt;참고로 선택된 시그널과 인자가 맞지 않아서 연결할 수 없는 슬롯은 선택할 수 없게 되어있습니다.&lt;br /&gt;&lt;br /&gt;이런식으로 이번엔 스핀박스의 valueChanged시그널을 슬라이더의 setValue슬롯에 연결합니다.&lt;br /&gt;&lt;br /&gt;이번엔 색반전하기 체크박스가 체크되어있을 떄만 미리보기가 가능하게 할려고 합니다.&lt;br /&gt;&lt;br /&gt;체크박스는 체크상태가 변경될때마다 toggled(bool)이란 시그널을 뱉습니다. 이것을 미리보기 버튼의 setEnabled(bool)로 연결합니다.&lt;br /&gt;&lt;br /&gt;그런데, 이때 Configure Connection창에서 버튼의 슬롯 목록을 보면 setEnabled(bool)이 안보일 것입니다.&lt;br /&gt;&lt;br /&gt;setEnabled(bool)이란 슬롯은 QPushButton 자체의 슬롯이라기보다는, QWidget 클래스로부터 상속받은 슬롯이고, 처음 상태에서는 상속받은 시그널이나 슬롯은 나타나지 않게 되어있기 때문입니다.&lt;br /&gt;&lt;br /&gt;이럴 때는 Configure Connection창의 하단에 있는 Show all signals and slots를 선택하면 상속받은 시그널과 슬롯까지 전부 표시해주므로, 이걸 체크하고 선택하면 됩니다.&lt;br /&gt;&lt;br /&gt;마지막으로 버튼그룹의 accepted를 전체 다이얼로그(위젯을 배치하지 않은 빈공간으로 가져가면 됩니다. 화살표가 마치 접지마크 비슷한 상태입니다)의 accept로, rejected를 reject로 연결합니다.&lt;br /&gt;&lt;br /&gt;accepted는 OK버튼이 눌렸을때, rejected는 Cancel이 눌렸을 때 뱉어집니다. 그래서 OK가 눌리면 다이얼로그가 &#039;받아들여졌다(예를 들어, 설정 창이라면 설정을 적용한다든가)&#039;라는 의미로 accept로 연결하고, Cancel이 눌리면 취소되었단 의미로 reject로 연결합니다.&lt;br /&gt;&lt;br /&gt;이 두 슬롯은 모두 다이얼로그를 안보이게 하는 역할을 하고, 모달 다이얼로그의 반환값을 설정합니다.&lt;br /&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;img src=&quot;http://xylosper.net/attach/1/1211059185.png&quot; alt=&quot;연결된 시그널과 슬롯들&quot; height=&quot;253&quot; width=&quot;283&quot; /&gt;&lt;p class=&quot;cap1&quot;&gt;연결된 시그널과 슬롯들&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;이제 슬롯이 모두 연결되었는데요, 프로그램을 짜기 전에 한번 제대로 작동하는지 확인하고 싶습니다.&lt;br /&gt;&lt;br /&gt;이럴땐, Form메뉴의 Preview(단축키:Ctrl+R)를 선택하면 미리보기가 나타납니다.&lt;br /&gt;&lt;br /&gt;이상태에서 연결된 슬롯들은 모두 작동합니다.&lt;br /&gt;&lt;br /&gt;예를 들어 슬라이더를 움직이면 스핀박스의 값이 바뀔 것이고, 체크박스를 체크했다가 해재할때마다 버튼은 enbaled/disabled 상태가 반복됩니다.&lt;br /&gt;&lt;br /&gt;마지막으로 OK나 Cancel을 누르면 창을 닫게 됩니다.&lt;br /&gt;&lt;br /&gt;이제 폼디자인이 끝났습니다.&lt;br /&gt;&lt;br /&gt;원래는 이번회에 실제로 코드상에서 디자인한 폼을 어떻게 가져다 쓰는지까지 할려고 했습니다만, 그림이 많아서 내용이 길어진 관계로(언제나 길어지는 느낌입니다만-_-;) 실제로 프로그램을 만드는 것은 다음 시간에 소개하도록 하겠습니다.&lt;br /&gt;</description>
			<category>Qt</category>
			<category>Designer</category>
			<category>Qt</category>
			<category>디자이너</category>
			<author>(xylosper)</author>
			<guid>http://xylosper.net/114</guid>
			<comments>http://xylosper.net/114#entry114comment</comments>
			<pubDate>Sun, 06 Apr 2008 19:08:05 +0900</pubDate>
		</item>
		<item>
			<title>CMP 0.1.0 공개</title>
			<link>http://xylosper.net/115</link>
			<description>CMP는 (좀 무식한 방법으로 구현했지만) 통합/다중자막을 지원하는 리눅스용 동영상 플레이어입니다.&lt;br /&gt;&lt;br /&gt;Custom Media Player 라는 이름을 붙여서 혼자서 쓰던 플레이어인데, 이번기회에 좀 손봐서 공개하기로 하였습니다.&lt;br /&gt;&lt;br /&gt;다만 제가 직접 파싱하기 때문에, 현재는 제가 아는 포맷인 sami와 subrip밖에 지원하지 않습니다-_-;&lt;br /&gt;&lt;br /&gt;다른 포맷을 알려주시면 추가하도록 하겠습니다.&lt;br /&gt;&lt;br /&gt;구현은 Qt로 하였고, MPlayer자체도 크로스 플랫폼이므로 소스 자체는 크로스플랫폼입니다만, 리눅스에서밖에 써보지 않았기 때문에 다른 플랫폼에서는 어떻게 돌아갈지 모르겠습니다.&lt;br /&gt;&lt;br /&gt;손봤다고 해도 말그대로 &#039;좀&#039;이기 때문에 다른 분들이 쓰시기에는 불편한점이나 부족한점도 많을 것 같고, 테스트도 혼자 써본게 다이므로 버그도 많을 듯 합니다.&lt;br /&gt;&lt;br /&gt;이러한 점들은 저에게 알려주시면 개선해나가도록 하겠습니다.&lt;br /&gt;&lt;br /&gt;라이센스는 GPLv2를 따르며, Qt4.3이상과 MPlayer(rc2에서만 테스트해봤습니다)가 필요합니다.&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://xylosper.net/117&quot; target=&quot;_blank&quot;&gt;0.1.1이 공개되었습니다!&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;이하 개발후기랄까 잡설입니다-_-;&lt;br /&gt;&lt;br /&gt;제가 리눅스를 이용하면서 가장 아쉬웠던 것이 통합자막을 제대로 보여주는 플레이어가 없다는 점이었습니다.&lt;br /&gt;&lt;br /&gt;그나마 위안이었던게 Kipple님이 만든신 MPlayer용 통합자막 패치인데, 소스를 보니 두 클래스가 싱크가 일치하는 경우에만 함께 표시하도록 되어있었습니다.&lt;br /&gt;&lt;br /&gt;실제로 통합자막은 약간 어긋나는 경우도 많고, 게다가 이쪽 언어는 두마디로 나오는게 다른 언어로는 한마디로 나오거나 하는 경우도 있기 때문에, 제 욕구를 완벽히 충족시키진 못했습니다.&lt;br /&gt;&lt;br /&gt;한번은 저도 직접 MPlayer의 자막 파싱 부분을 수정해볼려고 들여다 보았지만, 역시나 C는 너무 어렵더군요.&lt;br /&gt;&lt;br /&gt;그러던 중, 2007년말, Qt4.4tp1이 발표되면서 Phonon을 이용하여 간단하게 동영상 플레이어를 만들 수 있게 되어, &#039;자막을 제대로 보여주는 플레이어 만들자&#039;는 생각에 처음엔 Phonon을 이용하여 동영상 플레이어를 만들기 시작하였습니다.&lt;br /&gt;&lt;br /&gt;이래저래 만들고나니, 대강 혼자선 쓸만하다고 생각될 만큼은 만들어졌는데, Qt4.4tp1은 아직 개발 도중인지라 부족한 점이 많았습니다.&lt;br /&gt;&lt;br /&gt;그러다가 MPlayer의 slave모드를 이용하면 Phonon못지 않게 쉽게 동영상 플레이어를 만들 수 있단 것을 알았고, 백엔드를 Phonon에서 MPlayer로 옮겼습니다.&lt;br /&gt;&lt;br /&gt;이런 과정때문에 Phonon만큼 구조적이지 못하지만 클래스 설계는 (Phonon만큼 방대하진 않지만) Phonon과 비슷한 것같습니다.&lt;br /&gt;&lt;br /&gt;또 MPlayer와 연동하는 방법은 SMPlayer를 대부분 &lt;span style=&quot;text-decoration: line-through;&quot;&gt;베꼈&lt;/span&gt;참조했습니다.&lt;br /&gt;&lt;br /&gt;결국 제가 짠 부분과 Phonon을 흉내낸 부분, SMPlayer를 &lt;span style=&quot;text-decoration: line-through;&quot;&gt;베낀&lt;/span&gt;참조한 부분이 뒤섞여 뒤죽박죽인 소스가 되었지만, 혼자 쓰는 거니까 걍 두고있었습니다.&lt;br /&gt;&lt;br /&gt;이번에 공개하기전에 소스를 좀 정리하긴 했지만 그래도 아직 뭔가 꺼림직한 부분이 많습니다-_-;&lt;br /&gt;&lt;br /&gt;이름은 뭐 말그대로 나를 위한 커스텀 플레이어란 뜻입니다.&lt;br /&gt;&lt;br /&gt;참고로 Phonon으로 만들던 초기 이름은 IWSUS(I Want to See Unified Subtitles) 였습니다-_-;&lt;br /&gt;&lt;br /&gt;차후 Qt4.4가 정식 릴리즈되고 Phonon이 MPlayer만큼 쓸만해지면 Phonon으로 옮길지도 모르고, 또 계속 만들어 나가면 이름도 또 바뀔지도 모르겠습니다. 아니 그전에 계속 개발 할지도 모르겠네요.-_-;&lt;br /&gt;&lt;br /&gt;통합자막을 구현하는데 있어서 정말 단순한 방법을 썼습니다.&lt;br /&gt;&lt;br /&gt;일단 자막을 다 파싱한 다음에, 하나로 합쳐진 임시 자막파일을 만들고, 그자막 파일을 다시 읽어들이는 방법이지요.&lt;br /&gt;&lt;br /&gt;중간에 어차피 파싱을 다시하는 거면 굳이 플레이어를 만들 필요 없이 그냥 통합자막을 변환해주는 프로그램을 만들면 되지 않나, 라는 생각에 자막 변환기로 노선을 변경한 적도 있었습니다.&lt;br /&gt;&lt;br /&gt;하지만 그냥 플레이어가 만들어 보고 싶어서 다시 돌아왔습니다.&lt;br /&gt;&lt;br /&gt;처음엔 느리면 어떻게하나 걱정했는데, 다행히도 요즘 컴퓨터가 빠른 덕에 별로 티안나더군요.&lt;br /&gt;&lt;br /&gt;OSD로 임시파일인 temp.smi를 읽어들인다고 나타나는 부분은, 일부러 OSD를 끄지 않고 냅뒀습니다.&lt;br /&gt;&lt;br /&gt;어차피 소스도 공개되있는데 숨겨봤자 나중에 소스보면 다 알테니 첨부터 다 까발리자는 생각입니다.&lt;br /&gt;&lt;br /&gt;사실 벌써 진작에 완성되었을 건데, 중간에 Phonon에서 MPlayer로 백엔드를 바꾸는 바람에 UI를 제외하고 코드는 사실상 처음부터 다시 쓰게되었고, 결국 황금같은 방학을 전부 써버렸습니다.&lt;br /&gt;&lt;br /&gt;아이콘은 KDE4의 아이콘 테마인 Oxygen을 가져다 썼습니다.&lt;br /&gt;&lt;br /&gt;스스로 그릴 실력은 못되니까요...&lt;br /&gt;&lt;br /&gt;그런데 어플레이케이션을 나타내는 아이콘이 마땅치가 않네요.&lt;br /&gt;&lt;br /&gt;어플리케이션의 아이콘은 유일해야할 아이콘이니 가져다 쓸수도 없고, 그릴 실력은 안되고...&lt;br /&gt;&lt;br /&gt;언젠가 허접한거라도 하나 그려넣을지도 모르겠습니다.&lt;br /&gt;&lt;br /&gt;써보시고 조금이라도 도움되셨다면 한마디씩 해주시면 감사하겠습니다.&lt;br /&gt;</description>
			<category>CMPlayer</category>
			<category>CMP</category>
			<category>동영상플레이어</category>
			<category>통합자막</category>
			<author>(xylosper)</author>
			<guid>http://xylosper.net/115</guid>
			<comments>http://xylosper.net/115#entry115comment</comments>
			<pubDate>Fri, 04 Apr 2008 17:49:47 +0900</pubDate>
		</item>
		<item>
			<title>Qt에 대하여 - 7. 레이아웃 시스템</title>
			<link>http://xylosper.net/113</link>
			<description>보통 다이얼로그같은 것을 하나 만들면 그 안에는 여러개의 위젯이 들어갑니다.&lt;br&gt;&lt;br&gt;무작정 생성만 해두면 다 한군데에 몰려있으니 위치관계를 고려해서 리사이즈도 해주고 위치도 옮겨주고 줄간격도 맞춰주고...어떻게 깔끔한 모양을 만들었습니다.&lt;br&gt;&lt;br&gt;그런데 창을 리사이즈했더니 위젯은 고대로 있고 창만 커집니다.&lt;br&gt;&lt;br&gt;기껏 좌표 계산해서 가운데로 가져다 놨더니 창을 키우니 더이상 가운데가 아니게 되고, 반대로 창을 작게 했더니 다 짤려 나오고...&lt;br&gt;&lt;br&gt;그럼 리사이즈 할때마다 다시 계산을 다 해서 배열해야 할까요?&lt;br&gt;&lt;br&gt;우리의 강력한 큐티는 이런 경우에도 쉽게 대처할 수 있는 레이아웃 시스템을 가지고 있습니다.&lt;br&gt;&lt;br&gt;일단 소스코드를 보시죠.&lt;br&gt;&lt;br&gt;mainwidget.h&lt;br&gt;[code]&lt;br&gt;#include &amp;lt;QWidget&amp;gt;&lt;br&gt;&lt;br&gt;class QLabel;&lt;br&gt;class QLineEdit;&lt;br&gt;&lt;br&gt;class MainWidget : public QWidget {&lt;br&gt;&amp;nbsp; &amp;nbsp; Q_OBJECT&lt;br&gt;public:&lt;br&gt;&amp;nbsp; &amp;nbsp; MainWidget();&lt;br&gt;private slots:&lt;br&gt;&amp;nbsp; &amp;nbsp; void setName(const QString &amp;amp;name);&lt;br&gt;private:&lt;br&gt;&amp;nbsp; &amp;nbsp; QLabel *printName;&lt;br&gt;&amp;nbsp; &amp;nbsp; QLineEdit *nameEdit;&lt;br&gt;};&lt;br&gt;[/code]mainwidget.cpp&lt;br&gt;[code]&lt;br&gt;#include &quot;mainwidget.h&quot;&lt;br&gt;#include &amp;lt;QLabel&amp;gt;&lt;br&gt;#include &amp;lt;QLineEdit&amp;gt;&lt;br&gt;#include &amp;lt;QHBoxLayout&amp;gt;&lt;br&gt;#include &amp;lt;QVBoxLayout&amp;gt;&lt;br&gt;#include &amp;lt;QSpacerItem&amp;gt;&lt;br&gt;&lt;br&gt;MainWidget::MainWidget()&lt;br&gt;: QWidget() {&lt;br&gt;&amp;nbsp; &amp;nbsp; printName = new QLabel();&lt;br&gt;&amp;nbsp; &amp;nbsp; nameEdit = new QLineEdit(this);&lt;br&gt;&amp;nbsp; &amp;nbsp; &lt;br&gt;&amp;nbsp; &amp;nbsp; QHBoxLayout *hbox1 = new QHBoxLayout;&lt;br&gt;&amp;nbsp; &amp;nbsp; hbox1-&amp;gt;addWidget(new QLabel(trUtf8(&quot;이름을 적어주세요:&quot;), this));&lt;br&gt;&amp;nbsp; &amp;nbsp; hbox1-&amp;gt;addWidget(nameEdit);&lt;br&gt;&amp;nbsp; &amp;nbsp; &lt;br&gt;&amp;nbsp; &amp;nbsp; QVBoxLayout *vbox = new QVBoxLayout;&lt;br&gt;&amp;nbsp; &amp;nbsp; vbox-&amp;gt;addLayout(hbox1);&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; QHBoxLayout *hbox2 = new QHBoxLayout;&lt;br&gt;&amp;nbsp; &amp;nbsp; hbox2-&amp;gt;addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum));&lt;br&gt;&amp;nbsp; &amp;nbsp; hbox2-&amp;gt;addWidget(printName);&lt;br&gt;&amp;nbsp; &amp;nbsp; hbox2-&amp;gt;addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum));&lt;br&gt;&amp;nbsp; &amp;nbsp; vbox-&amp;gt;addLayout(hbox2);&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; setLayout(vbox);&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; connect(nameEdit, SIGNAL(textChanged(const QString&amp;amp;)), this, SLOT(setName(const QString&amp;amp;)));&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; setName(QString());&lt;br&gt;}&lt;br&gt;&lt;br&gt;void MainWidget::setName(const QString &amp;amp;name) {&lt;br&gt;&amp;nbsp; &amp;nbsp; static const QString text = trUtf8(&quot;당신의 이름은 %1입니다.&quot;);&lt;br&gt;&amp;nbsp; &amp;nbsp; if (name.isEmpty())&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; printName-&amp;gt;setText(text.arg(trUtf8(&quot;무명씨&quot;)));&lt;br&gt;&amp;nbsp; &amp;nbsp; else&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; printName-&amp;gt;setText(text.arg(name));&lt;br&gt;&amp;nbsp; &amp;nbsp; adjustSize();&lt;br&gt;}&lt;br&gt;[/code]main.cpp&lt;br&gt;[code]&lt;br&gt;#include &amp;lt;QApplication&amp;gt;&lt;br&gt;#include &quot;mainwidget.h&quot;&lt;br&gt;&lt;br&gt;int main(int argc, char **argv) {&lt;br&gt;&amp;nbsp; &amp;nbsp; QApplication app(argc, argv);&lt;br&gt;&amp;nbsp; &amp;nbsp; MainWidget mw;&lt;br&gt;&amp;nbsp; &amp;nbsp; mw.show();&lt;br&gt;&amp;nbsp; &amp;nbsp; return app.exec();&lt;br&gt;}&lt;br&gt;[/code]&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;img src=&quot;http://xylosper.net/attach/1/1309350199.png&quot; alt=&quot;whats-your-name&quot; height=&quot;106&quot; width=&quot;257&quot; /&gt;&lt;p class=&quot;cap1&quot;&gt;실행화면&lt;/p&gt;&lt;/div&gt;이번 예제는 이름을 적으면 적은 이름을 표시해주는 whats-your-name이라는 프로그램입니다.&lt;br&gt;&lt;br&gt;mainwidget.h는 QLineEdit라는 새로운 위젯이 나온 것 외에는 딱히 설명할 것이 없어보입니다.&lt;br&gt;&lt;br&gt;간단히 복습해보면 Q_OBJECT는 메타 오브젝트 시스템을 위한 키워드이며, 시그널/슬롯을 이용할려면 선언해줘야하고, slots는 함수를 슬롯으로 이용할 수 있게 만들어주는 키워드입니다.&lt;br&gt;&lt;br&gt;QLineEdit는 위의 스샷에서 보듯이 무엇가를 입력받기 위한 위젯입니다(오래되서 확실친 않지만 아마 MFC에선 CEdit란 이름의 클래스가 같은 역할을 했던거 같습니다).&lt;br&gt;&lt;br&gt;이름에 Line이라고 적혀있는 대로, 입력 받을 수 있는건 한줄이며, QLabel등과 동일하게 text()/setText()로 현재 글을 가져오거나 지정할수도 있습니다.&lt;br&gt;&lt;br&gt;이 위젯은 글자가 입력/수정될때마다 textEdited(const QString&amp;amp;)시그널과 textChanged(const QString&amp;amp;)시그널을 내뱉습니다.&lt;br&gt;&lt;br&gt;둘의 차이는, textEdited는 사용자가 QLineEdit에 직접 입력한 경우에만 발생되지만, textChanged는 프로그램내에서 setText등을 이용해서 글자를 바꿨을때도 발생한다는 것입니다.&lt;br&gt;&lt;br&gt;우리는 여기서 textChanged시그널을 이용해서 입력된 이름을 표시할 것입니다.&lt;br&gt;&lt;br&gt;이제 mainwidget.cpp파일로 넘어갑니다.&lt;br&gt;&lt;br&gt;해더파일중에 QVBoxLayout, QHBoxLayout, QSpacerItem 등 처음 보는 클래스들이 보일텐데요, 이건 생성자안에서 생성할때 설명하겠습니다.&lt;br&gt;&lt;br&gt;printName은 &quot;당신의 이름은 ~입니다.&quot;라고 표시하기 위한 라벨이고, nameEdit가 이름을 입력받기위한 에디트입니다.&lt;br&gt;&lt;br&gt;13번째 줄을 보면 QHBoxLayout *hbox1를 할당하고 있습니다.&lt;br&gt;&lt;br&gt;이름에서 알수 있듯이 오늘의 주인공인 레이아웃 클래스중 하나입니다.&lt;br&gt;&lt;br&gt;QHBoxLayout의 H는 Horizontal의 H입니다.&lt;br&gt;&lt;br&gt;즉 수평으로 위젯들을 배치할때 유용하게 쓸수 있는 레이아웃 클래스입니다.&lt;br&gt;&lt;br&gt;다음줄을 보시면 addWidget이란 멤버함수를 호출하고 있습니다.&lt;br&gt;&lt;br&gt;이 함수는 레이아웃에 widget을 추가해줍니다.&lt;br&gt;&lt;br&gt;QHBoxLayout클래스에 추가된 widget은 추가된 순서대로 배열됩니다.&lt;br&gt;&lt;br&gt;addWidget의 안을 보면 new QLabel(trUtf8(&quot;이름을 적어주세요:&quot;), this) 이렇게 바로 동적할당한 포인터를 넘겨주고 있습니다.&lt;br&gt;&lt;br&gt;이건 두줄로 풀어쓰면&lt;br&gt;&lt;br&gt;QLabel *label = new QLabel(trUtf8(&quot;이름을 적어주세요:&quot;), this);&lt;br&gt;hbox1-&amp;gt;addWidget(label);&lt;br&gt;&lt;br&gt;과 동등한데, 여기서 label은 딱히 다음에 쓸일이 없기 때문에, 그냥 변수를 선언하지 않고 바로 포인터를 넘겨준 것입니다(전회에 설명한대로, 동적할당하더라도 this의 자식객체로 들어가기 때문에 나중에 자동으로 해제되므로 이런식으로 짜는게 가능합니다).&lt;br&gt;&lt;br&gt;그리고 또 다음줄에 addWidget(nameEdit)가 호출되고 있습니다.&lt;br&gt;&lt;br&gt;따라서 &quot;이름을 적어주세요:&quot;라벨이 제일 왼쪽에 들어가고, 그오른쪽에 nameEdit가 들어갑니다.&lt;br&gt;&lt;br&gt;만약 여기에 새로운 위젯을 추가한다면 이번엔 nameEdit의 오른쪽에 추가되겠죠?&lt;br&gt;&lt;br&gt;17번째 줄을 보면 이번엔 QVBoxLayout *vbox를 할당하고 있습니다.&lt;br&gt;&lt;br&gt;눈치빠른 분이라면 V가 vertical의 이니셜이란 것을 눈치채셨을 듯합니다.&lt;br&gt;&lt;br&gt;QHBoxLayout과 기본적인 사용법은 똑같으나, 위젯을 배치하는 방향이 옆으로(왼쪽에서 오른쪽으로)가 아니라 세로로(위에서 아래로)배치하는 레이아웃 클래스가 QVBoxLayout입니다.&lt;br&gt;&lt;br&gt;다음줄을 보면 addLayout이란 함수로 hbox1를 추가하고 있습니다.&lt;br&gt;&lt;br&gt;addLayout은 기본적인 동작방식은 addWidget과 거의 같지만, 그 대상이 위젯이 아니라 다른 레이아웃 클래스라는 점만 다릅니다.&lt;br&gt;&lt;br&gt;위젯들을 포함한 레이아웃이 통째로 삽입됩니다(결과는 스샷을 보는 쪽이 알기쉽습니다).&lt;br&gt;&lt;br&gt;20번째 줄을 보면 hbox2라는&amp;nbsp; 새로운 QHBoxLayout을 할당하고 있습니다.&lt;br&gt;&lt;br&gt;사실 더이상 hbox1은 쓸일이 없기때문에, 새로운 변수를 선언할 필요없이 hbox1에 새로 할당해도 되지만, 편의상 구분하기 위해 새로운 변수를 선언하였습니다.&lt;br&gt;&lt;br&gt;hbox2에서는 addItem이라는 또다른 함수가 호출되고 있습니다.&lt;br&gt;&lt;br&gt;&#039;item&#039;이라는 것은 레이아웃에 들어갈수 있는 아이템(마땅히 다른 말이 떠오르지 않네요)입니다.&lt;br&gt;&lt;br&gt;이렇게 레이아웃에 추가될수 있는 것은 위젯, 다른 레이아웃, 그리고 아이템 이렇게 세가지입니다.&lt;br&gt;&lt;br&gt;그리고 아이템의 경우는 클래스가 딱 두개밖에 없습니다.&lt;br&gt;&lt;br&gt;하나는 여기서 만들고 있는 QSpacerItem, 다른 하나는 QWidgetItem입니다.&lt;br&gt;&lt;br&gt;사실 addWidget함수는 내부적으로 QWidgetItem을 생성하여, addItem함수를 이용하도록 구현되어있습니다.&lt;br&gt;&lt;br&gt;하지만 addWidget이나 기타 위젯으로 바로 접근 가능한 함수들을 제공하고 있으므로, 사실성 QWidgetItem을 직접 보게될일은 거의없고, 결국 우리가 보게될 아이템은 QSpacerItem 한개뿐입니다.&lt;br&gt;&lt;br&gt;QSpacerItem은 이름그대로 공간을 때우기위한 아이템입니다.&lt;br&gt;&lt;br&gt;예를 들어, 다이얼로그에서는 자주 확인 버튼이 맨아래 오른쪽에 위치한걸 볼 수 있습니다.&lt;br&gt;&lt;br&gt;이러한 것은 QHBoxLayout에 QSpacerItem과 버튼을 차례로 추가해주는 방법으로 구현가능합니다.&lt;br&gt;&lt;br&gt;이렇게 하면 다이얼로그가 리사이즈되도 버튼은 그대로 두고 QSpacerItem이 알아서 늘어났다 줄어들었다 하면서 공간을 채워주는 것이죠.&lt;br&gt;&lt;br&gt;생성자는&lt;br&gt;&lt;br&gt;QSpacerItem(int w, int h, QSizePolicy::Policy hPolicy = QSizePolicy::Minimum,QSizePolicy::Policy vPolicy = QSizePolicy::Minimum)&lt;br&gt;&lt;br&gt;이런 모습인데요,&amp;nbsp; w와 h는 sizeHint를 제공하고, hPolicy와 vPolicy는 sizePolicy를 제공합니다.&lt;br&gt;저의 경우는 0, 0, Expanding, Minimum 이라고 적었는데요, 이렇게 하면 기본적인 크기는 너비 높이 0으로 하되, 리사이즈될때는 옆으로는 늘어나도 되지만, 세로로는 늘어나지 않는 QSpacerItem을 생성한 셈입니다.&lt;br&gt;&lt;br&gt;21-23라인을 보시면, 두개의 QSpacerItem을 생성하여 그 중간에 printName을 끼워넣는 방식으로 레이아웃이 만들어지고 있습니다.&lt;br&gt;&lt;br&gt;이렇게 하면, 양쪽에 늘어나는 QSpacer가 놓여있기 때문에, printName은 창크기가 바껴도 항상 한가운데에 위치하게됩니다(사실, 좀더 쉬운 구현방법은 그냥 아이템없이 printName이 직접 늘어나게 한다음, printName의 글자를 중앙정렬시키는 건데요, 일부러 아이템을 소개하기위해 이렇게 했습니다).&lt;br&gt;&lt;br&gt;이렇게 만들어진 hbox2를 다시 vbox에 추가합니다.&lt;br&gt;&lt;br&gt;최종적으로 만들어진 레이아웃의 모양을 시각화하면 다음과 같습니다.&lt;br&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;img src=&quot;http://xylosper.net/attach/1/1070186234.png&quot; alt=&quot;시각화된 레이아웃&quot; height=&quot;69&quot; width=&quot;275&quot; /&gt;&lt;p class=&quot;cap1&quot;&gt;시각화된 레이아웃&lt;/p&gt;&lt;/div&gt;위의 빨간 사각형이 hbox1, 아래의 빨간 사각형이 hbox2, 그리고 아래에 양쪽으로 그려져있는 파란 스프링이 두개의 QSapcerItem입니다.&lt;br&gt;&lt;br&gt;그리고 빨간 사각형 두개의 주변으로 vbox가 있는 셈이지요.&lt;br&gt;&lt;br&gt;이렇게 레이아웃이 완성되면 이 레이아웃을 위젯에 세팅해주기만 하면되고, setLayout함수가 그역할을 합니다(26번째 줄).&lt;br&gt;&lt;br&gt;이때 주의할 것은 이미 한번 레이아웃이 세팅된 위젯에는, 그 레이아웃을 delete하기전엔 새로운 레이아웃을 세팅할 수 없다는 것입니다.&lt;br&gt;&lt;br&gt;이정도면 레이아웃에 대해서 알아야 할건 거의다 설명했는데, 한가지 설명안한것이 소유권(부모-자식관계)입니다.&lt;br&gt;&lt;br&gt;여기서는 레이아웃 클래스들은 전부 부모를 지정하지 않고(널로 지정하고) 생성하였습니다.&lt;br&gt;&lt;br&gt;하지만 한 레이아웃이 다른 레이아웃으로 들어가거나, 어떤 위젯의 레이아웃으로 지정되면(setLayout), 그 레이아웃이나 위젯이 부모가 됩니다.&lt;br&gt;&lt;br&gt;최종적으로 이 예제에서는 vbox는 hbox1과 hbox2의 부모가, this(MainWidget)은 vbox의 부모가 되어 있는 것입니다.&lt;br&gt;&lt;br&gt;또, addItem으로 추가된 아이템의 소유권(아이템클래스같이 QObject를 상속받지 않는데, 자동으로 삭제되는 경우는 자식-부모라고 할 수 없어서 소유권이란 말도 자주 씁니다)은 레이아웃이 가지고 있으므로, 레이아웃이 해제될때 자동으로 추가된 아이템들도 해제됩니다.&lt;br&gt;&lt;br&gt;단 addWidget으로 추가된 위젯의 경우는 소유권(부모)이 바뀌지 않습니다.&lt;br&gt;&lt;br&gt;다만, setLayout으로 레이아웃을 지정하면, 레이아웃의 위젯들은 자동으로 setLayout을 호출한 위젯의 자식이 됩니다.&lt;br&gt;&lt;br&gt;따라서 이 예제에서는 printName등을 할당할때, this를 넘겨주지 않더라도 최종적으로는 this의 자식이 될것입니다.&lt;br&gt;&lt;br&gt;만약 레이아웃 클래스(QHBoxLayout등)을 생성할때 부모 위젯을 넘겨주면 어떻게 될까요?&lt;br&gt;&lt;br&gt;이경우는 자동적으로 부모위젯의 setLayout함수가 호출되어 레이아웃을 세팅합니다...만, 이경우도 이미 세팅된 레이아웃이 있는 경우 무시됩니다.&lt;br&gt;&lt;br&gt;이제 다시 예제로 돌아갑니다.&lt;br&gt;&lt;br&gt;connect는 처음 설명한데로 QLineEdit의 textChanged시그널과 MainWidget::setName을 연결하고 있고, 마지막으로 빈이름을 설정하고 있습니다.&lt;br&gt;&lt;br&gt;이제 setName함수를 보면, static 변수로 printName라벨의 텍스트로 설정할 바탕이될 문자열을 선언하고 있습니다.&lt;br&gt;&lt;br&gt;그런데 %1이란 이상한 글자가 들어가 있네요.&lt;br&gt;&lt;br&gt;if문을 보면 name이 비어있는 경우와 비어있지 않은 경울 놔눠서 하고 있는데, QString::arg()라는 함수가 호출되고 있습니다.&lt;br&gt;&lt;br&gt;이 %1이라는 건, 비유하자면 printf나 sprintf등에서 쓰는 %d 라던가 %s 같은 다른 변수로 치환될 부분을 나타냅니다.&lt;br&gt;&lt;br&gt;그리고 숫자의 순서대로 치환해갑니다.&lt;br&gt;&lt;br&gt;예를 들어 QString(&quot;%1 + %2 = %3&quot;).arg(1).arg(2).arg(3) 와 같이 하면 &quot;1 + 2 = 3&quot;이라는 문자열이 반환되는 거죠.&lt;br&gt;&lt;br&gt;예제에서는 &lt;span&gt;text.arg(trUtf8(&lt;span class=&quot;dp-string&quot;&gt;&quot;무명씨&quot;&lt;/span&gt;&lt;span&gt;)) 혹은 &lt;/span&gt;&lt;/span&gt;&lt;span&gt;text.arg(name)라고 하고 있으므로 name이 비어있으면 %1이 무명씨로, 그렇지 않으면 %1이 name으로 치환될 것입니다.&lt;br&gt;&lt;br&gt;또한 sprintf처럼 숫자를 치환할때 적당히 0이나 다른 문자를 체워넣거나 하는 것도 가능합니다.&lt;br&gt;&lt;br&gt;하지만 %치환자와 arg를 이용한 치환에서만 가능한 것이 있습니다.&lt;br&gt;&lt;br&gt;바로 번역할 때, 어순때문에 치환자의 순서가 바뀌더라도, 치환의 순서는 숫자로 지정되므로 그대로 유지된다는 것입니다.&lt;br&gt;&lt;br&gt;예를 들어 tr(&quot;I do %2 width %3&quot;)을 &quot;나는 %3을 가지고 %2를 한다&quot;와 같이 번역해도 치환에는 문제가 없는것이죠.&lt;br&gt;&lt;br&gt;마지막으로&amp;nbsp; adjustSize()라는 함수를 호출하고 있는데, 이것이 참 편리한 함수입니다.&lt;br&gt;&lt;br&gt;이 예제에서 글자가 길어지면 저절로 printName라벨의 크기가 늘어납니다. 그리고 printName은 hbox2에 들어있으므로 hbox2도자동으로 늘어나고, hbox2는 vbox에, vbox는 MainWidget에 들어가있으므로 최종적으로 MainWidget의 크기가 늘어나면서 레이아웃이 유지됩니다.&lt;br&gt;&lt;br&gt;그런데 일단 늘어난 다음에 다시 글자수를 적게하면 한번 늘어난 크기가 줄어들지 않습니다.&lt;br&gt;&lt;br&gt;다시 줄어들게 하고는 싶은데, 글자수에 따라서 얼마나 줄여야될지를 계산할려니 또 귀찮아집니다.&lt;br&gt;&lt;br&gt;이럴때 adjustSize()함수를 호출하면 sizeHint()에 기반하여 적절한 크기를 계산하여 리사이즈 해주므로 너무 크기도, 너무 작지도 않게 적당하게 자동으로 크기가 변경됩니다.&lt;br&gt;&lt;br&gt;이 레이아웃 시스템, 코드도 그리 어렵지 않습니다만, 예를 들어 학생정보를 입력받기위해서 수많은 라벨과 에디트등이 필요한 상황이라면 이것도 또 코드짜는게 만만치 않을 것입니다.&lt;br&gt;&lt;br&gt;하지만 우리의 사랑스러운 큐티(여담이지만 트롤테크 내부에서는 Qt를 cute처럼 발음한다고 하네요)는 이런 경우에 쉽게 GUI디자인을 가능케하는 Qt Designer라는 프로그램을 제공하고 있습니다(사실 이미 여러분은 디자이너의 화면을 보았습니다. 저위에 제가 &#039;시각화&#039;라는 이름으로 달아놓은 스샷이 바로 디자이너에서 디자인할때의 모습입니다).&lt;br&gt;&lt;br&gt;다음시간에는 이 Designer에 대해 알아보도록 하겠습니다.&lt;/span&gt;</description>
			<category>Qt</category>
			<category>layout</category>
			<category>Qt</category>
			<category>레이아웃</category>
			<author>(xylosper)</author>
			<guid>http://xylosper.net/113</guid>
			<comments>http://xylosper.net/113#entry113comment</comments>
			<pubDate>Fri, 28 Mar 2008 05:09:00 +0900</pubDate>
		</item>
		<item>
			<title>Qt에 대하여 - 6. Meta-Object System</title>
			<link>http://xylosper.net/112</link>
			<description>제목을 쓰면서 느낀건데 아무래도 귀찮아서 그냥 Meta-Object는 메타오브젝트라고 한글로 적어야겠습니다-_-;&lt;br&gt;&lt;br&gt;다시 &lt;a href=&quot;http://xylosper.net/111&quot; target=&quot;_blank&quot;&gt;전편&lt;/a&gt;의 소스를 살펴보시면, 두개의 해더파일에 모두 Q_OBJECT 라는 키워드가 들어가있는 것이 보일 것입니다.&lt;br&gt;&lt;br&gt;이 키워드야말로 큐티의 메타오브젝트시스템의 핵심이라고 할수 있습니다.&lt;br&gt;&lt;br&gt;메타 오브젝트 시스템의 기본은 QObject클래스와 Q_OBJECT 키워드, 그리고 moc(메타 오브젝트 컴파일러)라는 큐티전용 전처리기입니다.&lt;br&gt;&lt;br&gt;메타 오브젝트 시스템이란, 이름대로만 설명하자면 객체스스로 객체에 대한 정보를 담고 있는 것을 말합니다.&lt;br&gt;&lt;br&gt;일반적인 C++클래스는 그 클래스 자체에 대한 설명은 담고 있지 않습니다.&lt;br&gt;&lt;br&gt;예를 들어 A라는 클래스의 인스턴스 a를 생성했을때, 따로 클래스의 선언이나 정의를 한 소스를 보거나, 클래스를 설명한 문서를 보는 등의 일을 하지 않으면, 이 인스턴스 a로부터 a의 클래스 &#039;이름&#039;은 무엇인가, 또 다른 클래스 B와의 상속관계는 어떠한가와 같은 정보는 알수 없습니다.&lt;br&gt;&lt;br&gt;이에반해 큐티의 메타오브젝트 시스템이 적용된 클래스는, 인스턴스만 가지고도 그 인스턴스의 형에 대한 정보를 알 수 있습니다.&lt;br&gt;&lt;br&gt;사실 이것과 메타 오브젝트 시스템 전반에 관련되어서 어떤 연결점이 있는진 저도 잘 모르므로, 너무 구체적인 설명은 피하도록하고, 메타 오브젝트 시스템덕분에 어떤게 가능하고, 어떻게 이용하지는에 대해서 적도록 하겠습니다.&lt;br&gt;&lt;br&gt;일단 전편에서 설명한 시그널/슬롯 또한 이 메타 오브젝트 시스템덕분에 가능합니다.&lt;br&gt;&lt;br&gt;또, qobject_cast라고 하는 형변환 연산자가 제공됩니다.&lt;br&gt;&lt;br&gt;이 형변환 연산자는 QObject를 상속받은 클래스간에서 형변환을 해주는데 쓸수 있습니다.&lt;br&gt;&lt;br&gt;원래 C++에는 dynamic_cast라는 상속관계에 있는 클래스간에 부모클래스에서 자식클래스로, 혹은 자식클래에서 부모클래스로 형변환해주는 캐스팅연산자가 있습니다.&lt;br&gt;&lt;br&gt;하지만, 이 dynamic_cast는 RTTI에 의해서 캐스팅되기 때문에 이식성이 없는 코드가 되기 쉽고, 무엇보다 성능면에서 심각하게 느립니다.&lt;br&gt;&lt;br&gt;그래서 보통 이건 100% 상속관계에 있다고 확신할땐 그냥 static_cast를 씁니다.&lt;br&gt;&lt;br&gt;하지만, 형변환을 해야겠는데, 상속관계에 있을수도 있고 아닐수도 있다거나, 서로다른 동적 라이브러리간에서 형변환을 해야하는 경우에 유용한 것이 qobject_cast입니다.&lt;br&gt;&lt;br&gt;이 연산자(내장된게 아니므로 정확히는 연산자가 아니라 템플릿함수입니다만 앞으로 그냥 편의상 형변환 연산자와 똑같이 취급하겠습니다)는 QObject를 상속한 두 클래스간에 형변환을 해주고, 만약 형변환이 불가능한 경우는 널 포인터를 반환해줍니다.&lt;br&gt;&lt;br&gt;예를 들어 QLabel은 QWidget을 상속했으므로&lt;br&gt;&lt;br&gt;QLabel *label = new QLabel;&lt;br&gt;QWidget *widget = qobject_cast&amp;lt;QWidget*&amp;gt;(label);&lt;br&gt;&lt;br&gt;과 같은 형변환에서는 제대로 형변환이 이루어질테고, QLabel과 QPushButton은 상속관게에 없으므로&lt;br&gt;&lt;br&gt;QPushButton *button = qobject_cast&amp;lt;QPushButton*&amp;gt;(label);&lt;br&gt;&lt;br&gt;과 같은 변환에서는 button은 널 포인터가 됩니다.&lt;br&gt;&lt;br&gt;그럼 qobject_cast&amp;lt;QPushButton*&amp;gt;(widget)의 결과는 어떨까요?&lt;br&gt;&lt;br&gt;얼핏 QPushButton은 QWidget을 상속받으니까 widget을 QPushButton*으로 형변환 가능할 듯하지만, 이게 기똥차게도 널을 반환해줍니다.&lt;br&gt;&lt;br&gt;실제로 widget은 QLabel의 인스턴스니까 여기서 만약 널이 반환되지 않으면 라벨을 토글하는 등의 어처구니 없는 일이 발생하겠죠?&lt;br&gt;&lt;br&gt;특히 유용하게 쓰이는 경우는 예를 들어 어떤 함수의 인자로 QWidget*을 받아오는데, QPushButton*인 경우만 특별한 처리를 하고 싶거나 하는 경우에, 간단하게 qobject_cast로 캐스팅해보고 널인지 아닌지 검사해서 QPushButton의 포인터만 골라내는 것이 가능합니다.&lt;br&gt;&lt;br&gt;또한, tr/trUtf8을 이용한 번역기능도 역시 메타 오브젝트 시스템의 덕분입니다(사실 이부분은 저도 실제로 번역해본 적이 없기 때문에 자세한 설명은 못하겠습니다. 그냥 습관적으로 일단 외부로 보여지는 문자열은 전부 tr로 싸고 있습니다.)&lt;br&gt;&lt;br&gt;Q_PROPERTY키워드를 이용한 프로퍼티도 지원됩니다만, 프로퍼티는 제가 써본적이 없네요-_-;&lt;br&gt;&lt;br&gt;위에서 설명한 기능들을 이용하기위해서는 메타오브젝트 시스템이 필요하고, 여기서 Q_OBJECT의 역할이 나옵니다.&lt;br&gt;&lt;br&gt;Q_OBJECT는 매크로인데, 메타오브젝트를 위한 각종 함수들을 자동으로 선언해줍니다.&lt;br&gt;&lt;br&gt;그리고 moc는 컴파일하기전에 Q_OBJECT가 포함된 클래스 선언문을 찾아서 적절한 moc파일을 생성해줍니다.&lt;br&gt;&lt;br&gt;moc는 qmake로 생성한 Makefile에서 알아서 돌려주므로, 우리가 신경써야 할것은 첫째, QObject를 상속받을 것(당연히 직접 상속받지 않고 QObject를 상속받은 클래스를 상속받아도 상관없습니다), 그리고 클래스 선언내에 private영역에 Q_OBJECT라는 키워드를 적어둘 것, 이 두가지입니다.&lt;br&gt;&lt;br&gt;connect함수의 원형을 보면 알겠지만, const QObject *로 넘기도록 되있으므로 일단 QObject를 상속받지 않으면 connect함수 자체를 이용 할 수 없습니다.&lt;br&gt;&lt;br&gt;하지만 저도 종종 Q_OBJECT선언하는 것을 까먹곤 합니다.&lt;br&gt;&lt;br&gt;이런 경우 컴파일은 잘되도 실행했을때 해당하는 슬롯이나 시그널이 없다는 문구가 콘솔창에 나타나므로, 분명히 제대로 했는데도 그럴땐 혹시 Q_OBJECT를 빼먹은 것 아닌가 확인하시구요, Q_OBJECT를 추가했을땐 꼭 그파일도 moc가 돌아가도록 qmake를 한번 더 실행해줘야합니다.&lt;br&gt;&lt;br&gt;또 한가지 주의할점이 있는데요, Q_OBJECT는 반드시 해더파일에 있어야 합니다.&lt;br&gt;&lt;br&gt;확실친 않지만 아마도 moc가 해더파일만 도는건지, cpp파일에 Q_OBJECT를 포함한 채로 클래스를 선언하면 링크단계에서 어떤 vtable이 존재하지 않는다는 에러가 나옵니다.&lt;br&gt;&lt;br&gt;이상 메타오브젝트 시스템에 대한 설명이었습니다.&lt;br&gt;&lt;br&gt;마지막으로, 지난 예제 clicks의 MainWidget의 생성자에 대해서 좀 설명해볼려고 합니다.&lt;br&gt;&lt;br&gt;생성자부분만 다시 가지고 오면,&lt;br&gt;[code]&lt;br&gt;MainWidget::MainWidget(QWidget *parent)&lt;br&gt;: QWidget(parent) {&lt;br&gt;&amp;nbsp; &amp;nbsp; button = new DoubleButton(this);&lt;br&gt;&amp;nbsp; &amp;nbsp; label = new QLabel(trUtf8(&quot;클릭 안됨&quot;), this);&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; connect(button, SIGNAL(doubleClicked()), this, SLOT(setLabelDoubleClicked()));&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; label-&amp;gt;move(100, 0);&lt;br&gt;&amp;nbsp; &amp;nbsp; resize(200, 50);&lt;br&gt;}&lt;br&gt;[/code]&lt;br&gt;여기서 보통 C++을 쓰는 사람이라면 new연산자를 이용하는 부분이 잘 이해가 안될수 있습니다.&lt;br&gt;&lt;br&gt;딱히 new를 이용해서 동적할당할 필요성도 못느끼는데다가, 아무리 눈씻고 찾아봐도 여기서 할당한 메모리를 delete하는 부분이 없으니까요.&lt;br&gt;&lt;br&gt;물론 &#039;간단한 프로그램이고 한번 할당한담에 종료할때 알아서 운영체제가 해제할테니 별로 신경안써도 되&#039;라고 생각 할수도 있지만, 사실 프로그램이 종료될때 button과 label은 잘 delete된후에 종료됩니다.&lt;br&gt;&lt;br&gt;그 비밀은 바로 QObject가 가지고 있습니다(그래서 딱히 메타 오브젝트 시스템을 이용한게 아님에도 밀접한 연관이 있는 클래스이므로 이 글에 같이 적습니다)&lt;br&gt;&lt;br&gt;전에 위젯 클래스를 소개할때 생성자로 넘기는 &#039;부모 위젯&#039;에 대해 이야기한적이 있습니다.&lt;br&gt;&lt;br&gt;사실 그때 설명하지 않은 것이 있는데, 부모는 위젯에만 있는게 아닙니다.&lt;br&gt;&lt;br&gt;QObject를 상속받는 모든 클래스는 &#039;부모&#039;를 지정할 수 있습니다.&lt;br&gt;&lt;br&gt;QObject의 생성자를 보아도 QObject(QObject *parent = 0) 처럼 QWidget과 동일한 모습을 가지고 있습니다.&lt;br&gt;&lt;br&gt;이렇게 어떤 인스턴스가 다른 인스턴스의 &#039;자식&#039;이 되면, 부모 인스턴스가 소멸될때 자식으로 등록된 인스턴스를 알아서 지워줍니다.&lt;br&gt;&lt;br&gt;다시 생성자를 보면, label도, button도 모두 생성자의 마지막에 this(MainWidget 인스턴스의 포인터)를 넘기고 있는 것을 알 수 있습니다.&lt;br&gt;&lt;br&gt;MainWidget은 main함수의 지역변수로 선언되어있으므로, 프로그램이 종료될때 저절로 소멸될 것입니다.&lt;br&gt;&lt;br&gt;그리고 이때, MainWidget의 자식으로 등록되어있는 label과 button도 알아서 delete 시켜주는 것이죠.&lt;br&gt;&lt;br&gt;물론 동적 생성을 하지 않고 처음부터 그냥 인스턴스로 생성해도 상관없습니다.&lt;br&gt;&lt;br&gt;이경우는 delete하지 않아도 자동으로 소멸될것이고, 또한 MainWidget의 소멸자에서 미리 delete하도록 해도 문제없습니다.&lt;br&gt;&lt;br&gt;어떤 원리인지는 저도 잘 모르지만 알아서 delete가 필요하면 지우고 필요없으면 안하는 구조로 되어있으니까요.&lt;br&gt;&lt;br&gt;이덕분에 Qt로 프로그래밍할때는 자바의 가비지 컬렉션처럼 메모리 관리가 자동으로 되면서도 가비지 컬렉션처럼 느리지도 않다는 잇점이 있습니다.&lt;br&gt;&lt;br&gt;다만 주의할 점은 이것은 QObject를 상속받은 경우에만 해당하는 것입니다(일부 QObject를 상속받지 않고 구현된 큐티의 클래스들도 있는데, 이 클래스들에는 해당사항없습니다).&lt;br&gt;&lt;br&gt;그래도 아직 따질게 있으신 분이 계실지도 모르겠습니다.&lt;br&gt;&lt;br&gt;동적할당하는 메모리가 자동으로 관리된다고 해도, 이경우는 동적할당행위 그자체가 필요 없는데 굳이 동적할당을 하는 이유가 뭐냐? 고 물으실수 있는데요, 그 이유는 컴파일 의존성을 줄이기위해서입니다.&lt;br&gt;&lt;br&gt;&lt;p id=&quot;more112_0&quot; class=&quot;moreless_fold&quot;&gt;&lt;span style=&quot;cursor: pointer;&quot; onclick=&quot;toggleMoreLess(this, &#039;112_0&#039;,&#039;컴파일 의존성이 뭔데?&#039;,&#039;숨기기&#039;); return false;&quot;&gt;컴파일 의존성이 뭔데?&lt;/span&gt;&lt;/p&gt;&lt;div id=&quot;content112_0&quot; class=&quot;moreless_content&quot; style=&quot;display: none;&quot;&gt;컴파일 의존성이란  말그대로 컴파일시에 파일들간의 의존성을 나타냅니다.&lt;br&gt;&lt;br&gt;혹시 C++로 프로그램 만들면서, 파일 하나에서 한글자만 고쳤는데 갑자기 수십개의 파일이 다 다시 컴파일되는 경험을 겪으신적 없으신가요?&lt;br&gt;&lt;br&gt;이것은 그 파일들이 모두 의존관계에 있기 때문입니다.&lt;br&gt;&lt;br&gt;C++은 해더파일과 소스파일로 나뉩니다.&lt;br&gt;&lt;br&gt;그리고 주로 해더파일에는 선언문이, 소스파일에는 정의가 들어갑니다.&lt;br&gt;&lt;br&gt;다음은 clicks 예제의 MainWidget의 선언부입니다.&lt;br&gt;[code]&lt;br&gt;#include &amp;lt;QWidget&amp;gt;&lt;br&gt;&lt;br&gt;class DoubleButton; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; class QLabel;&lt;br&gt;&lt;br&gt;class MainWidget : public QWidget {&lt;br&gt;&amp;nbsp; &amp;nbsp; Q_OBJECT&lt;br&gt;public:&lt;br&gt;&amp;nbsp; &amp;nbsp; MainWidget(QWidget *parent = 0);&lt;br&gt;private slots:&lt;br&gt;&amp;nbsp; &amp;nbsp; void setLabelDoubleClicked();&lt;br&gt;private:&lt;br&gt;&amp;nbsp; &amp;nbsp; QLabel *label;&lt;br&gt;&amp;nbsp; &amp;nbsp; DoubleButton *button;&lt;br&gt;};&lt;br&gt;[code]&lt;br&gt;여기서 만약에 동적할당을 하지 않고 label과 button을 각각 QLabel *, DoubleButton*이 아닌 QLabel, DoubleButton으로 선언하면 무엇이 달라질까요?&lt;br&gt;&lt;br&gt;그러면 MainWidget은 QLabel과 DoubleButton을 멤버로 가지므로, 그 크기를 계산하기 위해서는 QLabel의 크기, DoubleButton의 크기를 알 필요가 있습니다.&lt;br&gt;&lt;br&gt;그러므로 이들의 정의가 필요해지고, &amp;lt;QLabel&amp;gt;과 &quot;doublebutton.h&quot;파일을 인클루드해야할 필요가 생깁니다.&lt;br&gt;&lt;br&gt;여기까진 좋습니다. 어차피 mainwidget.cpp에서 인클루드할꺼 해더에서 미리 인클루드 한셈이라고 치지요.&lt;br&gt;&lt;br&gt;그런데, 이 mainwidget.h를 또 다른 a.cpp라는 소스파일에서 인클루드 했다고 칩시다.&lt;br&gt;&lt;br&gt;그리고 DoubleButton에 뭔가 함수 하나를 추가합니다.&lt;br&gt;&lt;br&gt;그러면 DoubleButton의 정의가 바꼈으므로 당연히 이를 포함하고 있는 mainwidget.cpp파일은 다시 컴파일해야합니다.&lt;br&gt;&lt;br&gt;그런데, a.cpp는 어떨까요? button은 MainWidget의 private멤버이므로 a.cpp에서 button을 가져다 쓸일이 없음에도 불구하고, mainwidget.h에 doublebutton.h가 포함되어있고, 이 mainwidget.h를 포함시켰기 때문에, a.cpp도 다시 컴파일되어야 합니다.&lt;br&gt;&lt;br&gt;이것이 바로 컴파일 의존성때문에 생기는 문제입니다.&lt;br&gt;&lt;br&gt;그러면 포인터의 경우는 어떨까요?&lt;br&gt;&lt;br&gt;포인터는 자료형이 무엇이든 결국 그 크기 자체는 (대부분) 4바이트로 정해져있습니다..&lt;br&gt;&lt;br&gt;그러므로 사용할 포인터으 클래스를 전방선언만 해주면, 컴파일러는 이건 이 클래스 포인터로 쓰일꺼야 라고 알테고, 컴파일 중간에 크기 계산할때도 포인터니까 그 클래스의크기는 알필요 없이 4바이트만 더 할당하면 됩니다.&lt;br&gt;&lt;br&gt;결과적으로 doublebutton.h나 QLabel 해더파일은 mainwidget.h에서 포함시킬 필요가 없어지고, 실제로 이들을 가져다 쓰는 mainwidget.cpp에서 포함시키면됩니다.&lt;br&gt;&lt;br&gt;이렇게 되면 doublebutton.h를 수정하더라도 a.cpp와는 전혀 무관한 상태이기 때문에 a.cpp가 다시 컴파일되는 불상사를 막을 수 있습니다.&lt;br&gt;&lt;br&gt;간단한 예제니까 사실 아무래도 상관없지만, 좀 프로젝트가 커지면 컴파일시간이 꽤 길어집니다.&lt;br&gt;&lt;br&gt;이럴때 컴파일 의존성때문에 뭐 하나 고칠때마다 다 리빌드하는 셈이되면 참 짜증나겠죠.&lt;br&gt;&lt;br&gt;그래서 이런 컴파일 의존성을 줄이기 위해서라도 포인터로 멤버변수를 선언하고 해더파일은 되도록이면 cpp에서만 인클루드하도록 프로그램을 짜는 것입니다.&lt;br&gt;&lt;/div&gt;&lt;br&gt;포인터로 선언하고 해더파일을 인클루드하는 대신에 전방선언을 해서 컴파일 의존성을 줄일수 있는 것이지요.&lt;br&gt;&lt;br&gt;그래서 대부분의 QObject를 상속받는 클래스의 인스턴스는 동적할당으로 생성하게 됩니다.&lt;br&gt;&lt;br&gt;이제 생성자에서 느껴진 위화감은 해소되었을꺼 같은데, 마지막 두줄이 신경쓰입니다.&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; label-&amp;gt;move(100, 0);&lt;br&gt;&amp;nbsp; &amp;nbsp; resize(200, 50);&lt;br&gt;&lt;br&gt;이 두줄인데요, 이 두줄을 적은 이유는, 그냥 생성만 해놓으면 button과 label이 겹쳐서 보이지 않기 때문에 적당히 label을 오른쪽으로 움직여준것이고, 또 움직인 영역이 위젯의 크기보다 크면 짤리거나 안보이기 때문에 위젯자체도 적당한 크기로 리사이즈 해준 것입니다.&lt;br&gt;&lt;br&gt;그런데, 이게참 번거롭기 짝이없을 뿐만 아니라 모양새도 참 구리구리합니다.&lt;br&gt;&lt;br&gt;그럼 매번 모든 위젯의 위치를 계산하고 움직여준다음에 크기를 변경해줘야하는 수고가 필요한걸까요?&lt;br&gt;&lt;br&gt;절~대 아닙니다. 우리의 큐티는 이미 이 문제를 쉽게 해결할수 있는 레이아웃 시스템을 가지고 있습니다.&lt;br&gt;&lt;br&gt;다음회에는 레이아웃에 대해서 소개해보겠습니다.&lt;br&gt;</description>
			<category>Qt</category>
			<category>Meta-Object System</category>
			<category>QObject</category>
			<category>Qt</category>
			<category>메타 오브젝트 시스템</category>
			<author>(xylosper)</author>
			<guid>http://xylosper.net/112</guid>
			<comments>http://xylosper.net/112#entry112comment</comments>
			<pubDate>Thu, 27 Mar 2008 05:07:00 +0900</pubDate>
		</item>
		<item>
			<title>Qt에 대하여 - 5. 체험 signal/slot</title>
			<link>http://xylosper.net/111</link>
			<description>이번에는 직접 시그널과 슬롯을 구현해보고, 가능하다면 Qt의 Meta-Object 시스템에 대해서도 소개해보려고 합니다.&lt;br /&gt;&lt;br /&gt;버튼과 라벨을 하나씩 배치하고, 버튼이 더블 클릭되면 라벨의 텍스트가 바뀌는 clicks라는 예제입니다.&lt;br /&gt;&lt;br /&gt;QPushButton은 한번 클릭한 경우와 두번 클릭한 경우 구분없이 clicked()시그널이 나옵니다.&lt;br /&gt;&lt;br /&gt;여기선 더블클릭하면 doubleClicked()라는 시그널을 발생시키는 DoubleButton이란 버튼을 구현하고, 이 시그널을 받아서 처리하도록 슬롯을 만들것입니다.&lt;br /&gt;&lt;br /&gt;이번회는 클래스를 두개를 만들기 때문에 소스양이 좀 많습니다.(사실 이건 많은것도 아니죠-_-;)&lt;br /&gt;&lt;br /&gt;doublebutton.h&lt;br /&gt;[code]&lt;br /&gt;#include &amp;lt;QPushButton&amp;gt;&lt;br /&gt;&lt;br /&gt;class DoubleButton : public QPushButton {&lt;br /&gt;&amp;nbsp; &amp;nbsp; Q_OBJECT&lt;br /&gt;public:&lt;br /&gt;&amp;nbsp; &amp;nbsp; DoubleButton(QWidget *parent = 0);&lt;br /&gt;signals:&lt;br /&gt;&amp;nbsp; &amp;nbsp; void doubleClicked();&lt;br /&gt;protected:&lt;br /&gt;&amp;nbsp; &amp;nbsp; virtual void mouseDoubleClickEvent(QMouseEvent *event);&lt;br /&gt;};&lt;br /&gt;[/code]&lt;br /&gt;doublebutton.cpp&lt;br /&gt;[code]&lt;br /&gt;#include &quot;doublebutton.h&quot;&lt;br /&gt;&lt;br /&gt;DoubleButton::DoubleButton(QWidget *parent)&lt;br /&gt;: QPushButton(trUtf8(&quot;눌러보세요&quot;), parent) {&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void DoubleButton::mouseDoubleClickEvent(QMouseEvent *event) {&lt;br /&gt;&amp;nbsp; &amp;nbsp; QPushButton::mouseDoubleClickEvent(event);&lt;br /&gt;&amp;nbsp; &amp;nbsp; emit doubleClicked();&lt;br /&gt;}&lt;br /&gt;[/code]&lt;br /&gt;mainwidget.h&lt;br /&gt;[code]&lt;br /&gt;#include &amp;lt;QWidget&amp;gt;&lt;br /&gt;&lt;br /&gt;class DoubleButton; &amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; class QLabel;&lt;br /&gt;&lt;br /&gt;class MainWidget : public QWidget {&lt;br /&gt;&amp;nbsp; &amp;nbsp; Q_OBJECT&lt;br /&gt;public:&lt;br /&gt;&amp;nbsp; &amp;nbsp; MainWidget(QWidget *parent = 0);&lt;br /&gt;private slots:&lt;br /&gt;&amp;nbsp; &amp;nbsp; void setLabelDoubleClicked();&lt;br /&gt;private:&lt;br /&gt;&amp;nbsp; &amp;nbsp; QLabel *label;&lt;br /&gt;&amp;nbsp; &amp;nbsp; DoubleButton *button;&lt;br /&gt;};&lt;br /&gt;[/code]&lt;br /&gt;mainwidget.cpp&lt;br /&gt;[code]&lt;br /&gt;#include &amp;lt;QLabel&amp;gt;&lt;br /&gt;#include &quot;mainwidget.h&quot;&lt;br /&gt;#include &quot;doublebutton.h&quot;&lt;br /&gt;&lt;br /&gt;MainWidget::MainWidget(QWidget *parent)&lt;br /&gt;: QWidget(parent) {&lt;br /&gt;&amp;nbsp; &amp;nbsp; button = new DoubleButton(this);&lt;br /&gt;&amp;nbsp; &amp;nbsp; label = new QLabel(trUtf8(&quot;클릭 안됨&quot;), this);&lt;br /&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; connect(button, SIGNAL(doubleClicked()), this, SLOT(setLabelDoubleClicked()));&lt;br /&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; label-&amp;gt;move(100, 0);&lt;br /&gt;&amp;nbsp; &amp;nbsp; resize(200, 50);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void MainWidget::setLabelDoubleClicked() {&lt;br /&gt;&amp;nbsp; &amp;nbsp; label-&amp;gt;setText(trUtf8(&quot;더블 클릭&quot;));&lt;br /&gt;}&lt;br /&gt;[/code]&lt;br /&gt;main.cpp&lt;br /&gt;[code]&lt;br /&gt;#include &amp;lt;QApplication&amp;gt;&lt;br /&gt;#include &quot;mainwidget.h&quot;&lt;br /&gt;&lt;br /&gt;int main(int argc, char **argv) {&lt;br /&gt;&amp;nbsp; &amp;nbsp; QApplication app(argc, argv);&lt;br /&gt;&amp;nbsp; &amp;nbsp; MainWidget mw;&lt;br /&gt;&amp;nbsp; &amp;nbsp; mw.show();&lt;br /&gt;&amp;nbsp; &amp;nbsp; return app.exec();&lt;br /&gt;}&lt;br /&gt;[/code]&lt;br /&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;img src=&quot;http://xylosper.net/attach/1/1399454673.png&quot; alt=&quot;clicks&quot; height=&quot;82&quot; width=&quot;208&quot; /&gt;&lt;p class=&quot;cap1&quot;&gt;실행화면&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;일단 Q_OBJECT라는 키워드는 나중에 설명할테니 패스하시구요, 우선 doublebutton.h파일의 7번째 줄을 보시면 처음보는 키워드가 보일 것입니다.&lt;br /&gt;&lt;br /&gt;바로 signals 라는 키워드인데요, 뒤에 :를 붙여서 마치 public이나 private같은 접근한정자처럼 쓰였습니다.&lt;br /&gt;&lt;br /&gt;이 키워드가 함수를 시그널로 만들어주는 키워드입니다.&lt;br /&gt;&lt;br /&gt;사용법도 public등과 같이 signals:라고 그 다음부터 다른 한정자가 나오기 전까지는 전부 시그널로 처리됩니다.&lt;br /&gt;&lt;br /&gt;일반적으로 시그널은 직접 호출될 일이 없기 때문에 원형만 선언하고 내용은 정의하지 않아도 됩니다.(물론 호출해서 일반함수로 쓰는 것도 가능하며, 이경우는 당연히 함수 정의도 있어야겠지요)&lt;br /&gt;&lt;br /&gt;이제 그 다음줄에 있는 doubleClicked()라는 함수는 시그널로 이용할 수 있습니다.&lt;br /&gt;&lt;br /&gt;남은 문제는 언제 이것을 발생시키느냐입니다.&lt;br /&gt;&lt;br /&gt;이름을 그럴싸하게 지었다고 지가 알아서 튀어나올리는 만무하겠죠?&lt;br /&gt;&lt;br /&gt;그럼 버튼이 더블클릭되는 시점이 언제인지를 알아야겠습니다.&lt;br /&gt;&lt;br /&gt;이를 위해서 어떤 위젯이 더블클릭되면 호출되는 이벤트 처리 함수인 mouseDoubleClickEvent 함수를 오버라이딩하기로 합니다.&lt;br /&gt;&lt;br /&gt;doublebutton.cpp파일의 8-11번째 줄을 보면 다음과 같이 적혀있습니다.&lt;br /&gt;[code]&lt;br /&gt;void DoubleButton::mouseDoubleClickEvent(QMouseEvent *event) {&lt;br /&gt;&amp;nbsp; &amp;nbsp; QPushButton::mouseDoubleClickEvent(event);&lt;br /&gt;&amp;nbsp; &amp;nbsp; emit doubleClicked();&lt;br /&gt;}&lt;br /&gt;
[/code]&lt;br /&gt;여기서 QPushButton::mouseDoubleClickEvent(event);를 호출하는 이유는, 혹시 모를 더블클릭관련된 다른 이벤트들이 처리되도록하기 위해서입니다.&lt;br /&gt;&lt;br /&gt;제가아는 한에서 QPushButton이나 그 상위의 QWidget은 딱히 더블클릭에 대해서 아무것도 하지 않는 걸로 알고 있으므로 이경우는 저 라인이 있으나 없으나 똑같을 것입니다.&lt;br /&gt;&lt;br /&gt;중요한건 그다음줄인데요, 여기서 또 emit 이라는 처음보는 키워드가 나옵니다.&lt;br /&gt;&lt;br /&gt;사전을 찾아보시면 emit은 뱉다 라는 뜻이라고 나옵니다.&lt;br /&gt;&lt;br /&gt;예, 말그대로 emit doubleClicked(); 라고 적으면 doubleClicked() 시그널을 뱉어냅니다.&lt;br /&gt;&lt;br /&gt;참고로 이부분은 doubleClicked()를 호출하는 구문이 아닙니다.&lt;br /&gt;&lt;br /&gt;큐티용 전처리기인 moc를 거쳐서 이부분은 (직접 그자리에서 치환되진 않지만 결과적으로 보면) 여기에 연결된 슬롯들을 호출하는 구문으로 치환될 것입니다.&lt;br /&gt;&lt;br /&gt;이렇게 하여 시그널을 만들고 그것을 &lt;span style=&quot;text-decoration: line-through;&quot;&gt;뱉는&lt;/span&gt;발생시키는 방법을 알아보았습니다.&lt;br /&gt;&lt;br /&gt;참고로 signals는 다른 public같은 한정자와 같이 쓰면안됩니다.&lt;br /&gt;&lt;br /&gt;signals 자체에 protected 한정자가 포함되어있기 때문입니다.(즉, 모든 시그널은 protected 멤버함수입니다.)&lt;br /&gt;&lt;br /&gt;다음으로 슬롯을 만드는 방법을 알아보겠습니다.&lt;br /&gt;&lt;br /&gt;(여기서도 일단 Q_OBJECT는 패스합니다)mainwidget.h를 보면 역시나 처음보는 키워드가 있습니다.&lt;br /&gt;&lt;br /&gt;9번째 줄의 slots라는 키워드인데요, 뻔합니다. 이게 슬롯선언을 위한 키워드죠.&lt;br /&gt;&lt;br /&gt;슬롯은 시그널과 달리 직접 호출되는 함수이기 때문에 원형만 선언하고 정의하지 않으면 링크단계에서 에러가 나며, 또 꼭 시그널에 의해 호출되지 않고 평범한 함수호출로도 자주 이용되기 때문에 접근 한정자가 없습니다.&lt;br /&gt;&lt;br /&gt;그러므로 이경우는 private slots: 와 같이 private라는 접근 한정자를 달아주었습니다.&lt;br /&gt;&lt;br /&gt;외부에서 호출가능하게 만들려면 public slots: 와 같이 해야겠지요.&lt;br /&gt;&lt;br /&gt;signals와 마찬가지로 slots다음부터 다른 한정자가 다올때까지 선언된 함수들은 모두 슬롯으로 이용가능해집니다.&lt;br /&gt;&lt;br /&gt;그러므로 다음줄에 적힌 setLabelDoubleClicked() 함수는 다른 시그널에 연결가능한 슬롯이 되었습니다.&lt;br /&gt;&lt;br /&gt;그리고 mainwidget.cpp의 setLabelDoubleClicked()의 구현을 보면 심플합니다.&lt;br /&gt;&lt;br /&gt;그냥 label의 setText()함수를 이용해서 더블클릭이란 글자로 바뀌도록 합니다.&lt;br /&gt;&lt;br /&gt;이제 더블클릭되면 발생할 시그널과, 이를 연결할 슬롯이 준비되었으므로 둘을 연결하기만 하면됩니다.&lt;br /&gt;&lt;br /&gt;mainwidget.cpp에서 MainWidget의 생성자를 봅시다.&lt;br /&gt;&lt;br /&gt;connect(button, SIGNAL(doubleClicked()), this, SLOT(setLabelDoubleClicked()));&lt;br /&gt;&lt;br /&gt;라고 적혀있죠? button의 시그널인 doubleClicked()와 this(MainWidget)의 setLabelDoubleClicked()를 연결합니다.&lt;br /&gt;&lt;br /&gt;생성자에서 뭔가 하고싶은 말이 있으신 분이 계실지도 모르겠는데, 잠시 참아주세요.&lt;br /&gt;&lt;br /&gt;이제 컴파일해보고 실행하고 버튼을 더블 클릭하면 라벨의 텍스트가 더블 클릭으로 바뀝니다.&lt;br /&gt;&lt;br /&gt;별거 아닌 예제지만 시그널과 슬롯을 이용하기 위한 것들을 하나빼고 다 설명했습니다.&lt;br /&gt;&lt;br /&gt;그럼 빠진 하나는? 기억력좋으신 분은 제가 Q_OBJECT를 패스라고 설명한걸 기억하실 텐데요, 바로 이 키워드가 핵심키워드입니다.&lt;br /&gt;&lt;br /&gt;사실 이글에서 이 키워드와, 그리고 생성자에서 느낀 위화감을 설명해줄 Qt의 Meta-Object 시스템까지 소개할려고 했는데, 내용이 길어져서 다음회로 넘겨야 겠습니다.&lt;br /&gt;&lt;br /&gt;이리하여, 다음회는 Meta-Object 시스템입니다.&lt;br /&gt;</description>
			<category>Qt</category>
			<category>Qt</category>
			<category>signal</category>
			<category>slot</category>
			<category>슬롯</category>
			<category>시그널</category>
			<author>(xylosper)</author>
			<guid>http://xylosper.net/111</guid>
			<comments>http://xylosper.net/111#entry111comment</comments>
			<pubDate>Wed, 26 Mar 2008 22:23:09 +0900</pubDate>
		</item>
		<item>
			<title>Qt에 대하여 - 4. Hello, world! advanced</title>
			<link>http://xylosper.net/110</link>
			<description>좀더 진보된(?) Hello, world입니다.&lt;br&gt;[code]&lt;br&gt;#include &amp;lt;QApplication&amp;gt;&lt;br&gt;#include &amp;lt;QPushButton&amp;gt;&lt;br&gt;&lt;br&gt;int main(int argc, char **argv) {&lt;br&gt;&amp;nbsp; &amp;nbsp; QApplication app(argc, argv);&lt;br&gt;&amp;nbsp; &amp;nbsp; QPushButton button(QObject::trUtf8(&quot;안녕하세요! 종료하고 싶으시면 눌러보세요.&quot;));&lt;br&gt;&amp;nbsp; &amp;nbsp; QObject::connect(&amp;amp;button, SIGNAL(clicked()), qApp, SLOT(quit()));&lt;br&gt;&amp;nbsp; &amp;nbsp; button.show();&lt;br&gt;&amp;nbsp; &amp;nbsp; return app.exec();&lt;br&gt;} &lt;br&gt;[/code]&lt;br&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;img src=&quot;http://xylosper.net/attach/1/1121753415.png&quot; alt=&quot;Hello, world! advanced&quot; height=&quot;64&quot; width=&quot;272&quot; /&gt;&lt;p class=&quot;cap1&quot;&gt;실행결과&lt;/p&gt;&lt;/div&gt;signal/slot이 드디어 나왔습니다.&lt;br&gt;이번회는 signal/slot에 대한 설명과 tr/trUtf8 함수에 대한 설명을 위한 시간을 가지겠습니다.&lt;br&gt;기본적인 구조는 동일하므로 지난번같이 각 라인을 설명하진 않겠습니다.&lt;br&gt;&lt;br&gt;일단 QPushButton이라는 새로운 클래스가 나왔는데요, 이 클래스도 역시 위젯이며, 이름대로 push하기 위한 button입니다.&lt;br&gt;&lt;br&gt;보통 자주 보는 확인버튼이나 취소버튼등이 이 클래스로 구현될 수 있습니다.&lt;br&gt;&lt;br&gt;QPushButton도 역시 QLabel과 마찬가지로 생성자로 문자열을 받아서, 그 문자열로 버튼의 text를 초기화하며, 마찬가지로 text(), setText()로 문자열을 확인하거나 지정할 수 있습니다.&lt;br&gt;&lt;br&gt;그런데, 6번째 줄의 button을 생성할때, 생소한 정적함수 QObject::trUtf8()이란 함수가 호출되고 있습니다.&lt;br&gt;&lt;br&gt;이 함수는 프로그램을 번역할떄 도움이 됩니다.&lt;br&gt;&lt;br&gt;만약 프로그램을 다른 언어로 번역해야 할때, 소스내의 모든 문자열을 변역할 필요는 없을 것입니다.&lt;br&gt;&lt;br&gt;그렇다고 소스를 일일이 돌아다니면서 번역하자니 상당한 노력이 들테고, 빠진부분도 많겠지요.&lt;br&gt;&lt;br&gt;만약 번역이 필요한 부분의 문자열은 전부 QObject::tr()혹은 QObject::trUtf8()로 감싸두면, Qt를 설치할때 함께 설치된 툴중 하나인 lupdate라는 프로그램을 이용하면, 프로젝트 파일에 등록된 모든 소스를 파싱하여 번역이 필요한 부분만 골라서 번역을 위한 xml파일을 생성해주고, 번역작업은 이 파일만 가지고 하면 됩니다.&lt;br&gt;&lt;br&gt;이또한 Qt Linguist 라는 프로그램을 통해서 손쉽게 열고 편집할 수 있기 때문에, 번역하는 사람이 프로그래밍을 전혀 몰라도 되고, 그러므로 프로그래밍 언어는 몰라도 말로 하는 언어에 능통한 사람이 번역이 가능하고 좀더 고품질의 번역이 가능하겠죠?&lt;br&gt;&lt;br&gt;그럼 tr()과 trUtf8()의 차이는 무엇인가하면, 함수 이름에서 알 수 있는데 인코딩의 차이입니다.&lt;br&gt;&lt;br&gt;만약 영어로 프로그램을 만든다면 모든 문자가 ascii범위내에 있을테니 tr로 충분합니다만, 한국어로 메뉴등을 작성한다면, Qt의 문자열 클래스인 QString은 유니코드로 처리하기 때문에 인코딩이 중요해집니다.&lt;br&gt;&lt;br&gt;그래서 한글을 써서 Qt로 프로그래밍을 하실때는 꼭 소스파일을 전부 utf8로 저장하시고, 한글이 필요한 부분에서는 trUtf8이나 QString::fromUtf8()과 같은 함수로 utf8로부터 문자열을 생성해주는 함수를 이용하셔야 합니다.&lt;br&gt;&lt;br&gt;사실 처음에 이걸 모르고 자꾸 에러가 나고 제대로 표시가 안되는 바람에 전부 영어로 짠다음에 위에서 말한 Linguist로 한글로 메뉴를 번역하는 짓을 하곤 했습니다-_-;&lt;br&gt;&lt;br&gt;이제 그 다음줄로 가봅시다.&lt;br&gt;&lt;br&gt;사실 이부분이 이번 편의 하일라이트입니다.&lt;br&gt;[code]&lt;br&gt;&amp;nbsp; &amp;nbsp; QObject::connect(&amp;amp;button, SIGNAL(clicked()), qApp, SLOT(quit()));&lt;br&gt;[/code]&lt;br&gt;여기서 보이는 QObject::connect, SIGNAL, SLOT 이 세 키워드 모두 매우매우 중요합니다.&lt;br&gt;&lt;br&gt;우선 시그널(signal)에 대해서 설명해보겠습니다.&lt;br&gt;&lt;br&gt;큐티의 시그널이란, 뭐 이름 그대로 신호같은 겁니다.&lt;br&gt;&lt;br&gt;예를 들어 위의 예제에서 clicked()가 시그널이며, 이름으로 부터 유추할수 있듯이 button이 clicked하면(눌러지면) clicked()라는 시그널이 발생됩니다.&lt;br&gt;&lt;br&gt;이 시그널은 슬롯으로 지정된 함수들과 &#039;연결&#039;될 수 있습니다.&lt;br&gt;&lt;br&gt;참고로 슬롯과 마찬가지로 시그널도 함수들입니다(시그널과 슬롯을 선언하는 방법은 나중에 상속받아서 클래스를 만드는 예제에서 설명하겠습니다.)&lt;br&gt;&lt;br&gt;그리고 &#039;연결&#039;을 행하는 함수가 바로 QObject::connect()입니다.&lt;br&gt;&lt;br&gt;즉 위의 한줄은, button의 clicked() 시그널과 qApp의 quit() 슬롯을 연결해라! 라고 하는 것입니다.&lt;br&gt;&lt;br&gt;여기서 qApp는 QApplication의 객체에 대한 포인터를 바로 불러올수 있는 매크로입니다.&lt;br&gt;&lt;br&gt;사실 여기선 같은 함수내에서위에 QApplication의 객체 app가 있으므로, qApp대신에 &amp;amp;app라고 직접 포인터를 넘겨줘도 되지만, 일부러 qApp라는 매크로를 소개하기 위해서 적어보았습니다.&lt;br&gt;&lt;br&gt;확실친 않지만 아마도 QApplication::instance() 함수의 매크로로 정의되어있을 것같습니다.&lt;br&gt;&lt;br&gt;아무튼 저렇게해서 시그널과 슬롯이 연결되면, 시그널이 발생될때마다 연결된 슬롯이 호출됩니다.&lt;br&gt;&lt;br&gt;프로그램의 흐름을 적어보자면&lt;br&gt;&lt;br&gt;button 클릭 -&amp;gt; clicked() 시그널 발생 -&amp;gt; quit() 슬롯 호출 -&amp;gt; 프로그램 종료&lt;br&gt;&lt;br&gt;이런 순서가 되겠지요.&lt;br&gt;&lt;br&gt;&lt;p id=&quot;more110_0&quot; class=&quot;moreless_fold&quot;&gt;&lt;span style=&quot;cursor: pointer;&quot; onclick=&quot;toggleMoreLess(this, &#039;110_0&#039;,&#039;뭔가 설명이 애매한데?&#039;,&#039;숨기기&#039;); return false;&quot;&gt;뭔가 설명이 애매한데?&lt;/span&gt;&lt;/p&gt;&lt;div id=&quot;content110_0&quot; class=&quot;moreless_content&quot; style=&quot;display: none;&quot;&gt;위의 설명이 뭔가 굉장히 추상적이고 뜬구름 잡는 듯한 설명이라고 생각하는 분도 계실 것 같습니다.&lt;br&gt;&lt;br&gt;여기서 잠시 connect 함수의 원형을 살펴보겠습니다.(오버로드된 버전도 있지만 간단하므로 생략합니다.)&lt;br&gt;[code]&lt;br&gt;bool connect(const QObject *sender, const char *signal, const QObject *receiver,&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; const char *method, Qt::ConnectionType type = Qt::AutoCompatConnection);&lt;br&gt;[/code]&lt;br&gt;여기서 한가지 흥미로운 사실을 알 수 있습니다.&lt;br&gt;&lt;br&gt;두번째 인자로 넘긴 SIGNAL(clicked())와 네번째 인자로 넘긴 SLOT(quit())의 자료형이 const char * 즉, 문자열로 되어있는 것입니다.&lt;br&gt;&lt;br&gt;결국 SIGNAL()과 SLOT()은 함수이름을 문자열로 변환해주는 매크로인 셈입니다.&lt;br&gt;&lt;br&gt;사실 (당연하지만) 시그널이나 슬롯이란 표준 C++에서 지원하는 개념이 아니라, 큐티에서 독자적으로 도입한 개념이고 그 구현또한 실제 직접적으로 보이는 것이 아니라, 일단 moc라는 일종의 전처리기 같은 것을 거쳐서 표준적인 C++구문들로 변환된후에 컴파일되는 것이기 때문에, 제대로 설명하자면 그 파일들을 분석해볼 필요가 있습니다.&lt;br&gt;&lt;br&gt;하지만 사실 그런 부분은 알 필요가 없기 때문에(이것도 객체지향에서 얘기하는 정보은폐라고 할수 있을지도 모르겠네요), 그냥 시그널과 슬롯을 개념적으로 시그널이 발생되면 슬롯이 호출된다 정도로만 알고 계시면 될것 같습니다.&lt;/div&gt;하나의 시그널은 여러개의 슬롯과 연결될 수 있으며, 반대로 여러개의 시그널이 하나의 슬롯으로 연결될수도 있습니다.&lt;br&gt;&lt;br&gt;또 연결하는 시그널과 슬롯들은 인자가 같거나, 슬롯쪽이 적어야 합니다.&lt;br&gt;&lt;br&gt;왜냐하면 시그널에서 필요한 정보가 슬롯으로 전달될때 슬롯함수를 호출하면서 그 인자로 넘어가기 때문입니다.&lt;br&gt;&lt;br&gt;예를 들어 QPushButton의 함수중에 setCheckable(bool)을 호출하여 true로 설정해주면, 이 버튼은 토글버튼(한번 누르면 들어가고, 한번 누르면 다시 나오는 방식의 버튼)이 됩니다.&lt;br&gt;&lt;br&gt;이때, 사용자가 이 버튼을 눌렀을때, 예를 들어 버튼이 들어가면 on이라 적어주고, 버튼이 나오면 off라 적어주는 obj의 슬롯 onOff(bool on)이란 함수와 연결하고 싶다면,&lt;br&gt;&lt;br&gt;connect(&amp;amp;button, SIGNAL(toggled(bool)), obj, SLOT(onOff(bool)));&lt;br&gt;&lt;br&gt;과 같이 적어주어야 합니다.&lt;br&gt;&lt;br&gt;toggled(bool) 시그널은 위와같이 토글 버튼일때, 토글될때마다 그 상태가 자료형 bool의 인자에 저장되어서 발생합니다.&lt;br&gt;&lt;br&gt;예를 들어보면,&lt;br&gt;&lt;br&gt;프로그램 실행(버튼 나온 상태:off) -&amp;gt; 버튼 클릭(들어감) -&amp;gt; toggled(true) 발생 -&amp;gt; onOff(true) 호출 -&amp;gt; 글자를 on으로 바꿈&lt;br&gt;-&amp;gt; 버튼 클릭(나옴) -&amp;gt; toggled(false) 발생 -&amp;gt; onOff(false) 호출 -&amp;gt; 글자를 off로 바꿈&lt;br&gt;&lt;br&gt;이와같이 작동하겠지요.&lt;br&gt;&lt;br&gt;단, 슬롯쪽이 인자 갯수가 적은 경우는 괜찮습니다.&lt;br&gt;&lt;br&gt;SIGNAL(foo(bool, int))와 SLOT(foo(bool))은 연결될 수 있습니다.&lt;br&gt;&lt;br&gt;단 앞에서부터 인자가 일치해야하므로, SLOT(foo(int))와는 연결될 수 없습니다.&lt;br&gt;&lt;br&gt;참고로 SIGNAL()과 SLOT()에 함수 이름을 적어줄 때는 규칙이 있습니다.&lt;br&gt;&lt;br&gt;함수이름(인자자료형만,...) 이런 식입니다.&lt;br&gt;&lt;br&gt;예를 들어 어떤 시그널이나 슬롯의 원형이 다음과 같다면&lt;br&gt;&lt;br&gt;double foo(int first, bool second)&lt;br&gt;&lt;br&gt;SIGNAL(foo(int, bool))이나 SLOT(foo(int, bool))과 같이 적어줍니다.&lt;br&gt;&lt;br&gt;반환형이 double이나 인자의 이름인 first나 second등은 적지 않습니다.&lt;br&gt;&lt;br&gt;또한, 시그널과 시그널을 연결할 수도 있습니다.&lt;br&gt;&lt;br&gt;시그널 A와 시그널 B를 연결하면 A시그널이 발생하면 자동으로 B시그널도 발생됩니다.&lt;br&gt;&lt;br&gt;이경우도 시그널과 슬롯을 연결할때와 마찬가지로 인자에 대한 규칙이 적용됩니다.&lt;br&gt;&lt;br&gt;이상 큐티를 이용하는데 매우 중요한 시그널/슬롯에 대한 설명이었습니다.&lt;br&gt;&lt;br&gt;이거 모르고 큐티로 프로그램을 짠다는건 사실상 불가능할 정도이니, 잘 알아두시고, 혹시 잘 이해가 안되거나 설명이 난해한부분이 있으면 말씀해주시면 개선하도록 하겠습니다.&lt;br&gt;</description>
			<category>Qt</category>
			<category>Qt</category>
			<category>signal</category>
			<category>slot</category>
			<category>번역</category>
			<category>슬롯</category>
			<category>시그널</category>
			<author>(xylosper)</author>
			<guid>http://xylosper.net/110</guid>
			<comments>http://xylosper.net/110#entry110comment</comments>
			<pubDate>Wed, 26 Mar 2008 20:00:10 +0900</pubDate>
		</item>
		<item>
			<title>Qt에 대하여 - 3. 위젯(Widget)</title>
			<link>http://xylosper.net/109</link>
			<description>전회에 QLabel을 위젯이라고 소개하였습니다.&lt;br /&gt;&lt;br /&gt;그럼 위젯이란 무엇일까요?&lt;br /&gt;&lt;br /&gt;쉽게 얘기하면 보통 우리가 &#039;창(window)&#039;이라고 하는 것들입니다.&lt;br /&gt;&lt;br /&gt;MFC에서는 창이라고 하지만, Qt에서는 위젯이라는 이름이 쓰입니다.&lt;br /&gt;&lt;br /&gt;일반적인 유저들은 창이라고하면 독립된 창 하나만을 생각하기 쉽습니다만, 그뿐만 아니라 창안의 버튼이라든가, 글쓰는 난이라든가, 콤보박스등도 모두 창입니다.&lt;br /&gt;&lt;br /&gt;이글을 Qt에 대한 글이므로 되도록 창이란 용어보다는 위젯이라는 용어를 쓰고, 창이란 용어는 하나의 독립된 창을 나타낼때만 쓰도록 하겠습니다.&lt;br /&gt;&lt;br /&gt;Qt에서 위젯들은 모두 QWidget이라는 클래스로부터 상속됩니다.&lt;br /&gt;&lt;br /&gt;이 클래스는 MFC로 치면 CWnd같은 클래스로, 모든 위젯의 공통요소들이 정의되어있고, 필요한 이벤트처리 함수가 오버라이딩 가능하도록 정의되어있습니다.&lt;br /&gt;&lt;br /&gt;QWidget 클래스의 생성자는 QWidget::QWidget(QWidget *parent = 0, Qt::WindowFlags f = 0) 과 같은 원형을 가지고 있으며, QWidget을 상속하는 대부분(아마 모든이라고 해도 될듯한데 전부 제가 확인한 것은 아니므로 대부분이라고 적습니다)의 위젯 클래스들도 최소한 이 두개의 인자를 가지고 있습니다.&lt;br /&gt;&lt;br /&gt;첫번째 인자 parent는 부모 위젯을 지정해줍니다.&lt;br /&gt;&lt;br /&gt;여기서 지정하는 &#039;부모&#039;란 클래스 상속관계에서의 부모클래스 자식클래스가 아닌, 위젯간의 포함관계를 나타냅니다.&lt;br /&gt;&lt;br /&gt;포함관계란, 어떤 위젯이 어떤 위젯의 내부에 존재하는 것을 가리킵니다.&lt;br /&gt;&lt;br /&gt;예를 들어 어떤 위젯A을 띄웠더니 그안에 버튼이 있더라, 그럼 위젯 A는 버튼의 부모가 되는 것입니다.&lt;br /&gt;&lt;br /&gt;디폴트 인자로 널포인터가 지정되어있는데, 만약 부모를 0으로 지정하면 최상위 윈도우, 즉 어떤 다른 위젯에도 포함되어있지 않은 독립된 창이 됩니다.&lt;br /&gt;&lt;br /&gt;지난 &lt;a href=&quot;http://xylosper.net/108&quot; target=&quot;_blank&quot;&gt;Hello, world예제&lt;/a&gt;에서 QLabel 클래스의 인스턴스를 생성할때, label(&quot;Hello, world!&quot;)와 같이 생성자를 호출하였는데, 사실 이것도 뒤에 두개의 인자 parent와 f가 디폴트 인자 0, 0으로 지정되어 생략된 형태였습니다.&lt;br /&gt;&lt;br /&gt;이경우 parent가 0이므로 label은 최상위 윈도우가 되어서 독립된 창으로 표시된 것입니다.&lt;br /&gt;&lt;br /&gt;두번째 인자인 f는 위젯의 기본적인 (정확한 표현은 아니지만)스타일등을 지정합니다.&lt;br /&gt;&lt;br /&gt;여기에는 Qt::Widget이나 Qt::Dialog, Qt::ToolTip 등과 같은 값과 |(BIT OR연산자)로 Qt::FramelessWindowHint나 Qt::WindowStaysOnTopHint같은 값이 결합되어서 들어갈 수 있는데, 아마 제 글에서 이부분값을 0이외의 값으로 지정할 일은 없을 듯합니다.&lt;br /&gt;&lt;br /&gt;&lt;p id=&quot;more109_0&quot; class=&quot;moreless_fold&quot;&gt;&lt;span style=&quot;cursor: pointer;&quot; onclick=&quot;toggleMoreLess(this, &#039;109_0&#039;,&#039;인자 f에 대한 좀더 자세한 설명&#039;,&#039;숨기기&#039;); return false;&quot;&gt;인자 f에 대한 좀더 자세한 설명&lt;/span&gt;&lt;/p&gt;&lt;div id=&quot;content109_0&quot; class=&quot;moreless_content&quot; style=&quot;display: none;&quot;&gt;이부분에 들어가는 인자는 위젯의 종류와 기본적인 속성을 지정해줍니다.&lt;br /&gt;&lt;br /&gt;기본값인 0은 Qt::Widget의 값인데, 이경우는 parent가 0이면 자동으로 독립된 창으로, 0이 아니면 다른 위젯에 포함된 위젯이됩니다.&lt;br /&gt;&lt;br /&gt;또 Qt::Window라는 값도 있는데, 이값으로 지정되면 무조건 작업표시줄에 타이틀까지 가지는 독립된 창으로 표시됩니다.&lt;br /&gt;&lt;br /&gt;Qt::Dialog는 QDialog에서 기본으로 지정되는 값으로, 독립된 창을 만들되 작업표시줄에는 표시되지 않고 또한 다이얼로그 창처럼 최소화나 최대화 버튼이 없는 위젯으로 만듭니다.&lt;br /&gt;&lt;br /&gt;이외에도 Qt::ToolTip, Qt::Tool, Qt::Popup...등이 있으며 각각의 옵션에 대해서는 assistant를 참고하시기 바랍니다.&lt;br /&gt;&lt;br /&gt;또한 이들과 함께 |연산자로 결합될수 있는 값들이 있습니다.&lt;br /&gt;&lt;br /&gt;예를 들어 Qt::FramelessWindowHint는 제목표시줄같은 프레임이 없는 창을 만들게하고, Qt::WindowStaysOnTopHint는 창을 항상위로 뜨게 합니다.&lt;br /&gt;&lt;br /&gt;이외에도 많은 옵션이 존재하므로 역시 assistant를 참고하시기 바랍니다.&lt;br /&gt;&lt;/div&gt;다음로 QWidget 클래스의 중요한 프로퍼티와 함수 몇가지를 소개하겠습니다.&lt;br /&gt;&lt;br /&gt;1) size 관련&lt;br /&gt;&lt;br /&gt;size()함수는 현재 위젯의 크기를 QSize 클래스에 담아서 반환해줍니다.&lt;br /&gt;&lt;br /&gt;QSize는 이름 처럼 너비(width()) 높이(height())등 크기에 대한 정보를 가지고있는 클래스입니다.&lt;br /&gt;&lt;br /&gt;너비만 알고 싶다면 width(), 높이만 알고 싶다면 height()를 바로 이용해도 됩니다.&lt;br /&gt;&lt;br /&gt;크기를 변경하고 싶다면 resize(const QSize&amp;amp;)나, resize(int width, int height)를 이용하면됩니다.&lt;br /&gt;&lt;br /&gt;이처럼 이름만 봐도 바로 뭐하는건지 알듯한 함수에 대해서는 앞으로 자세한 설명을 생략합니다.&lt;br /&gt;&lt;br /&gt;sizeHint()는 위젯의 (일반적으로) 가장 적합한 크기를 반환해줍니다.&lt;br /&gt;&lt;br /&gt;이는 위젯의 종류에 따라서 달라질수 있으므로 오버라이딩 가능하게 가상함수로 선언되어있구요.&lt;br /&gt;&lt;br /&gt;또, Qt의 레이아웃 시스템은 이 sizeHint()에 근거하여 작동하며, adjustSize()라는 함수도 sizeHint()에 근거하여 적당한 크기로 위젯을 리사이즈해줍니다.&lt;br /&gt;&lt;br /&gt;이외에도 minimumSizeHint, sizePolicy, minimumSize, maximumSize 등의 프로퍼티가 있습니다.&lt;br /&gt;&lt;br /&gt;2) 위치 관련&lt;br /&gt;&lt;br /&gt;pos()함수는 현재 위젯의 위치를 부모 클래스에 대한 상대적인 위치로 반환합니다.&lt;br /&gt;&lt;br /&gt;만일 현재 위젯이 최상위 윈도우라면 화면내에서의 위치를 반환합니다.&lt;br /&gt;&lt;br /&gt;상대적인 위치가 아닌, 화면내에서의 위치를 알고 싶으면 부모위젯의 mapToGlobal()함수로 글로벌 좌표로 변환해주면 됩니다.&lt;br /&gt;&lt;br /&gt;위젯을 움직이려면, move(const QPoint &amp;amp;)나 move(int x, int y)와 같은 함수를 이용하면 됩니다.&lt;br /&gt;&lt;br /&gt;3) 보이기/숨기기&lt;br /&gt;&lt;br /&gt;show(), hide(), setVisible(bool), setHidden(bool) 와 같은 함수들이 있고 이름만 보면 아실 것입니다.&lt;br /&gt;&lt;br /&gt;여기서 setVisible이나 setHidden처럼 같은 역할의 함수가 여러개가 존재하는 이유는 slot/signal을 위한 편의 제공입니다...만 아직 slot/signal을 설명하지 않았으므로 그냥 이런것도 있다는 것만 알아두시면 되겠습니다.&lt;br /&gt;&lt;br /&gt;또 close()라는 함수도 있습니다. hide()는 단순히 보이지 않게만 하지만, close는 위젯을 닫아버리고, 만약 그것이 최상위 윈도우라면 어플리케이션은 종료됩니다.&lt;br /&gt;&lt;br /&gt;4) 각종 이벤트 함수들&lt;br /&gt;&lt;br /&gt;위젯은 GUI의 기본 요소인 만큼 각종 이벤트 함수들이 오버라이딩가능하도록 가상함수로 선언되어있습니다.&lt;br /&gt;&lt;br /&gt;개인적으로 다음과 같은 이벤트 처리 함수를 자주 이용하게 되더군요.&lt;br /&gt;&lt;br /&gt;keyPressEvent, mousePressEvent, mouseMoveEvent, resizeEvent, moveEvent&lt;br /&gt;&lt;br /&gt;전부 이름만봐도 어떤 경우에 호출되는 함수인지 알듯하여 자세한 설명은 생략하고, 그외에도 많은 함수나 프로퍼티가 있으니, 나중에 예제에서 쓸일이 있으면 그때 설명하도록 하겠습니다.&lt;br /&gt;&lt;br /&gt;위젯에 대해서는 이정도로 마치도록 하구요, 각종 위젯에 대한 소개는 몇가지 다른 위젯을 좀더 접해본후에 하도록 하겠습니다.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;</description>
			<category>Qt</category>
			<category>Qt</category>
			<category>widget</category>
			<category>위젯</category>
			<author>(xylosper)</author>
			<guid>http://xylosper.net/109</guid>
			<comments>http://xylosper.net/109#entry109comment</comments>
			<pubDate>Wed, 26 Mar 2008 17:43:27 +0900</pubDate>
		</item>
		<item>
			<title>Qt에 대하여 - 2. Hello, world!</title>
			<link>http://xylosper.net/108</link>
			<description>뭐든 프로그래밍 언어를 공부할땐 Hello, world부터 시작하듯, 저도 Qt의 Hello, world로 시작해보겠습니다.&lt;br /&gt;&lt;br /&gt;일단 적당한 곳에 main.cpp파일을 만드시고, 다음과 같이 적어보세요.&lt;br /&gt;[code]&lt;br /&gt;#include &amp;lt;QApplication&amp;gt;&lt;br /&gt;#include &amp;lt;QLabel&amp;gt;&lt;br /&gt;&lt;br /&gt;int main(int argc, char **argv) {&lt;br /&gt;&amp;nbsp; &amp;nbsp; QApplication app(argc, argv);&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;QLabel label(&quot;Hello, world!&quot;);&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;label.show();&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;return app.exec();&lt;br /&gt;}&lt;br /&gt;[/code]&lt;br /&gt;그리고 콘솔(터미널, 명령프롬프트, 앞으로는 전부 콘솔이라고 적겠습니다)을 열고, main.cpp가 있는 곳으로 가서&lt;br /&gt;&lt;br /&gt;$qmake -project&lt;br /&gt;$qmake&lt;br /&gt;$make&lt;br /&gt;&lt;br /&gt;라고 차례대로 쳐줍니다.&lt;br /&gt;여기서 $는 콘솔임을 나타냅니다. 실제로 $를 칠 필요는 없구요, 예를 들어 C:\helloworld에 main.cpp가 들어있다면&lt;br /&gt;&lt;br /&gt;C:\helloworld&amp;gt;qmake -project(엔터)&lt;br /&gt;C:\helloworld&amp;gt;qmake(엔터)&lt;br /&gt;C:\helloworld&amp;gt;make(엔터)&lt;br /&gt;&lt;br /&gt;같이 되겠지요. 참고로 마지막의 make는 사용하는 프로그램에 따라다릅니다.&lt;br /&gt;&lt;br /&gt;예를 들어 mingw를 이용한다면 mingw32-make가 될것이고, VC++이라면 nmake, 리눅스라면 make나 gmake등이 되겠지요.&lt;br /&gt;&lt;br /&gt;사용하시는 make툴에 맞게 입력하시면 됩니다.&lt;br /&gt;&lt;br /&gt;그러면 helloworld폴더내에 helloworld실행파일이 생길것입니다.(윈도우라면 helloworld.exe겠죠? 앞으로 .exe는 생략합니다.)&lt;br /&gt;&lt;br /&gt;이걸 실행해보면 다음과 같은 창이 나타납니다.&lt;br /&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;img src=&quot;http://xylosper.net/attach/1/1183423092.png&quot; alt=&quot;Hello, world&quot; height=&quot;64&quot; width=&quot;191&quot; /&gt;&lt;p class=&quot;cap1&quot;&gt;Hello, word 실행 결과(편의상 실행후 리사이즈했습니다)&lt;/p&gt;&lt;/div&gt;여러분의 플랫폼에 따라서 창의 모습은 다를수 있지만, 결과는 같을 것입니다.(저는 리눅스에서 만들었습니다.)&lt;br /&gt;&lt;br /&gt;Hello, world!라고 적힌 창이 하나 뜨고 끝입니다.&lt;br /&gt;&lt;br /&gt;윈도우 프로그래밍을 해보신 분이라면 알겠지만, 윈도우에서의 창모양은 MFC에서 만들었대랑 완전히 똑같을 것입니다.&lt;br /&gt;&lt;br /&gt;MFC도 큐티도 결국엔 Win32API를 호출해서 만드므로 어떻게 보면 당연한 결과입니다.&lt;br /&gt;&lt;br /&gt;그럼 이제 프로그램의 각 라인과 위에서 컴파일하기위해서 입력했던 명령들에 대해서 설명해보겠습니다.&lt;br /&gt;&lt;br /&gt;편의상 한번더 소스코드를 여기에 적습니다.&lt;br /&gt;[code]&lt;br /&gt;#include &amp;lt;QApplication&amp;gt;&lt;br /&gt;#include &amp;lt;QLabel&amp;gt;&lt;br /&gt;&lt;br /&gt;int main(int argc, char **argv) {&lt;br /&gt;&amp;nbsp; &amp;nbsp; QApplication app(argc, argv);&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;QLabel label(&quot;Hello, world!&quot;);&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;label.show();&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;return app.exec();&lt;br /&gt;}&lt;br /&gt;[/code]&lt;br /&gt;소스 설명의 앞의 번호는 소스코드의 줄번호입니다.&lt;br /&gt;&lt;br /&gt;1. #include &amp;lt;QApplication&amp;gt;&lt;br /&gt;&lt;br /&gt;QApplication이란 Qt의 어플리케이션을 총괄하는 클래스이고, 그 클래스를 이용하기위해서 포함하는 해더파일이 QApplication입니다.&lt;br /&gt;&lt;br /&gt;이처럼 Qt의 해더파일은 클래스이름과 똑같습니다(표준 라이브러리처럼 .h도 안붙습니다)&lt;br /&gt;&lt;br /&gt;또한 (일부 서드파티 클래스를 제외하고)모든 Qt의 클래스는 대문자 Q로 시작합니다.&lt;br /&gt;&lt;br /&gt;2. #include &amp;lt;QLabel&amp;gt;&lt;br /&gt;&lt;br /&gt;Q로 시작하는걸로 봐서 Qt의 클래스라는걸 알수 있겠죠? QLabel이라는 클래스를 이용하기 위해서 QLabel 해더파일을 인클루드합니다.&lt;br /&gt;&lt;br /&gt;QLabel은 위젯(창) 클래스중 하나인데, 이름그대로 라벨처럼 간단한 글자를 나타낼 수 있습니다.&lt;br /&gt;&lt;br /&gt;위젯에 대해서는 따로 설명하게 될것 같습니다.&lt;br /&gt;&lt;br /&gt;일단은 위젯은 창이다라고만 생각하시면 되겠습니다.&lt;br /&gt;&lt;br /&gt;4. main 함수 선언입니다. 처음 C/C++공부하실때 많이 보셨죠?&lt;br /&gt;&lt;br /&gt;개인적으로 큐티가 마음에 드는 이유중 하나가 명시적으로 main함수가 호출된다는 것입니다.&lt;br /&gt;&lt;br /&gt;MFC의 경우는 WinMain함수가 꽁꽁 숨겨져 있는 반면, 큐티에서는 C++의 기본 엔트리 포인트인 main함수를 그대로 이용하기 때문에, 프로그램의 흐름이 더 잘 느껴(?)집니다.&lt;br /&gt;&lt;br /&gt;5. QApplication app(argc, argv);&lt;br /&gt;&lt;br /&gt;QApplication의 인스턴스 app를 생성합니다.&lt;br /&gt;&lt;br /&gt;이것은 마치 MFC의 theApp 인스턴스처럼 어플리케이션하나에서 하나뿐인 QApplication 인스턴스입니다.&lt;br /&gt;&lt;br /&gt;main함수로 넘어온 argc, argv인자를 생성자의 인자로 넘겨주면, 나중에 명령행 인자로 들어온 인자들을 정적함수인 QApplication::arguments()로 가져올수 있게 됩니다.&lt;br /&gt;&lt;br /&gt;어플리케이션의 기본적인 설정이나 디폴트값등도 가지고 있으며, 대부분 스태틱함수로 접근가능하거나 qApp라는 매크로로 이용가능하게 되어있습니다.&lt;br /&gt;&lt;br /&gt;클립보드에 뭔가 넣고 가져오거나 할때도 QApplication을 거쳐야 하며, 윈도우에서는 별로 쓸일이 없지만, 데스크탑을 관리하거나 하는 경우에도 QApplication을 거쳐야 합니다.&lt;br /&gt;&lt;br /&gt;또한, QObject(Qt의 최상위 클래스, MFC의 CObject같은거죠)를 상속받는 모든 클래스는 QApplication의 인스턴스가 생성된 후에만 생성될 수 있다는 것 주의하세요.&lt;br /&gt;&lt;br /&gt;6. &lt;span&gt;QLabel label(&lt;span class=&quot;dp-string&quot;&gt;&quot;Hello, world!&quot;&lt;/span&gt;&lt;span&gt;);&lt;br /&gt;&lt;br /&gt;QLabel 클래스의 인스턴스인 label을 생성합니다.&lt;br /&gt;&lt;br /&gt;생성자로 문자열을 넘기고 있는데, 이 문자열이 QLabel의 초기 text프로퍼티로 세팅됩니다.&lt;br /&gt;&lt;br /&gt;QLabel::text()로 어떤 문자열을 표시하는지 알수 있으며, QLabel::setText()로 문자열을 새로 지정해줄수 있습니다.&lt;br /&gt;&lt;br /&gt;더 자세한건 나중에 각종 위젯을 소개할때 설명하겠습니다.&lt;br /&gt;&lt;br /&gt;7. label.show();&lt;br /&gt;&lt;br /&gt;함수이름대로입니다. label을 show합니다(보여줍니다).&lt;br /&gt;&lt;br /&gt;처음 생성된 상태는 숨겨져 있는 상태이기 때문에, show()를 호출하지 않으면 보이지 않습니다.&lt;br /&gt;&lt;br /&gt;참고로 숨기기는 예상하셨겠지만 hide()입니다.&lt;br /&gt;&lt;br /&gt;8.&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class=&quot;dp-keyword&quot;&gt; return&lt;/span&gt;&lt;span&gt;&amp;nbsp;app.exec();&lt;br /&gt;&lt;br /&gt;QApplication::exec()를 실행하고 반환된 값을 main의 반환값으로 반환합니다.&lt;br /&gt;&lt;br /&gt;QApplication::exec()는 어플리케이션의 이벤트 루프로 들어가는 함수입니다.&lt;br /&gt;&lt;br /&gt;&lt;p id=&quot;more108_0&quot; class=&quot;moreless_fold&quot;&gt;&lt;span style=&quot;cursor: pointer;&quot; onclick=&quot;toggleMoreLess(this, &#039;108_0&#039;,&#039;이벤트루프란?&#039;,&#039;숨기기&#039;); return false;&quot;&gt;이벤트루프란?&lt;/span&gt;&lt;/p&gt;&lt;div id=&quot;content108_0&quot; class=&quot;moreless_content&quot; style=&quot;display: none;&quot;&gt;이벤트 루프는 GUI의 핵심이라고도 할 수 있습니다.&lt;br /&gt;&lt;br /&gt;콘솔 프로그램의 경우는 프로그램이 사용자의 행동을 쉽게 컨트롤 할 수 있습니다.&lt;br /&gt;&lt;br /&gt;사용자로부터뭔가를 입력 받는 방법은 콘솔에 쳐넣는 방법밖에 없으니까요.&lt;br /&gt;&lt;br /&gt;하지만 GUI 프로그램의 경우는 사용자로부터 입력받는 방법이 매우 많습니다.&lt;br /&gt;&lt;br /&gt;예를 들어 버튼을 누른다던가, 단축키를 누른다던가, 더블클릭을 한다던가...버튼을 누르는 것도 버튼 갯수만큼 입력가능한 경우가 생기는 거구요.&lt;br /&gt;&lt;br /&gt;그렇기 때문에 콘솔처럼 정해진 흐름대로 처리하는 건 불가능합니다.&lt;br /&gt;&lt;br /&gt;그래서 일종의 무한루프인 이벤트루프를 돌리면서 사용자가 무언가를 누르거나 마우스를 클릭하면 &#039;이벤트&#039;가 발생하고, 이벤트 루프에서는 이 이벤트가 적절히 처리되도록 적합한 객체로 이벤트를 보내줍니다.&lt;br /&gt;&lt;br /&gt;예를 들어 어떤 버튼을 누르면 이벤트 루프에서 버튼이 눌렸다는 것을 캐치하고, 적합한 이벤트를 생성하여서 이 이벤트를 처리하도록 그 버튼으로 이벤트를 보내주는 것이지요.&lt;br /&gt;&lt;br /&gt;이과정은 프로그램이 종료될때까지 계속 반복됩니다.&lt;br /&gt;&lt;/div&gt;이상으로 소스코드에 대한 설명을 마치겠습니다.&lt;br /&gt;&lt;br /&gt;대강의 흐름을 보자면, QApplication을 생성하고, QLabel을 만들어서 보여준다음 이벤트루프로...가 되겠지요.&lt;br /&gt;&lt;br /&gt;어때요, 참 쉽죠?(여기서 웃으신다면 어렸을때 EBS자주보신 분입니다)&lt;br /&gt;&lt;br /&gt;이번엔 프로그램을 실행하기까지의 과정을 설명하겠습니다.&lt;br /&gt;&lt;br /&gt;$qmake -project&lt;br /&gt;&lt;br /&gt;qmake를 project 생성모드로 실행합니다.&lt;br /&gt;&lt;br /&gt;Qt로 짠 프로그램은 .pro 라는 프로젝트파일로 관리됩니다.&lt;br /&gt;&lt;br /&gt;이 프로젝트 파일은 물론 손으로 만들거나 편집하는 것도 가능하지만, 처음 프로젝트를 시작할 때는 qmake를 -project 옵션을 주고 실행하면, 해당 폴더 내의 소스파일들(*.h, *.cpp, *.hpp 등등)을 자동으로 등록하여 폴더 이름과 같은 이름의 프로젝트 파일을 생성해줍니다.&lt;br /&gt;&lt;br /&gt;저같은 경우는 helloworld라는 폴더안에서 작업했기 때문에 helloworld.pro 라는 파일이 생성되었고, 이 파일을 열어보면 다음과 같이 적혀있습니다.&lt;br /&gt;&lt;br /&gt;######################################################################&lt;br /&gt;# Automatically generated by qmake (2.01a) ? 3? 26 14:01:43 2008&lt;br /&gt;######################################################################&lt;br /&gt;&lt;br /&gt;TEMPLATE = app&lt;br /&gt;TARGET = &lt;br /&gt;DEPENDPATH += .&lt;br /&gt;INCLUDEPATH += .&lt;br /&gt;&lt;br /&gt;# Input&lt;br /&gt;SOURCES += main.cpp&lt;br /&gt;&lt;br /&gt;여기서 중요한건 TEMPLATE, TARGET, SOURCES, 그리고 여기엔 없지만 HEADERS 라는 항목입니다.&lt;br /&gt;&lt;br /&gt;TEMPLATE는 어플리케이션을 만드는 건지, 라이브러리를 만드는 건지를 정하는 부분입니다.&lt;br /&gt;&lt;br /&gt;app라고 적혀있으므로 빌드하면 어플리케이션의 실행파일 나올테고 만약 TEMPLATE의 값이 lib인 경우는 빌드결과 라이브러리 파일(dll이나 so, a등)이 나올 것입니다.&lt;br /&gt;&lt;br /&gt;또, subdir이라는 값도 가질수 있는데, 이경우는 자체적으로는 바이너리를 생성하지 않고, 하위 프로젝트를 관리하게 됩니다.&lt;br /&gt;&lt;br /&gt;다음으로 TARGET은 빌드될 바이너리 파일의 이름을 정합니다.&lt;br /&gt;&lt;br /&gt;기본값으로 아무것도 지정하지 않으면 프로젝트 파일과 같은이름(이경우는 helloworld)의 파일이 생성됩니다.&lt;br /&gt;&lt;br /&gt;SOURCES와 HEADERS는 말그대로 소스파일과 해더파일입니다.&lt;br /&gt;&lt;br /&gt;이경우는 해더파일이 없기 때문에 안나타나있지만, 만약 해더파일을 추가할경우는 SOURCES와 동일하게&lt;br /&gt;&lt;br /&gt;HEADERS += helloworld.h&lt;br /&gt;&lt;br /&gt;와 같이 하면 됩니다.&lt;br /&gt;&lt;br /&gt;이렇게 프로젝트 파일을 한번 생성하면 더이상 qmake -project는 실행하지 않아도 되며, 그 후에 프로젝트 파일을 수정하면 qmake만 한번 돌려주면 됩니다.&lt;br /&gt;&lt;br /&gt;아무런 옵션 없이 qmake를 돌리면 makefile 모드로 실행됩니다.&lt;br /&gt;&lt;br /&gt;이모드에서는 프로젝트파일로 부터 적절한 과정을 거쳐서 Makefile 파일을 생성합니다.&lt;br /&gt;&lt;br /&gt;마지막으로 make 를 실행하면 Makefile을 바탕으로 바이너리가 빌드되고, helloworld라는 실행파일이 생성됩니다.&lt;br /&gt;&lt;br /&gt;이상 기본적인 빌드 방법에 대한 설명이었습니다.&lt;br /&gt;&lt;br /&gt;소스파일을 수정할때 특별히 Qt의존적인 부분이 없다면 make만 한던 더 돌려주면되고, 프로젝트파일에 소스파일을 추가 삭제했거나 프로젝트 파일의 옵션을 수정했다면 qmake를 돌린후에 make를 돌려주어야합니다.&lt;br /&gt;&lt;br /&gt;마지막으로 위젯(widget)에 대해서 설명해볼려고 했는데, 내용이 길어진 관계로 다음 회로 돌려야 겠습니다.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;</description>
			<category>Qt</category>
			<category>Hello World!</category>
			<category>Qt</category>
			<author>(xylosper)</author>
			<guid>http://xylosper.net/108</guid>
			<comments>http://xylosper.net/108#entry108comment</comments>
			<pubDate>Wed, 26 Mar 2008 12:03:05 +0900</pubDate>
		</item>
		<item>
			<title>Qt에 대하여 - 1. Qt를 깔자</title>
			<link>http://xylosper.net/107</link>
			<description>Qt를 쓸려는데, Qt가 깔려있지 않으면 말이 안되겠죠?&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://xylosper.net/106&quot; target=&quot;_blank&quot;&gt;0. Qt 소개&lt;/a&gt;에도 적었듯이, Qt는 QPL을 적용한 상용에디션과, GPL을 적용한 오픈소스에디션이 있습니다.&lt;br /&gt;&lt;br /&gt;앞으로 딱히 말이 없으면 GPL을 따르는 오픈소스에디션의 Qt를 가리킵니다.&lt;br /&gt;&lt;br /&gt;우선, Qt는 크로스플랫폼 라이브러리이기때문에, 사용하려는 운영체제에 맞는 것을 다운 받아야합니다.&lt;br /&gt;&lt;br /&gt;각각의 운영체제별 Qt는 다음 페이지에서 다운받을수 있습니다(주소가 변경될 경우 링크가 깨질 수 있습니다.)&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://trolltech.com/developer/downloads/qt/windows&quot; target=&quot;_blank&quot;&gt;Qt/Windows Opensource Edition&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;http://trolltech.com/developer/downloads/qt/mac&quot; target=&quot;_blank&quot;&gt;Qt/Mac Opensource Edition&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;http://trolltech.com/developer/downloads/qt/x11&quot; target=&quot;_blank&quot;&gt;Qt/X11 Opensource Edition&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Qt/Windows이외에는 모두 소스만 제공됩니다.&lt;br /&gt;&lt;br /&gt;이말은 즉, Qt자체를 우선 컴파일해야 한다는 뜻입니다.&lt;br /&gt;&lt;br /&gt;예를 들자면, MFC를 쓰기위해서 MFC라이브러리 자체를 컴파일하는 셈이지요.&lt;br /&gt;&lt;br /&gt;리눅스 사용자야 컴파일이 익숙한 분들이 많지만, 윈도우 사용자들은 기본이 바이너리배포이기 때문에 컴파일이 익숙하지 못한 분도 많다고 생각됩니다.&lt;br /&gt;&lt;br /&gt;그때문인지 트롤테크에서도 Qt/Windows만 소스와 바이너리를 모두 제공하고 있습니다.&lt;br /&gt;&lt;br /&gt;단, 바이너리의 경우는 MinGW용으로 컴파일된 바이너리이므로, Visual C++로 Qt를 이용하실 분은 소스를 다운 받으셔서 컴파일 하셔야 합니다.&lt;br /&gt;&lt;br /&gt;&lt;p id=&quot;more107_0&quot; class=&quot;moreless_fold&quot;&gt;&lt;span style=&quot;cursor: pointer;&quot; onclick=&quot;toggleMoreLess(this, &#039;107_0&#039;,&#039;MinGW?&#039;,&#039;숨기기&#039;); return false;&quot;&gt;MinGW?&lt;/span&gt;&lt;/p&gt;&lt;div id=&quot;content107_0&quot; class=&quot;moreless_content&quot; style=&quot;display: none;&quot;&gt;MinGW는 GCC(GNU Compiler Collection)에 윈도우용 응용프로그램을 개발하는데 필요한 각종 해더파일이 포함된 프로그램입니다.&lt;br /&gt;&lt;br /&gt;즉 MinGW를 C/C++(그외에도 포트란이나 자바 컴파일러도 들어있습니다)를 컴파일할 수 있는 건 물론, PSDK를 깔지 않아도 Win32API를 이용하여 윈도우 어플리케이션을 만드는게 가능합니다.&lt;br /&gt;&lt;br /&gt;다만 MinGW는 Visual Studio같은 통합개발환경(Integrated Development Environment)가 아닌, 쉽게 말하면 도스용프로그램같이 프롬프트 열고 명령어를 쳐넣어서 이용해야 하기 때문에, Eclipse의 CDT나 Dev-C++등을 이용하면 좋겠지요.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;컴파일해서 설치하는 경우는 어느 운영체제든 대동소이하므로 윈도우에서 컴파일하는 경우를 예로 들어 적겠습니다.&lt;br /&gt;&lt;br /&gt;위 링크에서 소스를 다운 받습니다.&lt;br /&gt;&lt;br /&gt;Qt를 설치할 곳에 압축을 풀어줍니다.&lt;br /&gt;&lt;br /&gt;참고로 Qt를 한번 설치한다음에 폴더이름을 바꾸거나 다른 곳으로 이동하면 경로문제때문에 다시 컴파일해야하는 문제가 발생하므로, 이단계에서 어디에 깔지 정해두는게 좋습니다.&lt;br /&gt;&lt;br /&gt;윈도우의 경우는 시작-&amp;gt;실행에서 cmd라고 치면 명령프롬프트가 나타납니다(맥이라면 터미널, 리눅스라면 콘솔을열고 하면되겠지요).&lt;br /&gt;&lt;br /&gt;Qt의 압축을 푼 디렉토리로 이동하여, configure.exe(맥이나 리눅스라면 ./configure)를 실행하는데요, 여기서 잠깐만 가디려주세요.&lt;br /&gt;&lt;br /&gt;간단히 적자면, configure는 컴파일할때 어떤걸 적용하여 컴파일할지를 정하는 과정입니다.&lt;br /&gt;&lt;br /&gt;예를 들어 디버깅은 빼고 컴파일한다던가, 특정모듈을 뺀다던가 추가한다던가..&lt;br /&gt;&lt;br /&gt;그러므로 이단계에서 한번 confgure.exe --help 를 실행해서 어떤 옵션들이 있고 자기에게 필요한 것이 무엇인가하는 것을확인하여 그 옵션을 적용할 필요가 있습니다.&lt;br /&gt;&lt;br /&gt;예를 들어 제가 윈도우에서 Qt를 컴파일할때는 주로 다음과 같은 옵션을 넣어서 컴파일합니다.&lt;br /&gt;&lt;br /&gt;configure.exe -debug-and-release -qt-sql-sqlite &lt;br /&gt;&lt;br /&gt;이경우는 디버그와 릴리즈를 모두 컴파일하고, sqlite드라이버를 활성화시키는 옵션입니다.&lt;br /&gt;&lt;br /&gt;만약 VisualC++을 이용하실 분이라면 &lt;span class=&quot;ct lh&quot;&gt;-platform win32-msvc.net 같은(버전에따라 다릅니다. 정확한건 configure.exe --help로 확인해보세요) &lt;/span&gt;옵션을 적용하여야 합니다.&lt;br /&gt;&lt;br /&gt;옵션을 결정하여 configure.exe를 실행하면, 우선 라이센스동의를 묻는 말이 나오고, 동의하면 configure 작업이 진행됩니다.&lt;br /&gt;&lt;br /&gt;이게 끝나면 mingw32-make(VC++이라면 nmake)를 한번 쳐주면 주르륵 컴파일하기 시작합니다.&lt;br /&gt;&lt;br /&gt;굉장히 오래(두시간정도? 재본적이 없네요)걸리므로 미리 시간 때울 방법을 마련해두는것도 좋겠습니다.&lt;br /&gt;&lt;br /&gt;이게 끝나면 Qt의 설치도 끝납니다.&lt;br /&gt;&lt;br /&gt;좀더 자세한 설치방법을 알고 싶으신 분은 Qt node의 &lt;a href=&quot;http://qtnode.net/wiki?title=Main_Page&quot; target=&quot;_blank&quot;&gt;Setting up Qt&lt;/a&gt; 부분을 참고하시기 바랍니다.&lt;br /&gt;&lt;br /&gt;만약 IDE에서 Qt를 이용하시는 경우는 직접 Qt경로를 지정해주면 되므로 PATH를 뚫어놓지 않아도 됩니다만, 그렇지 않다면 환경변수의 PATH에 Qt가 설치된경로의 bin폴더(예: C:\Qt\bin)을 추가해놓으시는게 편할 것입니다.&lt;br /&gt;&lt;br /&gt;IDE에서 Qt를 이용할려면 몇가지 선행작업이 필요한데, 이것들은 직접 Qt를 써보기 전엔 왜 그런게 필요한지 이해하기 힘드므로, 당장에 IDE에서 Qt를 이용하는 방법은 설명하지 않겠습니다.&lt;br /&gt;&lt;br /&gt;당분간 명령프롬프트(터미널, 콘솔)에서 직접 명령어를 쳐서 컴파일 하도록 할 것이므로 위에서 얘기한 PATH등록을 해두시길 추천합니다.&lt;br /&gt;&lt;br /&gt;혹시 그래도 난 당장 IDE에서 쓰고 싶다! 라는 분은, &lt;a href=&quot;http://qtnode.net/wiki?title=Qt4_with_Visual_Studio#Maintaining_Visual_Studio_Projects&quot; target=&quot;_blank&quot;&gt;Visual C++에서 프로젝트관리하는 방법&lt;/a&gt;이나 &lt;a href=&quot;http://trolltech.com/developer/downloads/qt/eclipse-integration-download/?searchterm=eclipse%20integration&quot; target=&quot;_blank&quot;&gt;Eclipse CDT Qt Integration&lt;/a&gt;를 알아보시기 바랍니다.&lt;br /&gt;&lt;br /&gt;사실 이런 부분에 대한 설명보다는 빨리 프로그래밍 하는 부분을 설명하고 싶어서 좀 날림으로 적은 감이 있습니다-_-;&lt;br /&gt;&lt;br /&gt;해보시고 잘 안되는 부분 알려주면 좀더 자세히 적도록 하겠습니다.&lt;br /&gt;&lt;br /&gt;다음에는 드디어 Hello World! 입니다.&lt;br /&gt;</description>
			<category>Qt</category>
			<category>Qt</category>
			<category>설치</category>
			<category>컴파일</category>
			<author>(xylosper)</author>
			<guid>http://xylosper.net/107</guid>
			<comments>http://xylosper.net/107#entry107comment</comments>
			<pubDate>Wed, 26 Mar 2008 11:38:51 +0900</pubDate>
		</item>
		<item>
			<title>Qt에 대하여 - 0. Qt 소개</title>
			<link>http://xylosper.net/106</link>
			<description>블로그에 좀 알찬 내용이 없는 듯하여 Qt를 소개하는 글을 좀 적어볼려고 합니다.&lt;br&gt;사실 Qt 강좌 라는 이름으로 시작할까도 생각해봤지만, 저도 잘 모르고 강좌라고 시작해놓고 제대로 마무리도 못하면 하느니 못하단 생각에 그냥 &#039;Qt에 대하여&#039;라는 제목으로 글 몇개 쓸려고 합니다.&lt;br&gt;그럼 시작합니다.&lt;br&gt;&lt;br&gt;0. Qt 소개&lt;br&gt;&lt;br&gt;직업으로 프로그래밍 하시는 분들이 아닌, 그냥 공부하는 학생이나 취미로 프로그래밍하는 분들에게는 아마 Qt라는 이름조차도 생소한 분들이 많을 것이라고 생각합니다.&lt;br&gt;&lt;br&gt;구글에서 Qt로 검색해보면 나오는 것들은 크게 세가지가 있습니다.&lt;br&gt;&lt;br&gt;1. QuickTime Player&lt;br&gt;2. Quiet Time&lt;br&gt;3. Qt&lt;br&gt;&lt;br&gt;바로 3번이 제가 소개할 Qt입니다.&lt;br&gt;&lt;br&gt;&lt;p id=&quot;more106_0&quot; class=&quot;moreless_fold&quot;&gt;&lt;span style=&quot;cursor: pointer;&quot; onclick=&quot;toggleMoreLess(this, &#039;106_0&#039;,&#039;Qt의 이름에 대한 자세한 소개&#039;,&#039;숨기기&#039;); return false;&quot;&gt;Qt의 이름에 대한 자세한 소개&lt;/span&gt;&lt;/p&gt;&lt;div id=&quot;content106_0&quot; class=&quot;moreless_content&quot; style=&quot;display: none;&quot;&gt;위에서 적은 세가지 Qt(QT)를 보면, 1, 2번은 풀어쓴 말이 있는데, 3번은 그냥 Qt라고만 적었습니다.&lt;br&gt;&lt;br&gt;사실 Qt는 LG나 GS처럼 &#039;제작자쪽이 정한 공식적인 약어&#039;가 없습니다.&lt;br&gt;&lt;br&gt;다만, LG가 럭키금성의 줄임말이라고도 알려진 것처럼, 일반적으로 Qt는 Q-Toolkit의 약자로 알려져있습니다.&lt;br&gt;&lt;br&gt;그럼 Q는 무엇인가하면, 처음 Qt가 만들어질 당시, 제작자가 사용하던 Emacs(편집기)의 폰트에서 Q라는 글자가 굉장히 맘에 들어서 Q를 가져다 붙였다는 이야기가 있습니다.&lt;br&gt;&lt;br&gt;하지만 이제는 Qt자체를 하나의 고유명사로서 생각하는게 좋다고 생각합니다.&lt;br&gt;&lt;br&gt;실제로 Qt의 제작사를 가봐도 Qt toolkit이라고 소개되었기 때문에, Qt를 Q-Toolkit으로 생각하면 Q-Toolkit toolkit이라는 말도안되는 단어가 되버립니다.&lt;br&gt;&lt;/div&gt;&lt;br&gt;앞으로 글을 적을때는 매번 한영 전환해서 Qt라고 적기가 불편하므로 Qt와 &#039;큐티&#039;를 병용하겠습니다.&lt;br&gt;&lt;br&gt;큐티는 노르웨이의 &lt;a href=&quot;http://www.trolltech.com&quot; target=&quot;_blank&quot;&gt;트롤테크&lt;/a&gt;라는 회사에서 만든 크로스플랫폼을 위한 C++라이브러리입니다.&lt;br&gt;&lt;br&gt;&lt;p id=&quot;more106_1&quot; class=&quot;moreless_fold&quot;&gt;&lt;span style=&quot;cursor: pointer;&quot; onclick=&quot;toggleMoreLess(this, &#039;106_1&#039;,&#039;크로스플랫폼이란?&#039;,&#039;숨기기&#039;); return false;&quot;&gt;크로스플랫폼이란?&lt;/span&gt;&lt;/p&gt;&lt;div id=&quot;content106_1&quot; class=&quot;moreless_content&quot; style=&quot;display: none;&quot;&gt;크로스플랫폼이란 말을, 프로그래밍을 하시는 분이라면 한번쯤은 들어보셨을 것 같습니다. &lt;br&gt;&lt;br&gt;사실 저도 그냥 느낌상으로만 알고 있고 정확한 정의는 잘 모르므로, 그냥 제가 아는대로만 적어보겠습니다.&lt;br&gt;&lt;br&gt;&#039;프로그램이 실행되는 환경&#039;을 플랫폼이라고 합니다.&lt;br&gt;&lt;br&gt;이는 비단 아키텍쳐(인텔/AMD의 x86등)뿐만 아니라, OS도 해당됩니다.&lt;br&gt;&lt;br&gt;맥북같은 경우 윈도우와 같은 x86 32bit환경이지만 OSX라는 운영체제가 탑재되어있고, 이경우 윈도우와 OS는 서로 다른 플랫폼입니다.&lt;br&gt;&lt;br&gt;또, 같은 윈도우위에서도 Java로 짜인 프로그램은 자바런타임환경(JRE)의 가상머신에서 돌아가고, 닷넷프로그램은 닷넷프레임워크위에서 돌아가므로 이들도 또한 다른 플랫폼이라 할 수 있습니다.&lt;br&gt;&lt;br&gt;하지만, JRE와 닷넷프레임워크는 언어자체가 다르므로 한 언어의 라이브러리가 크로스플랫폼을 지원한다고하면, 보통 OS수준의 플랫폼이라고 생각하면 됩니다.&lt;br&gt;&lt;br&gt;그럼 크로스플랫폼이 무엇인가하면, 간단하게 말하자면, 복수의 플랫폼을 지원한다는 뜻입니다.&lt;br&gt;&lt;br&gt;예를 들어, 유명한 MS의 MFC같은 경우는 윈도우에서만 컴파일되고 실행될 수 있습니다.&lt;br&gt;&lt;br&gt;이런 경우 MFC는 단일 플랫폼 라이브러리인 것입니다.&lt;br&gt;&lt;br&gt;Qt의 경우는 윈도우뿐만아니라 맥, 리눅스와 각종 메이저한 유닉스에서 컴파일되고 실행될 수 있고, 이것을 크로스플랫폼이라고 합니다.&lt;br&gt;&lt;br&gt;Java의 경우도 적절하게 구현된 JVM만 있다면 어떤 OS에서든지 실행되므로 크로스플랫폼이라고 할수 있습니다.&lt;br&gt;&lt;br&gt;단, Java의 경우는 컴파일된 결과가 기계어가 아닌 바이트코드이기 때문에, 컴파일된 결과물을 가지고도 다른 플랫폼에서 실행하는 것이 가능하지만, Qt의 경우는 C++을 이용하고 있고, 네이티브하게 컴파일되기 때문에, 컴파일된 결과물은 다른 플랫폼에서 실행할 수 없고, 소스차원에서의 크로스플랫폼을 지원합니다.&lt;br&gt;&lt;/div&gt;&lt;br&gt;직업으로 프로그래밍하는 분이 아닌, 취미로하거나 공부/연구에 필요해서 프로그래밍을 하시는 분중에, C++을 이용하여 GUI프로그램을 만든다고 하면, 대부분이 Visual C++의 MFC를 이용해서 프로그래밍을 하고 있지 않나, 라고 생각합니다.&lt;br&gt;&lt;br&gt;그런데, 정품이용자분들께는 죄송하지만, 이런 분들중에 정말로 Visual C++을 구입해서 사용하시는 분들이 몇이나 되실지 궁금합니다.&lt;br&gt;&lt;br&gt;Visual C++자체는 익스프레스버젼도 있고해서 정품윈도우를 이용하시는 분은 공짜로 이용가능하지만, MFC는 그렇지가 않습니다.&lt;br&gt;&lt;br&gt;MFC는 상용 Visual Studio를 구입해야 이용할수 있으며, 절대로 공짜도 아니고 그냥 쉽게 프로그래밍 공부하기위해서 사볼만한 가격도 아닙니다.&lt;br&gt;&lt;br&gt;하지만 Qt는 듀얼라이센스를 적용하여, 일반 사용자들은 공짜로 이용할 수가 있습니다.(자세한건 글 마지막에 라이센스에 대한 부분에 적겠습니다.)&lt;br&gt;&lt;br&gt;사실 저도 처음엔 MFC로 프로그램을 만들었었고, C++로 윈도우에서 뭐만들려면 Win32API직접 쓰는거 빼곤 그거밖에 없는 줄 알았습니다.&lt;br&gt;&lt;br&gt;하지만 큐티를 알게 된 후에는 왜 처음부터 이걸 안썼을까, 라는 후회가 들정도로 잘 짜여진 라이브러리입니다.&lt;br&gt;&lt;br&gt;그럼 큐티로 뭘 할수 있냐? 고 물어보시면, 대답은 &#039;다&#039;입니다.&lt;br&gt;&lt;br&gt;처음에도 적었듯이 저도 전문가가 아니기 때문에 확답은 하기 힘들지만, MFC로 할수 있는건 당연히 다 할수 있고, 그이상의 것도 훨씬 쉽게 할수 있다고 생각합니다.&lt;br&gt;&lt;br&gt;게다가, 예를 들어 윈도우에서 프로그램을 만드는데, 이부분은 정말 Win32API를 쓰지 않으면 구현이 불가능한 부분이라고 생각되면, 그부분은 그냥 직접 windows.h를 인클루드하고 가져다 쓰면되기 때문에, 딱히 제한될만한 것도 없다고 생각됩니다.&lt;br&gt;&lt;br&gt;다만 이런경우는 이식성이 없는 코드가 되겠지요.&lt;br&gt;&lt;br&gt;그럼, 큐티의 장점을 몇가지 적어보면...&lt;br&gt;&lt;br&gt;1) 크로스 플랫폼&lt;br&gt;&lt;br&gt;일부 플랫폼 의존적인 함수를 쓰지 않는다면, 정말 윈도우에서 짠 소스 그대로 리눅스로 가져가서 컴파일해도 똑같은 결과가 나옵니다.&lt;br&gt;&lt;br&gt;덕분에 예를 들어, 리눅스 어플을 만들어야 하는데, 리눅스에선 익숙한 편집기도 없다, 이럴땐 그냥 윈도우에서 쓰던 편집기로 작성하고, 디버깅도 다 윈도우에서 한다음에, 리눅스에선 컴파일만 하고 간단히 테스트만 해보는 식으로도 어플리케이션을 만드는게 가능합니다.&lt;br&gt;&lt;br&gt;2) 잘 짜여진 객체지향 라이브러리&lt;br&gt;&lt;br&gt;사실 전 그냥 취미로 하기 때문에 어째서 Qt가 MFC보다 더 객체지향적인지는 딱 꼬집어 설명할 실력이 못됩니다만, 그냥 써봐도 MFC에서는 난해했던것이 Qt에서는 간단하고 명료한 느낌이 많이 들며, 일반적으로도 Qt가 MFC보다 잘 짜여져있다고 많이들 하시더군요.&lt;br&gt;&lt;a href=&quot;http://phil.freehackers.org/kde/qt-vs-mfc.html&quot; target=&quot;_blank&quot;&gt;Qt와 MFC를 비교한(비교라기보다는 MFC에 비해 Qt가 뛰어난 것들을 적어놓은) 글&lt;/a&gt;을 한번 읽어보시면 도움이 될지도 모르겠습니다.&lt;br&gt;&lt;br&gt;3) 보다 직관적인 GUI 디자인&lt;br&gt;&lt;br&gt;처음엔 MFC에서 다이얼로그 만들고 거기에 콤보박스나 라디오버튼 같은거 메뉴에서 끌어다가 붙이기만 해도 창이 완성되는 걸 보고 참 MFC는 대단하구나...라고 생각하곤 했습니다.&lt;br&gt;&lt;br&gt;하지만 Qt로 그런 창을 디자인해보면 MFC의 디자인방식은 정말이지 못해먹을 짓입니다.&lt;br&gt;&lt;br&gt;Qt에서도 Qt Designer 라는 프로그램을 이용하여 쉽게 창을 디자인 할수 있습니다.&lt;br&gt;&lt;br&gt;MFC처럼 각종 컨트롤(위젯)들을 끌어다 놓기만 해도 되는건 물론이거니와, 레이아웃시스템 덕분에 일일이 줄맞추거나 창이 리사이즈될때마다 크기나 위치를 일일이 지정해줄 필요가 없습니다.&lt;br&gt;&lt;br&gt;게다가 간단한 시그널/슬롯(Qt의 이벤트 처리 방식중 하나입니다. 이번 글은 아니지만, 나중에 자세히 적을 것입니다.)지정도 가능합니다.&lt;br&gt;&lt;br&gt;물론 디자이너를 쓰지 않고 직접 코드로 짜는 것도 가능하며, 사실 디자이너로 디자인된 파일도 변환기를 거쳐서 최종적으로는 C++코드로 변환되어서 컴파일됩니다.&lt;br&gt;&lt;br&gt;그렇기 때문에, 디자이너로 생성된 컨트롤들도, MFC에서는 리소스로 관리하여 변수와 연결해줘야 하는 반면에, 그대로 하나의 객체로서 다룰수 있어 더 직관적입니다.&lt;br&gt;&lt;br&gt;4) 간편한 리소스관리&lt;br&gt;&lt;br&gt;프로그램에서 아이콘을 가져다 써야하거나, 소리를 내야하는 경우, 외부파일을 가져다 쓰는 경우도 있지만, 이런 경우는 매번 배포할때마다 같이 챙겨서 배포해야 하기때문에, 실행파일 자체에 집어넣고 가져다 쓰는 경우가 많습니다.&lt;br&gt;&lt;br&gt;큐티에서는 간단하게 리소스로 가져다쓸 파일 목록만 작성해주면, 알아서 컴파일시에 포함시켜주며, 프로그램내에서 그 파일들을 가져다 쓸 땐, 로컬파일과 거의 동일하게 이용가능합니다.&lt;br&gt;&lt;br&gt;5) 다국어지원 및 국제화에 강하다&lt;br&gt;&lt;br&gt;Qt는 QString이라는 자체적으로 구현한 문자열 클래스를 이용합니다.&lt;br&gt;&lt;br&gt;이 QString은 내부적으로 유니코드로 문자열을 처리하기 때문에 예를들어 일본어와 한국어를 동시에 다루어야 하는 프로그램등을 인코딩문제때문에 골머리 썩힐 필요도 없습니다.&lt;br&gt;&lt;br&gt;게다가 프로그램을 다른 언어로 번역해야 할 경우, 소스코드에 적힌 문자열들 중에 번역이 필요한 문자열들만 골라서 따로 표시해주고, 이것들을 번역하여 프로그램 실행시에 번역된 파일을 선택함으로서 쉽게 여러 언어를 지원하는게 가능합니다.&lt;br&gt;&lt;br&gt;6) 풍부한 문서와 예제&lt;br&gt;&lt;br&gt;MFC를 이용함에 있어서 MSDN만큼이나 큰 조력자도 없을 것입니다.&lt;br&gt;&lt;br&gt;Qt에는 Qt Assistant 라는 도움말이 있습니다.&lt;br&gt;&lt;br&gt;이것은 Qt의 모든 클래스와 각종 모듈 및 기능, 예제에 대한 설명이 포함되어있으며, 사실 웹상에서 질문되는 Qt에 대한 질문중 반이상은 Assistant를 찾아보면 이미 답이나 해결책이 나와있는 것들입니다.&lt;br&gt;&lt;br&gt;또한, Qt는 많은 예제를 포함하고 있습니다.&lt;br&gt;&lt;br&gt;설명만으론 어떻게 써야할지 막막한 경우 대부분 예제를 통해서 사용법을 익히는게 가능하며, 예제에 대한 해설또한 assistant를 통해서 제공됩니다.&lt;br&gt;&lt;br&gt;앞으로 종종 &#039;자세한건 assistant를 참고하세요&#039;라는 말을 하게될 것입니다.&lt;br&gt;&lt;br&gt;7) 강력한 모듈들&lt;br&gt;&lt;br&gt;Qt는 단순한 GUI용 라이브러리가 아닙니다.&lt;br&gt;&lt;br&gt;어플리케이션을 개발하는데 필요한 컴포넌트들의 총체라고도 할 수 있을만큼 다양한 모듈들을 내장하고 있습니다.&lt;br&gt;&lt;br&gt;간단히 이름만봐도 뭐하는 건지 알만 모듈 몇가지만 적어보면,&lt;br&gt;&lt;br&gt;QtSql, QtXml, QtOpenGL, QtNetwork...&lt;br&gt;&lt;br&gt;이외에도 2008년 2사분기 말에 릴리즈될 예정인 Qt4.4에는 멀티미디어를 위한 Phonon과 Webkit이 추가됩니다.&lt;br&gt;&lt;br&gt;모듈들에 대해선 자세히 설명할 기회가 다음에 또 있을지도 모르겠습니다.&lt;br&gt;&lt;br&gt;8) Generic Containers&lt;br&gt;&lt;br&gt;C++을 유용성을 논할때 STL을 빼놓고는 이야기할 수 없을 것입니다.&lt;br&gt;&lt;br&gt;이 STL에 대응하여, 종종 QTL(Qt Template Library)라고 불리는 Generic Container가 존재합니다.&lt;br&gt;&lt;br&gt;물론 STL을 그대로 써도 좋습니다만, 예를 들어 STL에는 포함되어있지 않는 해쉬테이블등이 필요한 경우라면 Qt의 Generic Containers중 하나인 QHash를 이용하면 되겠지요.&lt;br&gt;&lt;br&gt;또, 이것들은 STL스타일의 반복자나 함수들도 대부분 존재하기 때문에, STL에 익숙한 분도 쉽게 이용할 수 있으며, 특히나 편리한 것은 Java스타일의 반복자들입니다.&lt;br&gt;&lt;br&gt;이또한 따로 자세히 설명할 기회가 있을 듯합니다.&lt;br&gt;&lt;br&gt;이상 큐티의 장점으로서 8가지를 언급했습니디만, 사실 이건 당장에 생각나는 것들만 적은 것이므로, 앞으로 업데이트될 수도 있습니다.&lt;br&gt;&lt;br&gt;그럼 무조건 큐티가 좋냐, 하면 단점도 있습니다.&lt;br&gt;&lt;br&gt;1) 컴파일 시간이 길다&lt;br&gt;&lt;br&gt;큐티는 이식성도 떨어지고 성능에도 문제가 있는 RTTI대신에 Meta-Object System을 이용합니다.&lt;br&gt;&lt;br&gt;단순히 타입정보를 알기위한 것 뿐만 아니라 이벤트처리나 프로퍼티처리를 위해서도 이용되는 것입니다만, 이것을 이용하기 위해서 일단 소스파일을 moc(Meta-Object Compiler)에 통과시켜서 moc파일을 생성한후에 컴파일하기 때문에 일반적인 컴파일 시간보다 시간이 오래걸립니다.&lt;br&gt;&lt;br&gt;2) 용량이 크다 &lt;br&gt;&lt;br&gt;라이브러리가 방대한 만큼 큐티자체의 용량도 크며 빌드된 바이너리의 용량도 MFC에 비해 약간 큽니다.&lt;br&gt;&lt;br&gt;이정도의 단점이 생각납니다만, 혹시 경험자분들중에 다른 단점이라고 생각되는 것이 있으시면 알려주시기 바랍니다. 추가하도록 하겠습니다.&lt;br&gt;&lt;br&gt;마지막으로 라이센스에 대한 이야기를 하려고합니다.&lt;br&gt;&lt;br&gt;Qt는 4.4.x까지는 QPL/GPL의 듀얼 라이센스 정책으로, 소스비공개의 상용 프로그램을 개발하기위해서는 라이센스비용을지불하고 이용해야 했습니다.&lt;br&gt;&lt;br&gt;하지만 Qt4.5부터는 LPGL이 추가되었기 때문에, Qt4.5이상을 이용할 경우 라이센스 비용을 지불하지 않더라도 소스를 공개할필요가 없어졌습니다.&lt;br&gt;물론 기존과 동일하게 GPL을 이용하는 것도 가능합니다.&lt;br&gt;&lt;br&gt;4.4까지는 무료이용을 위해선 소스공개를 해야한다는 제약에 꺼려지는 경우도있었지만, 이제는 LGPL이 정한 내용에 따르기만 한다면(수정부분 소스공개) 정말 자유롭게 이용할 수있게 되었습니다.&lt;br&gt;</description>
			<category>Qt</category>
			<category>C++</category>
			<category>MFC</category>
			<category>Qt</category>
			<author>(xylosper)</author>
			<guid>http://xylosper.net/106</guid>
			<comments>http://xylosper.net/106#entry106comment</comments>
			<pubDate>Tue, 25 Mar 2008 22:59:20 +0900</pubDate>
		</item>
	</channel>
</rss>
