メインコンテンツまでスキップ

チュートリアルメイン・コンポーネント

📚 Source Page

このチュートリアルでは、メイン・コンテンツ・コンポーネントを作成することによって、アプリケーション・ウィンドウにグラフィカル・コンテンツを追加する方法を説明します。これは、ウィンドウ内でユーザーにコンテンツを表示するために重要です。

レベル初心者

プラットフォーム:Windows, macOS, Linux

クラス: DocumentWindow,Component,Graphics

スタート

Projucerを起動し、次の名前で新しいGUIアプリケーション・プロジェクトを作成します。メインコンポーネントチュートリアル.での自動生成するファイル:フィールドでMain.cppファイルのみを作成する.

このステップでヘルプが必要な場合は、以下を参照してください。Tutorial: Projucer Part 1: Getting started with the Projucer.

を変更する。MainComponentTutorialApplicationクラスには以下が含まれる。MainWindowクラスを以下のように変更した:

//==============================================================================
class MainComponentTutorialApplication : public juce::JUCEApplication
{
public:
//...

//==============================================================================
class MainWindow : public juce::DocumentWindow
{
public:
MainWindow (juce::String name) : DocumentWindow (name,
juce::Colours::lightgrey,
DocumentWindow::allButtons)
{
setUsingNativeTitleBar (true);
centreWithSize (300, 200);
setVisible (true);
}

void closeButtonPressed() override
{
JUCEApplication::getInstance()->systemRequestedQuit();
}

private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainWindow)
};

private:
std::unique_ptr mainWindow;
};
DocumentWindowA resizable window with a title bar and maximise, minimise and close buttons.Definition juce_DocumentWindow.h:67
JUCEApplication::getInstancestatic JUCEApplication *JUCE_CALLTYPE getInstance() noexceptReturns the global instance of the application object being run.
JUCEApplication::systemRequestedQuitvoid systemRequestedQuit() overrideCalled when the operating system is trying to close the application.
nameint UnityEventModifiers const char * nameDefinition juce_UnityPluginInterface.h:204
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR#define JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(className)This is a shorthand way of writing both a JUCE_DECLARE_NON_COPYABLE and JUCE_LEAK_DETECTOR macro for ...Definition juce_PlatformDefs.h:262
ColoursContains a set of predefined named colours (mostly standard HTML colours)Definition juce_Colours.h:46
juceDefinition juce_AudioWorkgroup_mac.h:36

以下の行をinitialise()関数である:

void initialise (const juce::String& commandLine) override
{
mainWindow.reset (new MainWindow (getApplicationName()));
}

最後に、以下の行をshutdown()関数である:

void shutdown() override
{
mainWindow = nullptr;
}

はじめに

前回のチュートリアル(Tutorial: The application window)では、アプリケーションのグラフィカル・インターフェースのフレームとなるメイン・ウィンドウについて説明しました。このチュートリアルではメインコンテンツコンポーネントを示すオブジェクトである。内容アプリのインターフェイスのメインコンテンツコンポーネントは、すべてのJUCEアプリに不可欠なオブジェクトです。

新しいGUIアプリケーションをThe ProjucerJUCEアプリのメインコンテンツコンポーネントが自動的に生成されます。しかし、この概念に慣れ、JUCEアプリがどのように構成されているかを理解する良い方法は、このようなメインコンテンツコンポーネントを自分で作成することです。これが、このチュートリアルで行うことです。

IDEでチュートリアル・プロジェクトを開いてください。前回のチュートリアルと同じところ、つまり空のアプリケーション・ウィンドウから始めます。つまり、空のアプリケーション・ウィンドウです。Main.cppファイルではMainWindowクラスを使用します。その使い方は前回のチュートリアルですでに学んだ(Tutorial: The application window).では、このウィンドウをコンテンツで埋めましょう!

しかし、その前に、まずはコンポーネントもう少し先だ。

コンポーネント・クラス

