· KLDP.org · KLDP.net · KLDP Wiki · KLDP BBS ·
QT Programming Create New Widget

3. 기존의 Widget으로부터 새로운 기능의 Widget 생성 :



Qt에서 제공되는 기본 widget들은 강력하나 그러한 widget들에 추가적인 기능을 삽입하여 확장하거나 여러 기본적인 widget을 조합하여 새로운 의미와 기능을 창출해야 하는 경우도 있습니다. 이번에는 기존의 widget을 상속받아 기능을 확장해서 새로운 widget을 생성하는 예를 살펴보도록 하겠습니다. QFileDialog를 상속받은 클래스를 정의하고 그 내부에 파일의 내용을 텍스트로 보여주는 다이얼로그박스를 추가해보도록 하겠습니다.


s31_2.jpg
[JPG image (79.11 KB)]



구현하려는 기능은 다음과 같습니다.

1.파일다이얼로그에서 파일을 클릭할 경우 발생하는 경우 선택된 파일의 데이터를 읽어 파일 다이얼로그의 위나 아래에 텍스트창을 생성하고 그 안에 출력합니다. 2.파일다이얼로그의 위치에 따라 텍스트창의 위치를 파일다이얼로그의 위나 아래로 조정합니다.


해당 기능을 구현하기 위해 QFileDialog로부터 상속받는 TextPreviewFileDialog 클래스를 정의합니다.




//-----------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
// textpreviewfiledialog.h : TextPreviewFileDialog 클래스 선언부 
//-----------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------

#ifndef _textpreviewfiledialog_h_
#define _textpreviewfiledialog_h_

#include < qdialog.h >
#include < qfiledialog.h >
#include < qtextedit.h >

class TextPreviewFileDialog : public QFileDialog
{
	Q_OBJECT
public :
	//-----------------------------------------------------------------------------------------------------
	// member variables : 	
	//-----------------------------------------------------------------------------------------------------
	QDialog* m_pPreviewPopup; 	//Preview Dialog
	QTextEdit* m_pTextEdit;	//Preview Dialog에 넣을 TextEdit 컨트롤
	
	
	//-----------------------------------------------------------------------------------------------------
	// member functions : 
	//-----------------------------------------------------------------------------------------------------	
	//constructor/destructor
	TextPreviewFileDialog(QWidget* pQParentWidget); //default constructor 
	~TextPreviewFileDialog();	
	
	//event handlers : 
	void moveEvent ( QMoveEvent * pMoveEvent);
	void resizeEvent ( QResizeEvent * pResizeEvent );
	
	//custom logic unit : 
	void reform_preview_dialog();

public slots :
	void handler_filehighlighted(const QString& text);
};

#endif
//-----------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------




Qt Designer에서는 Signal/Slot의 Connection을 직접 생성해주지만 직접 widget을 만들 때에는 connect() 에 의해 연결한 Slot함수를 직접 선언해주어야 합니다. Slot함수를 선언하기 위해서는

1. 클래스 처음에 Q_OBJECT 라는 텍스트를 명시합니다. 2. slot함수 선언 전에 slots 지시자를 명시합니다.( ex) public slots: )

이런 수순을 거쳐 선언하면 됩니다. slot함수의 구현은 일반적인 멤버 함수의 구현과 차이가 없습니다.





//-----------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
// textpreviewfiledialog.cpp : TextPreviewFileDialog 클래스 구현부 
//-----------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------

#include "textpreviewfiledialog.h"
#include < qtextcodec.h >
#include < qmessagebox.h >
#include < qdesktopwidget.h >
#include < qrect.h >
#include < qapplication.h >


TextPreviewFileDialog::TextPreviewFileDialog(QWidget* pQParentWidget)
{
	//변수 초기화
	m_pPreviewPopup = NULL;
	m_pTextEdit = NULL;
	
	//Signal/Slot연결( 파일 다이얼로그에서 파일 항목을 선택할때마다 함수를 호출하도록 설정한다.)
	connect( this ,
		 SIGNAL( fileHighlighted(const QString&) ),
		 this , 
		 SLOT(handler_filehighlighted(const QString&) ) );		
}

