이번에는 메뉴를 작성하고 툴바를 생성하는 방법을 살펴보겠습니다.
texteditor.tar.gz

예제 소스 코드

일단 '새 파일'메뉴를 만들어 봅시다.

mainwindow.h
[code]
...
class MainWindow : public QMainWindow {
...
private slots:
    void newFile();
private:
...
};
[/code]
해더파일에는 위와 같이 '새 파일'메뉴가 실행되었을때 새파일을 만들어주기 위해 호출할 슬롯함수 newFIle()을 선언해두었습니다(슬롯으로 선언한 이유는 곧 나옵니다).

mainwindow.cpp
[code]
#include "mainwindow.h"
#include <QTextEdit>
#include <QMenuBar>
#include <QToolBar>

struct MainWindow::Data {
    QTextEdit *edit;
    QAction *newFileAction;
};

MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent), d(new Data) {
    d->edit = new QTextEdit(this);
    setCentralWidget(d->edit);
   
    QMenuBar *mb = menuBar();
   
    QMenu *fileMenu = mb->addMenu(trUtf8("파일(&F)"));
    d->newFileAction = fileMenu->addAction(trUtf8("새 파일(&N)"));
    d->newFileAction->setShortcut(QKeySequence("Ctrl+N"));
   
    QToolBar *fileBar = addToolBar(trUtf8("파일 도구막대"));
    fileBar->addAction(d->newFileAction);
   
    connect(d->newFileAction, SIGNAL(triggered()), this, SLOT(newFile()));
}

MainWindow::~MainWindow() {
    delete d;
}

void MainWindow::newFile() {
    d->edit->clear();
}
[/code]
mainwindow.cpp 가 변한 점을 하나씩 집어가도록 하겠습니다.

우선 해더파일이 늘었는데, 메뉴바 클래스인 QMenuBar나 툴바 클래스인 QToolBar를 이용하기위해서포함시킨 것들입니다.
그외에도 QMenu나 QAction등이 필요합니다만, QMenuBar안에 이미 포함되어있기 때문에 생략했습니다.

데이터클래스에 QAction *newFileAction 이라는 멤버가 추가되었습니다.
여기서 한가지 분명히 해두어야 할게 있습니다.
우리가 보통 '메뉴'라고 하면, 예를 들어, "'파일'메뉴의 '새 파일'메뉴"라고 하듯이, 목록(파일 메뉴)과 그 아래의 항목(새파일 메뉴)을 모두 메뉴라고 칭합니다.
Qt에서는, 그러한 목록은 QMenu 클래스로, 그리고 하위 항목들은 QAction 클래스로 구현합니다.
따라서 앞으로 메뉴 라고 하면 QMenu 클래스로 구현되는 목록을, 액션이라고 하면 메뉴의 하위 항목을 지칭하는 것으로 정하겠습니다.

그런데, 예를 들어 파일 메뉴의 하위항목으로 최근 파일 목록 같은 메뉴가 들어가 있어서, 메뉴가 메뉴를 포함하고 있는 경우도 많습니다.
그래서, 메뉴 자체도 거기에 대응하는 하나의 액션을 가지고 있고, 위젯으로서의 속성외의 것들은 액션으로 관리됩니다.
메뉴에 대응되는 액션은, QMenu::menuAction()으로 얻을수 있습니다.
반대로, 액션의 경우, 메뉴에 대응된 액션이라면, QAction::menu()가 널이 아닌 포인터를 반환합니다.
예를 들어, 메뉴항목을 숨기고 싶다면 QMenu::hide()가 아니라, 그 메뉴에 대응되는 액선의, QAction::setVisible(false)를 이용해야합니다.

newFileAction은 새파일을 만들기 위한 액션입니다. 액션의 사용법은 생성자를 살펴볼때 설명하겠습니다.

이제 생성자를 살펴보겠습니다.

QMenuBar *mb = menuBar();

이 한줄이 메뉴바를 생성하는 한줄입니다. 메뉴바는 QMainWindow::menuBar()가 처음으로 호출 될때 생성되며, 그이후로 menuBar()함수가 호출되면 이미 생성된 메뉴바에 대한 포인터를 반환합니다.
이제 메뉴바에 메뉴를 추가합시다.