全てのJUCEグラフィカル・インターフェースの最も重要な基本クラスはComponentクラスを使用します。JUCEでは、ボタンであれ、スライダーであれ、テキスト・フィールドであれ、GUIの実質的に目に見える要素はすべてコンポーネントこのクラスから派生したものです。JUCEでこのようなアプリを書く方法は主成分これはメイン・アプリケーション・ウィンドウが所有し、ウィンドウの内容.他のすべてのコンポーネントは子供たちこの主要コンポーネントのTutorial: Parent and child components).そのDocumentWindowクラスがある。MainWindowを派生させたもので、メインウィンドウがそのコンテンツ(メインコンポーネントとその子コンポーネントを含む)を正しく表示するために必要な機能を含んでいます。

注記

覚えておいてください:JUCEのすべてのグラフィカル要素はComponentクラスで構成される。GUIを構築するには、さまざまなコンポーネントをそして子供コンポーネントで構成される。一番上のコンポーネントはメインコンテンツコンポーネント.参照Tutorial: Parent and child componentsを参照されたい。

メイン・コンポーネント・クラスの追加

新しいソースファイルの作成

では、メイン・コンポーネント・クラスを作りましょう。そのためには、このクラスのソース・コードを格納する新しいファイルを作成する必要があります。に戻りましょう。The Projucerでチュートリアル・プロジェクトを開きます。左側のファイルブラウザを開く。次にソースグループ(新しいC++ソース・ファイルが常に置かれるべきファイル・グループ)を選択し新しいコンポーネントクラスを追加(CPPとヘッダーに分割)....The Projucerは、新しいComponentサブクラスのサブクラスを作成します。ダイアログでメインコンポーネントをクリックしファイル作成.次のことがわかるだろう。The Projucerは2つの新しいファイルを作成した:MainComponent.cppそしてMainComponent.h.ここで、プロジェクトを保存し、あなたのIDE.新しいファイルもそこに表示されるはずだ。The Projucerは新しいコンポーネント・クラスのコードを自動的に作成した。

The Projucerに新しいコンポーネント・クラス�を追加する。
The Projucerに新しいコンポーネント・クラスを追加する。
注記

覚えておいてください: 新しいクラスを作成する場合、クラス名と同じファイル名で、独自のファイルを作成する必要があります。常にThe Projucerを使用して新しいファイルを作成します。IDE(The Projucerそのような変更は、次にプロジェクトを保存するときに上書きされます)。

新しいコンポーネント・クラス

ご覧の通りだ、The Projucerから新しいクラスを自動的に派生させた。Componentクラスに以下のクラス宣言を追加した:

class MainComponent    : public juce::Component
{
public:
MainComponent();
~MainComponent();

void paint (juce::Graphics&) override;
void resized() override;

private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainComponent)
};

についてComponent基底クラスには2つの重要な仮想メンバ関数があり、派生クラスでオーバーライドする必要があります。The Projucerこの2つのオーバーライドは、すでにあなたのために作成されている:

  • Component::paint(): このメンバ関数は、コンポーネントがどのように画面に描画されるかを決定します。
  • Component::resized():このメンバ関数は、コンポーネントがリサイズされたときに何が起こるかを決定する。
注記

キーワードoverrideを、ベース・クラスの関数をオーバーライドすべきクラス内のすべての関数に適用します。これは、アプリで予期せぬエラーが発生するのを防ぐためです。JUCE coding standards.

ペイント機能の実装

についてpaint()関数はComponentオブジェクトがスクリーンにレンダリングされる。ここで、カスタム・アピアランスをMainComponentクラスである。

The Projucerは自動的にいくつかのデモ・コードを追加した。独自のコードをpaint()関数である。

void MainComponent::paint (juce::Graphics& g)
{
g.fillAll (juce::Colours::lightblue);

g.setColour (juce::Colours::darkblue);
g.setFont (20.0f);
g.drawText ("Hello, World!", getLocalBounds(), juce::Justification::centred, true);
}

このコードの詳細にはあまり立ち入る必要はない。次のチュートリアルで、ここで使われている関数について(さらに)詳しく学びます:Tutorial: The Graphics class.とりあえず、このデモ・コードがコンポーネントを水色の背景で満たし、テキストをレンダリングしていることは想像がつくだろう。**ハロー、ワールド!**とコンポーネントの中央に青いフォントで表示される。ここでのポイントはMainComponentオブジェクトはpaint()関数である。

メインコンポーネントを可視化する