//-------------------------------------------------------------------------------------------------------------------
// void handler_filehighlighted(const QString& text)  : 
// 파일다이얼로그에서 파일 항목을 클릭할때마다 호출되는 Slot함수이다. 
//-------------------------------------------------------------------------------------------------------------------
void TextPreviewFileDialog::handler_filehighlighted(const QString& text)
{
	//-------------------------------------------------------------------------------------------------------------------
	//local variables : 
	//-------------------------------------------------------------------------------------------------------------------	
	QFile qfile;
	QByteArray qByteArray;
	QTextCodec* pQTC = NULL;	
	//-------------------------------------------------------------------------------------------------------------------
	
	if( this->selectedFile()=="" )
	{
		if(m_pPreviewPopup != NULL )
		{
			m_pPreviewPopup->hide();
		}
		return;
	}	
	
	pQTC = QTextCodec::codecForName("utf8");
	if( pQTC == NULL )
	{
		return;
	}	
	
	
	qfile.setName( this->selectedFile() );
	if( qfile.open(IO_ReadOnly) ) //파일을 읽기 전용으로 연다.
	{		
		/*
		 * 이 구현에서는 통째로 다 읽어서 붙여넣었지만, 
		 * 미리 볼 양을 적절히 조절해서 사용할 수 있다.
		 */
		
		qByteArray = qfile.readAll();	//파일을 읽어들인다. 			
		if( qByteArray.count() > 0 )
		{
			if( m_pPreviewPopup == NULL )
			{
				m_pPreviewPopup = new QDialog( this );
				m_pTextEdit = new QTextEdit( m_pPreviewPopup );			
			}
			reform_preview_dialog();
			m_pTextEdit->setText( pQTC->toUnicode( qByteArray , qByteArray.count() ) );
			m_pPreviewPopup->setCaption( this->selectedFile() );
			m_pPreviewPopup->showNormal();			
		}
		else
		{
			m_pTextEdit->setText("");
		}
	}	
	return;
}

void TextPreviewFileDialog::moveEvent ( QMoveEvent * pMoveEvent)
{
	reform_preview_dialog();
}

//-------------------------------------------------------------------------------------------------------------------
//void reform_preview_dialog() :
//파일다이얼로그에 맞추어 Preview 다이얼로그를 생성
//-------------------------------------------------------------------------------------------------------------------
void TextPreviewFileDialog::reform_preview_dialog()
{	
	QRect rect;
	QDesktopWidget* pMainDesktop = QApplication::desktop(); //데스크탑 화면을 얻는다.
	
	if( m_pPreviewPopup == NULL )
		return;
	
	rect = pMainDesktop->screenGeometry(); //화면 사이즈를 얻는다.
	
	
	/*
	 * Qt Assistance에 의하면 QWidget::frameGeometry()로 프레임을 포함한 전체 윈도우 사이즈를
	 * 구할 수 있는 것으로 되어 있지만 실제로는 frameGeometry()와 geometry()가 동일한 값의 QRect
	 * 객체를 반환한다.
	 *
	 * 여기에서는 특정 상수를 가감하는 것으로 임시로 구현하였다.
	 */
	
	if( (rect.height() - ( this->y()+this->frameGeometry().height() )) < this->frameGeometry().height() )
	{
		//위로 preview화면을 출력한다.

		m_pPreviewPopup->setGeometry( this->x() , 
			      this->y() - this->frameGeometry().height() - 30 , 
			      this->width(),
			      this->height() );
	}
	else
	{
		//아래로 preview화면을 출력한다.
		
		m_pPreviewPopup->setGeometry( this->x() , 
			      this->y() + this->frameGeometry().height() + 30 , 
			      this->width(),
			      this->height() );
	}
	
	//내부 텍스트박스의 사이즈를 재조정한다.
	m_pTextEdit->setGeometry(0,0,m_pPreviewPopup->width() , m_pPreviewPopup->height() );	
}

void TextPreviewFileDialog::resizeEvent ( QResizeEvent * pResizeEvent )
{
	reform_preview_dialog();
}

TextPreviewFileDialog::~TextPreviewFileDialog()
{
	 
}

//-----------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------



미리 정의된 이벤트에 대한 핸들러는 virtual로 정의되어 있는 이벤트핸들러 함수를 재정의하는 것만으로도 간단하게 작성할 수 있습니다. 위 코드의 moveEvent() 함수가 이벤트 발생시에 호출됩니다. 미리 정의되어 있는 이벤트는 Qt Assistance에서 확인할 수 있습니다. 이벤트 핸들러의 이름은 대개 XXXevent()로 정의되어 있습니다.

생성자에서 connect를 이용해서 QFileDialog의 fileHighlighted() signal을 handler_filehighlighted()에 연결하는 것을 확인하세요.

사용하기 위해서는 modal dialog생성하듯이 사용하면 됩니다.



void Form_Main::pushButton_show_clicked()
{
	TextPreviewFileDialog dlg(this);
	dlg.exec();
}




결과화면

s32_1.jpg
[JPG image (53.01 KB)]






sponsored by andamiro
sponsored by cdnetworks
sponsored by HP

Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2007-11-11 18:08:10
Processing time 0.0118 sec