QMenu *fileMenu = mb->addMenu(trUtf8("파일(&F)"));

trUtf8()가 뭔지 기억이 안나신다면 4편을 참고하세요.

QMenu는, 위에서 설명했듯이 메뉴 목록을 나타내기위한 클래스로, 실제로 메뉴바에서 클릭했을때 표시되는 '창'이기때문에, QMenu도 역시 QWidget을 상속받아서 구현되어있습니다.

QMenuBar::addMenu()함수는 다음의 세가지 형태로 오버로드되어있습니다.

1. QAction *addMenu(QMenu *menu)
이미 존재하는 QMenu 인스턴스를 메뉴바에 추가할때 이용합니다.
여기서 반환되는 QAction*은, menu 메뉴에 대응되는 액션에 대한 포인터로, menu->menuAction()과 동일한 값입니다.

2. QMenu *addMenu(const QString &title)
메뉴바에 title이란 타이틀의 메뉴를 추가하여, 그 메뉴를 가리키는 포인터를 반환합니다.
타이틀은 메뉴바에서 표시되는 메뉴의 이름이며, 메뉴가 다른 메뉴에 포함되는 경우에는 해당 메뉴의 항목에 표시되는 이름입니다.
참고로, 이 항목이름도 메뉴에 대응되는 액션에 의해서 관리됩니다.

3. QMenu *addMenu(const QIcon &icon, const QString &title)
icon으로 지정된 아이콘을 설정해준다는 점 이외에는 2번과 다를바없습니다.
메뉴바에 추가된 메뉴에 대해서는 아이콘을 표시하지 않기 때문에 의미가 없습니다만, 메뉴의 하위 항목으로 메뉴가 들어가있는 경우에 타이틀 옆에 아이콘을 표시해줍니다.
타이틀과 마찬가지로, 메뉴에 대응되는 액션에의해 관리됩니다.

여기서는 2번을 이용하여, '파일'이라는 타이틀의 메뉴를 생성하였습니다.
참고로, (&F) 라는 것은, 이미 GUI프로그래밍 경험이 있으신분이라면 설명하지 않아도 아실 듯한데요, 보통 알트키와 함께 눌렀을떄 메뉴나 액션이 실행되는 단축키(정확한 명칭은 모르겠네요)입니다.
이경우 알트+F를 누르면 파일메뉴목록이 표시되는 것이죠.

d->newFileAction = fileMenu->addAction(trUtf8("새 파일(&N)"));
이제 메뉴를 생성하였으니, 하위 항목으로 액션을 생성합니다.
일반적으로 모든 위젯은 액션 리스트를 가지고 있고, 여기에 액션을 추가하기위해서는 QWidget::addAction(QAction *)함수를 이용합니다만, QMenu클래스의 경우는 편의를 몇가지 오버로드된 addAction()함수를 제공합니다.
위 함수는 QAction *QMenu::addAction(const Qstring &text)의 원형을 가지고 있고, text라는 이름으로 표시되는 QAction인스턴스를 생성하여, 그 포인터를 반환해줍니다.
이걸로 파일 메뉴에 새 파일 액션이 생성되었습니다.

d->newFileAction->setShortcut(QKeySequence("Ctrl+N"));
액션의 단축키(shortcut)를 지정해줍니다. 단축키는 필수사항은 아니지만 자주이용하는 액션이라면 단축키가 있는 것이 편리하겠죠. 단축키는 QKeySequence 클래스를 이용하여 지정할 수 있습니다.
QKeySequence를 생성하는 데에는 몇가지 방법이 있는데, 다음 두가지가 가장 자주 이용됩니다.
QKeySequence(const QString &key);
QKeySequence(int k1, int k2 = 0, int k3 = 0, int k4 = 0);

이경우 전자를 이용하였는데, 바로 키를 문자열로 적는 방법입니다. 간단하죠? 후자의 경우는, 키코드를 입력하는 방법입니다. 후자를 이용하면, QKeySequence(Qt::CTRL + Qt::Key_N)과 같이 적을수 있습니다.