では、コードをコンパイルして実行してください。青い背景とテキストの代わりに、空のアプリケーション・ウィンドウが表示されるだけです。なぜでしょうか?

まあ、私たちはそのことをMainWindowオブジェクトにコンテンツを表示する必要がある。まず最初に、ヘッダーを含める必要がある。MainWindowクラスはMainComponentクラスを追加する。クラスの先頭に以下のインクルードを追加する。Main.cppファイルを、すでに存在するインクルードの下に置く:

#include "MainComponent.h"

次のステップはMainComponentオブジェクトとして追加する。内容を呼び出せばよい。そのためにはDocumentWindow::setContentOwned()関数である。

注記

「所有」とはMainWindowオブジェクトの寿命に責任を持つようになった。MainComponentオブジェクトのデストラクタが呼ばれたときに自動的に破棄される。

のコンストラクタに以下の行を追加する。MainWindowクラスである:

setContentOwned (new MainComponent(), true);

となるようなMainWindowコンストラクタは次のようになる:

MainWindow (juce::String name)  : DocumentWindow (name,
juce::Colours::lightgrey,
DocumentWindow::allButtons)
{
setUsingNativeTitleBar (true);
setContentOwned (new MainComponent(), true);
centreWithSize (getWidth(), getHeight());
setVisible (true);
}

Component::centreWithSize()関数の引数も変わりました。のサイズを明示的に設定しないようになりました。MainWindowオブジェクトの内容からサイズを割り出すように指示する:

centreWithSize (getWidth(), getHeight());

しかし、これが機能するためにはMainComponentオブジェクトのサイズをcentreWithSize()関数の呼び出しが発生します。これが行われないと、メイン・ウィンドウは適切なウィンドウ・サイズを知ることができません(これを実行するとアサーションが失敗します)。次のセクションでは、この方法を説明します。

コンポーネントのサイズを設定する

原則として、以下の2つの方法がある。Componentオブジェクトに設定します。コンポーネントのコンストラクタでサイズを設定するか、親コンポーネントのコンストラクタでサイズを設定します。メイン・コンポーネントの場合、通常はコンポーネント自体にサイズを設定します。のコンストラクタに次の行を追加します。MainComponentクラスである:

setSize (400, 300);

(もちろん、他のサイズを選ぶこともできる)。

警告

覚えておいてください: コンポーネントのサイズは必ず設定してください。このステップを省略することは、JUCEのバグの非常に一般的な原因です。

の関数 Component::getWidth() と Component::getHeight() の呼び出しが、このような理由である。MainWindowクラスは、メイン・コンポーネントが正しいサイズで表示されるように、ウィンドウのサイズを把握することができます。このMainComponentオブジェクトのサイズは、それ自身のコンストラクタで設定される。MainWindowオブジェクトの位置とサイズが決まります。

これで必要なパーツはすべて揃った。アプリをコンパイルして実行すると、メイン・コンポーネントがアプリケーション・ウィンドウに正しく描画されているのが見えるはずだ:

新しいMainComponentオブジェクトがスクリーンにレンダリングされる。
新しいMainComponentオブジェクトがスクリーンにレンダリングされる。
エクササイズ

の第2引数が何であるかを調べる。setContentOwned()関数が意味するものである。trueこちら)と、それを変更した場合の動作について。ヒントResizableWindow::setContentOwned()関数である。

リサイズ機能の実装

ここまででpaint()関数をどのように使うことができるか見てみよう。MainComponentクラスはサイズ変更に反応する。

まず最初に、メイン・ウィンドウのサイズを変更できるようにする必要があります。詳しくはTutorial: The application windowその方法を覚えていないのなら。

アプリをコンパイルして実行し、マウスを使ってウィンドウのサイズを変更してください。するとMainComponentオブジェクトは、メイン・ウィンドウのサイズに合うように自分自身のサイズを変更します。Component基底クラス。

しかし、コンポーネントのサイズが変更されるたびに、カスタム作業を行いたい場合はどうでしょうか?もしかしたら、子コンポーネントがあり、メインコンポーネントのサイズによってレイアウトを変える必要があるかもしれません。この単純なデモアプリでは、メイン・コンポーネント内のテキストを変更し、コンポーネントの現在のサイズを表示するようにしてみましょう。

