HelloWorldのウインドウの大きさと位置を制御する | macOSアプリの作り方

Cocoa版Hello World作成の続きです。今回は、最小サイズと最大サイズを設定して、ウインドウサイズの制限を追加します。また、前回追加したHelloWindowControllerクラスにコードを追加して、スクリーンの中央に配置するようにします。

この記事では前回の記事で作成したCocoa版Hello Worldの続きから行います。前回の記事に沿って作成している場合はそれを使用してください。作成されていない場合は、前回の記事の末尾からサンプルコードをダウンロードしてご利用ください。

関連記事

前回のCocoa版Hello World作成の続きです。今回はウインドウコントローラクラスを追加して、Cocoa版Hello Worldで表示されるウインドウのウインドウコントローラを変更する方法について解説します。 この記事では[…]

スポンサーリンク

ウインドウサイズの最小値・最大値の設定

ウインドウサイズの最小値・最大値の設定はコードで行う方法とStoryboardファイル内で設定する方法があります。ここではコードで設定する方法を解説します。どちらの方法でも構わないのですが、次のような理由でコード定義にしました。

  • 値を決定するときに試行錯誤が簡単。
  • 将来のバージョンなどで値を変更していったときに変更履歴を追うのが容易になる。

最小値・最大値を設定するコードを追加する

Storyboardファイルからウインドウを読み込むと、AppKitはNSWindowController.windowDidLoad()メソッドが実行されます。windowDidLoad()メソッドはウインドウの初期化処理を行うべきメソッドです。このメソッド内で最小値・最大値を設定します。

次のようにコードを追加します。

import Cocoa

class HelloWindowController: NSWindowController {
    
    let minWindowWidth: CGFloat = 200
    let minWindowHeight: CGFloat = 150
    let maxWindowWidth: CGFloat = 1200
    let maxWindowHeight: CGFloat = 900

    override func windowDidLoad() {
        super.windowDidLoad()
        
        window?.minSize = CGSize(width: minWindowWidth,
                                 height: minWindowHeight)
        window?.maxSize = CGSize(width: maxWindowWidth,
                                 height: maxWindowHeight)
    }

}

次のスクリーンキャプチャは最小サイズにしているときです。

ウインドウの取得

AppKitのウインドウはNSWindowController.windowプロパティに入っています。

open var window: NSWindow?
スポンサーリンク

最小サイズ

ウインドウの最小サイズはNSWindow.minSizeプロパティに設定します。

open var minSize: NSSize

最大サイズ

ウインドウの最大サイズはNSWindow.maxSizeプロパティに設定します。

open var maxSize: NSSize

カーソルの制御

サイズ変更可能なウインドウの場合、ウインドウの角やフレームなどにカーソルを持って行くと、カーソルが自動的にリサイズ可能なことを示すように変化します。AppKitではカーソル制御をアプリ側で行えますが、何もしなくても、macOSの標準的な制御は行ってくれます。

例えば、次のスクリーンキャプチャはウインドウサイズを広げることも縮めることもできる状態のときです。

最小サイズのときは、これ以上縮小できないことを示すカーソルになります。

最大サイズのときは、これ以上を広げることができないことを示すカーソルになります。

ウインドウを中央に配置する

ウインドウを中央に配置する処理を追加します。

コードの追加

単純に考えると、スクリーンサイズとウインドウサイズを元に、中央に配置する座標を計算するという処理になりますが、NSWindowクラスにはウインドウを中央に移動するメソッドがあるので、座標を求める方法ではなく、用意されているメソッドを使用します。

次のようにコードを変更します。

import Cocoa

class HelloWindowController: NSWindowController {
    
    let minWindowWidth: CGFloat = 200
    let minWindowHeight: CGFloat = 150
    let maxWindowWidth: CGFloat = 1200
    let maxWindowHeight: CGFloat = 900

    override func windowDidLoad() {
        super.windowDidLoad()
        
        window?.minSize = CGSize(width: minWindowWidth,
                                 height: minWindowHeight)
        window?.maxSize = CGSize(width: maxWindowWidth,
                                 height: maxWindowHeight)

        window?.makeKeyAndOrderFront(nil)
        window?.center()
    }

}

追加したコードは次の部分です。

window?.makeKeyAndOrderFront(nil)
window?.center()

ウインドウリストとキーウインドウについて

macOSではスクリーンに表示されているウインドウを管理しているウインドウリストと呼ばれるリストがあります。windowDidLoad()メソッドが実行されている段階では、ウインドウリストにウインドウが入っていないので、スクリーンにはウインドウは表示されません。

この状態でcenter()メソッドを使っても、どのスクリーンに対して中央なのかが決まらないので、center()メソッドが動きません。

そこで、NSWindow.makeKeyAndOrderFront()メソッドを使用します。makeKeyAndOrderFront()メソッドは次のような処理を行います。

  • 先頭のスクリーンにウインドウを移動する。
  • ウインドウをキーウインドウに変更する
  • ウインドウを表示する

キーウインドウとは?

スクリーンには複数のアプリが同時に起動し、各アプリは複数のウインドウを持っています。ここでキーボードからキー入力を行うと、最前面にあるウインドウがキーダウンイベントを受け取り、キー入力を処理します。この最前面にあり、キーダウンイベントを受け取るウインドウのことを「キーウインドウ」と呼びます。

微妙に中央ではない?

center()メソッドで配置されたウインドウが微妙に中央ではないことに気がつきましたか?水平方向は中央揃えになっていますが、若干、上方向にずれて表示されます。これは、不具合ではありません。

人間の視覚的に、完全な中央よりも若干上にずれた位置の方が見やすく、気がつきやすいため、このような仕様になっています。

サンプルコードのダウンロード

今回の記事で作成したサンプルコードはこちらからダウンロードできます。

003_CocoaHelloWorld.zip

スポンサーリンク
最新情報をチェックしよう!