QToolBar *fileBar = addToolBar(trUtf8("파일 도구막대"));
QMainWindow::addToolBar()함수는 주어진 이름으로 툴바를 추가해줍니다. 툴바도 하나의 위젯이며 도킹윈도우처럼 자유롭게 메인윈도우에 붙였다 땔수 있고, 떨어져있을 경우 여기서 지정된 창이름으로 표시되고, 툴바에서 오른쪽 마우스 버튼을 클릭했을때 나타나는 툴바 목록에도 같은 이름으로 표시됩니다.

fileBar->addAction(d->newFileAction);
앞에서 설명했듯이, 모든 위젯은 자체의 액션 리스트를 가지고 있습니다. QToolBar클래스의 경우, 액션리스트를 툴바의 형태로 표시해줍니다. QToolBar클래스도 QMenu클래스와 마찬가지로 편의를 위해 다양한 형태로 오버로드된 addAction()함수를 제공하지만, 이경우는 이미 생성되어있는 액션을 추가하는 것이므로, addAction(QAction*)을 이용합니다.
이것으로 파일 툴바를 추가하고 거기에 새 파일 액션이 추가되었습니다.

connect(d->newFileAction, SIGNAL(triggered()), this, SLOT(newFile()));
QAction클래스에는 몇가지 시그널이 있는데 그중 다음 두개가 가장 자주 쓰입니다.
void QAction::triggered(bool checked = false);
void QAction::toggled(bool checked);
전자는 액션이 유저에의해서 활성화될때(클릭하거나 단축키를 누르거나 등...) 이 시그널이 발생합니다. 그리고 액션을 체크가능하게 설정했을 경우(setCheckable), check되있는 상태가 checked변수로 전달됩니다. 예제에서는 체크할수 있는 액션이 아니므로, 이변수는 무시하였습니다(디폴트 인자가 주어져있으므로 무시할수 있습니다).
후자는 체크가능한 액션에 대해서, 체크된 상태가 변했을때 발생합니다.
예제에서는 전자의 시그널을 이용하여, newFile()슬롯으로 연결하였습니다. 이처럼 액션은, triggered()나 toggled()시그널을, 원하는 동작을 하는 슬롯으로 연결하여 이용하는 것이 보통입니다.
이제 d->newFileAction이 실행될떄마다 newFile()함수가 호출됩니다.

그러면 마지막으로 newFile()함수를 살펴보겠습니다.
void MainWindow::newFile() {
    d->edit->clear();
}
간단합니다. QTextEdit::clear()함수는 내용을 모두 비워버리는 함수입니다. 지금 작성하고있는 어플리케이션은 SDI이므로, 현재 창을 깨끗이 비워주면 곧 새파일을 만드는 셈입니다. 물론 보통은 지금 작성중인 문서를 저장하겠냐는 둥 뭔가 추가로 작업을 해주어야 하지만, 일단은 이번편은 메뉴와 툴바를 만드는 법을 설명하는 것이 목표이므로 일단 간단하게 구현하였습니다.

이제 컴파일하고 실행해봅시다.
실행화면

실행화면

파일 메뉴가 추가되었고, 툴바도 생성된 것을 확인할수 있습니다.
적당히 몇글자 적어보고 툴바의 새 파일 버튼을 눌러보거나, 메뉴에서 새 파일을 클릭하거나, Ctrl+N을 눌러보면 작성된 내용이 모두 지워지는 것을 알수 있습니다.
그런데 뭔가 어색합니다. 보통 툴바에는 액션자체의 이름보다는, 아이콘이 표시되는데, 여기선 이름이 바로 표시되고있습니다.
아이콘을 지정해주면 되는데, 이건 매우 간단합니다. 하지만 여기서 함께 설명하지 않은 것은, 아이콘을 지정하는 것과 함께 '리소스'를 이용하는 방법을, 다음에 같이 설명하기 위해서입니다.
다음편에서는 리소스를 이용하는 법과, 리소스를 이용하여 아이콘을 설정하는 법을 알아보겠습니다.
2008/09/02 09:52 2008/09/02 09:52
Trackback address :: http://xylosper.net/notebook/trackback/123