コンポーネントのサイズを変更する際に必要な作業や更新は、コンポーネントのresized()関数を使用する。現在、この関数は空です。ここに私たちの機能を追加しましょう。

警告

Component::resized()関数は、コンポーネントのサイズ変更につながる何かが起こるたびに自動的に呼び出されます。決して自分でこの関数を呼び出してはいけません!

コンポーネント内に表示されるテキストは現在、リテラル文字列として与えられている。- です。paint()関数を使用します。新しいメンバ変数をMainComponentクラスで使用されます。変数には常に、説明的で意図がわかる名前をつけるのがよい習慣です。そうすることで、コードが読みやすく理解しやすくなり、追加コードのコメント量も減ります。新しい変数は、メイン・コンポーネントの現在のサイズを文字列で表すようにします。currentSizeAsString.

メンバ変数は常にクラスのprivateセクションで宣言される:

class MainComponent    : public juce::Component
{
// ...

private:
juce::String currentSizeAsString;
// ...
};

では、その動作を実装してみよう。currentSizeAsStringオブジェクトです。やるべきことは2つある:

  • の内容である。currentSizeAsStringオブジェクトが画面にレンダリングされなければならない。
  • についてcurrentSizeAsStringオブジェクトは、メイン・コンポーネントのサイズが変わるたびに自分自身を更新しなければならない。

最初の部分を実現する方法はいたって簡単だ。paint()関数はg.drawText()関数が呼び出されたら、単にリテラル文字列をcurrentSizeAsStringオブジェクトがある:

void MainComponent::paint (juce::Graphics& g)
{
//...
g.drawText (currentSizeAsString, getLocalBounds(), juce::Justification::centred, true);
}

番目の部分はもっと興味深い。サイズを変更するたびにresized()関数が呼び出される。ではcurrentSizeAsStringオブジェクトがそこにある:

void MainComponent::resized()
{
currentSizeAsString = juce::String (getWidth()) + " x " + juce::String (getHeight());
}

Component::getWidth() と Component::getHeight() は、コンポーネントの現在のサイズを問い合わせることができる便利な関数です。また、これらの整数をStringオブジェクトを使用します。(オブジェクトの操作方法についてはStringクラスは今後のチュートリアルで紹介する)。

今アプリをコンパイルして実行すると、常に現在のサイズが表示されることがわかるだろう:

完成したデモアプリ。
完成したデモアプリ。

ここで2つの興味深い観察ができる。第一に、表示は自動的に更新される。paint()関数はresized()関数が呼び出される。第二に、アプリの起動時、ウィンドウのサイズを自分で変更する前でも、サイズはすでに正しく表示されている。そのためresized()関数は何でもはコンポーネントのサイズを変更します。これには、コンポーネントのサイズが最初に設定されたときと、アプリ起動後にコンポーネントが描画されたときが含まれます。

エクササイズ

を変更する。MainComponent::resize()関数は、サイズを変更するたびにMainComponentオブジェクトの背景色も変わる。

チュートリアル・プロジェクトの完成版はこちらからダウンロードできる:PIP|ZIPそして自分のものと比較する。

概要

このチュートリアルでは、メイン・コンポーネントの概念、アプリへの追加方法、そしてpaint()そしてresized()関数を使用することができます。このチュートリアルを読めば、以下の重要なことがわかるはずだ:

  • すべてのJUCEアプリケーション・ウィンドウには、メイン・コンポーネントがあります。これは、アプリのGUIを構成する他のすべてのコンポーネントの親となります。
  • メイン・コンポーネントを含むすべてのコンポーネントには、オーバーライドする必要のある2つの重要な関数がある:paint()そしてresized().
  • の中でpaint()関数に、コンポーネントを画面にレンダリングするコードを追加する。
  • を実装する必要があります。resized()関数は、コンポーネントがサイズの変化に反応するような特別な動作が必要な場合に使用します。
  • についてpaint()そしてresized()関数はコールバック関数は、必要なときに自動的に呼び出される。
  • メイン・コンポーネントのサイズを設定し、メイン・ウィンドウに追加して表示させることを忘れてはならない。

参照