Kotlin MultiplatformでWindowsデスクトップアプリとそのインストーラーを作ってみる

以前JavaFXを使ったWindowsデスクトップアプリのインストーラー作成の手順を紹介しましたが、InteliJを使ったKotlin Multiplatformであればもっとお手軽に出来たので紹介します

準備するのはInteliJです。以下からダウンロード、インストールしてください。InteliJを使うとプロジェクトの作成時などでJavaやGradleなどの必要なものがセットアップされます

https://www.jetbrains.com/ja-jp/idea/

手順

(1)InteliJ初期画面ですがまずKotlin Multiplatformプラグインをインストールします

(2)プロジェクト_新規プロジェクトを選択

(3)ジェネレーターにKotlin Multiplatformが選択できるようになっています

(4)プロジェクト設定を以下のように入力。今回はデスクトップのみとします。

(5)プロジェクトが初期作成され、ビルドが走ってエラーとなりました。コンソールを見るとJava24を使えとのこと、設定ページへのリンクもあります

(6)リンクを押すと以下のダイアログが開きダウンロードを押すだけで済みます

(7)Java24がインストールされてビルドも成功します

(8)実行してみます。GradleタスクからjvmRunを実行

(9)アプリ画面です。ボタンを押すと図形が表示されたり隠れたりします

(10)インストーラーを作成します。GradleタスクからpackageReleaseMsiを実行

(11)成功しました。コンソールにインストーラーファイルの出力先が出ています

(12)インストーラーファイルです

(13)インストーラーファイルを実行するとセットアップウィザードが始まります

(14)セットアップウィザード2

(15)セットアップウィザード3

(16)セットアップウィザード4

(17)セットアップウィザード5

(18)アプリがインストールされました

(19)アプリ実行

(20)インストーラーをカスタマイズします。アイコンファイルを追加します。追加先は以下のようなリソースフォルダです

(21)build.gradle.ktsにインストーラーの設定を追加します。compose.desktop > application > nativeDistributions項目です

(22)packageNameを変更してwindowsのshortcutをtrueにiconFileの指定を追加しました

(23)再びGradleタスクからpackageReleaseMsiを実行。packageNameに指定した名前でインストーラファイルができました

(24)インストラー実行後、デスクトップにショートカットが出来てアイコン画像が適用されています

以上

Google Apps Script(GAS)でよく使う基本的なメソッド集

GASを触る機会がありましたので、今回はよく使う便利メソッド集をまとめていきます。

スプレッド操作系

// スプレッドシートを開く
const ss = SpreadsheetApp.getActiveSpreadsheet(); // アクティブなスプレッドシート
const ssById = SpreadsheetApp.openById('ID'); // IDで開く
const ssByUrl = SpreadsheetApp.openByUrl('URL'); // URLで開く

// シートを取得
const sheet = ss.getActiveSheet(); // アクティブシート
const sheetByName = ss.getSheetByName('シート名'); // シート名を指定して取得
const sheets = ss.getSheets(); // 全シート取得

// セルの値を取得・設定
const value = sheet.getRange('A1').getValue(); // 単一セルのデータみ取得
const values = sheet.getRange().getValues(); // シートの全データ取得(2次元配列)
const values = sheet.getRange('A1:B10').getValues(); // シートの特定範囲のみ取得(2次元配列)
sheet.getRange('A1').setValue('テキスト'); // 値を設定
sheet.getRange('A1:B10').setValues(values); // 範囲に設定

// 行・列の操作
const lastRow = sheet.getLastRow(); // 最終行番号
const lastCol = sheet.getLastColumn(); // 最終列番号
sheet.appendRow(['値1', '値2', '値3']); // 行を追加
sheet.insertRowAfter(1); // 指定行の後に挿入
sheet.deleteRow(2); // 行を削除

Google Drive操作

// ファイル操作
const file = DriveApp.getFileById('ID'); // ファイル取得
const fileName = file.getName(); // 名前取得
const fileUrl = file.getUrl(); // URL取得
file.setName('新しい名前'); // 名前変更

// フォルダ操作
const folder = DriveApp.getFolderById('ID'); // フォルダ取得
const files = folder.getFiles(); // フォルダ内のファイル
while (files.hasNext()) {
  const file = files.next();
  Logger.log(file.getName());
}

// ファイル作成
const newFile = folder.createFile('name.txt', 'content');

GSAPで横に流れる文字を作る

いにしえのHTMLタグ「marquee」のように、横に流れる文字をGSAPを使って作ります。
GSAPとは、簡単にアニメーションを実装できるJavaScriptライブラリです。

GSAP

■完成物

See the Pen
GSAPで流れる文字
by matsu (@pochi__2828)
on CodePen.

■解説

ベースとなるHTMLには、無限ループにするためにテキストを2回記述する必要があります。
そのテキストをflexboxで横並びにし、片方をleftでイイ感じの位置にずらします。
GSAPの設定は以下の通り。

xPercent →マイナス指定で左方向に移動
duration →動作時間
repeat →-1で無限リピート
ease →移動以外の動きは不要なのでnone

jQuery不要で簡単に動きを付けることができるので、GSAPは覚えていて損はないですね。

Agora APIExampleを使ってWeb通話してみる

Agoraはビデオや音声通話・ライブ配信を簡単に実装できるSDKツールです
Agoraを使ってWeb通話アプリを試そうとした際に
クイックスタートなどを参考にしてもある程度の実装・コーディングが必要になっていて...
とにかくまず動かしてみたいと思いやってみた記録です

◆前提(手順割愛)
・Windows11で作業します
・Androidアプリを作成してスマホで動かします
・AndroidStudioで作業します
・GitHubに接続します
・Agoraにサインアップしてアカウントを取得します
参考URL)https://jp.vcube.com/sdk/trial
・認証用にApp IDとApp Certificate用のTokenを作成します
参考URL)https://qiita.com/v-cube/items/c43dd8b0241f03fedc1d#app-certificate-%E3%81%AE%E6%9C%89%E5%8A%B9%E5%8C%96


AgoraIO/API-Examplesというリポジトリがあります
URL)https://github.com/AgoraIO/API-Examples
Agoraのサンプル集なのでこれをビルドすればすぐアプリとして動かせると考えました

◆手順
まず上記リポジトリからCloneします、取得先はAndroidStudioのプロジェクトフォルダとします
例)C:\Users\【ユーザー名】\StudioProjects\API-Examples

上記フォルダをAndroidStudioで開きます

API-Examples内には各機種向け、各機能ごとのサブプロジェクトという構成になっています
今回使用するのはAPI-Examples/Android/APIExampleです

App IDとApp Certificate用のTokenを設定します
設定先はAPIExample/app/src/main/res/values/string_configs.xmlです

<string name=”agora_app_id” translatable=”false”>YOUR APP ID</string>

“YOUR APP ID”部分をApp IDに書き換え

<string name=”agora_app_certificate” translatable=”false”>YOUR APP CERTIFICATE</string>

“YOUR APP CERTIFICATE”部分をApp Certificate用のTokenに書き換え

以上でビルドすればAPKができるはずでしたがビルドができない、失敗などあったので以下を追加処置しました

●API-Examples/build.gradle
修正前

id 'com.android.application' version '8.5.0' apply false
id 'com.android.library' version '8.5.0' apply false

修正後

id 'com.android.application' version '8.5.2' apply false
id 'com.android.library' version '8.5.2' apply false

●API-Examples/gradle.properties
修正前

rtc_sdk_version = 4.0.1

修正後

rtc_sdk_version = 4.5.2

●API-Examples/app/build.gradle
修正前


android {
    namespace "io.agora.api.example"
    compileSdk 35
    defaultConfig {
        applicationId "io.agora.api.example"
        minSdkVersion 24
        targetSdkVersion 35

修正後


android {
    namespace "io.agora.api.example"
    compileSdk 34
    defaultConfig {
        applicationId "io.agora.api.example"
        minSdkVersion 24
        targetSdkVersion 34

以上でビルドが通るようになりました
◆リリースビルドしてAPKファイルを作ります
Android StudioでTerminalビューを開き
API-Examples/Android/APIExample配下にあるgradleのスクリプトを実行します

gradlew assembleRelease

API-Examples/Android/APIExample/app\build/outputs/apk/releaseにapkファイルができます

◆スマホでアプリを動かしてみる

Android端末2台にAPKをインストールします

起動します。アプリの初期画面です。いろんなサンプルのメニュー選択画面になっています。

メニューの一番目のLive Interactive Vide Streaming(Token Verify)を選択してみます

「App ID」、「Token」、「Channel ID」を入力してビデオ通話を開始する機能になっています。「App ID」、「Token」はAgoraで発行したものを使用する必要があります。今回はアプリに「App ID」、「Token」を埋め込んでいますのでこの機能は使いません

メニューに戻って2番目のLive Interactive Vide Streamingを選択します

「Channel ID」を入力してビデオ通話を開始する機能になっています。「App ID」、「Token」はアプリに埋め込んだ値が使用されます。

「Channel ID」に適当な値を入力してJOINボタンを押すとビデオ通話を開始します

ビデオ通話を開始して待ち受けている状態です。画面左側に自分のカメラ映像を映しています

もう一方のスマホでアプリを起動して同じくLive Interactive Vide Streaming画面から「Channel ID」に先ほどと同じ値を入力してJOINボタンを押します

ビデオ通話に参加しました。相手のカメラ映像が映し出されています。音声もつながっており会話できます

以上

データベース設計の基礎について

今回はデータベース設計について学んだことをまとめます。
特に実務でも必ず使う論理設計と正規化に重点を置き、初心者でもイメージしやすいように解説できたらと考えています。

1. DB設計の全体像

DB設計は、ざっくり以下3つのステップで進めます。

1-1. 概念設計

・扱う情報や関係性を明確にする
・ER図(Entity Relationship Diagram)で表す

例:ユーザーが商品を注文する → 「ユーザー」「注文」「商品」というエンティティを洗い出す

1-2. 論理設計

・データをRDB(リレーショナルデータベース)で使える形に変換
・主キー、外部キー、正規化を行う

1-3. 物理設計(実際のDB実装の準備)

・データ型やインデックス設計
・DBMSごとの最適化

【ポイント】
概念設計は「何を扱うか」、論理設計は「どう整理するか」、物理設計は「どう動かすか」

2. 論理設計の基本

論理設計は、データを重複が少なく矛盾が起きにくい形に整理する作業です。

2-1. 主キー(Primary Key)
・各行を一意に識別するためのキー
・重複やNULLは禁止
例:user_id、order_id

2-2. 外部キー(Foreign Key)
・他のテーブルの主キーを参照するカラム
・データの関係性を保つ
例:orders.user_id → users.user_id

2-3. データ型の選択
・正しい型を選ぶことで性能や整合性が上がる
・数値はINTやBIGINT、日付はDATEやDATETIME

例:ユーザーと注文の関係
テーブル : users
・user_id (PK)
・name
・email

テーブル : orders
・order_id (PK)
・user_id (FK → users.user_id)
・order_date

3. 正規化の基本

正規化とは、冗長性を減らし整合性を保つためにテーブルを分割する作業です。
一言で言うと「意味ごとにテーブルを分けて整理する」ことです。

第1正規形(1NF)

・各カラムには1つの値だけを入れる
・繰り返しカラムを作らない

第2正規形(2NF)

・複合キーの一部にだけ依存する列を分ける
・主キーが2つ以上のカラムで構成されている場合に注意
例: (order_id, product_id) が主キーで、order_dateはorder_idだけで決まる場合、order_dateは別テーブルに分離する

第3正規形(3NF)

・主キー以外の列同士の依存を排除
例:住所テーブルに郵便番号から都道府県が決まる場合、都道府県は郵便番号から導けるため別テーブルに分離する

4. 正規化のメリットとデメリット

【メリット】
・データの重複削減
・更新時の整合性維持
・論理的な整理による可読性向上

【デメリット】
・JOINが多くなり、性能が落ちる可能性がある
・過度な分割は管理が複雑

実務では第3正規形まで行い、必要に応じて非正規化するのが一般的です。

5. 論理設計・正規化を学んで気づいたこと

・最初にしっかり設計すれば、後からの修正コストが大幅に減る
・正規化は理屈だけでなく、サンプルを作って試すと理解が深まる
・ER図を描くと頭の中が整理される
・完璧な正規化は不要で、システムの性質や速度も考慮が必要になる

6. まとめ

・論理設計は「データを整理する技術」
・正規化は「冗長性をなくし整合性を保つ方法」
・実務では正規化とパフォーマンスのバランスが重要
・最初の設計が後の保守性を左右する

参考資料

・書籍「達人に学ぶDB設計徹底指南書」

たった一言で改善するCTAの重要性

CTAとは「Call To Action(行動喚起)」の略語で、サイトへ訪問したユーザーを具体的な行動へ誘導することが目的です。
例えば、「お問い合わせ」や「お申し込みはこちら」などのボタンやリンクがそれです。

CTAを見直すことで、効果が上がった具体的な例が、abtest.designに掲載されているのでご紹介します。

https://abtest.design/tests/trial-for-free-cta

ボタンに注目してください。
左のA案は「SIGN UP FOR FREE(無料で登録)」、右のB案は「TRIAL FOR FREE(無料でお試し)」と書かれています。
A/Bテストの結果、B案はトライアル開始数が前月比104%増加したそうです。

些細な違いかもしれませんが、たった一言でも言葉選びは大切にしたいですね。

Java FX インストーラーを作成する

Java FXでJavaで手軽にGUIアプリを作れますが、いざそれを配布しようとすると少しハードルが高いです。少しトリッキーですが成功した実例をもとに手順を紹介します。

使用したツールは以下の通りです。Windows環境です。

  • pleiades-2025-03-ultimate-win-64bit-jre_20250319(Java開発、作業用)
  • openjdk-22.0.2_windows-x64_bin(Java開発、作業用)
  • openjfx-23.0.1_windows-x64_bin-sdk(JavaFX開発、作業用)
  • openjfx-23.0.1_windows-x64_bin-jmods(JavaFX実行用モジュール)
  • wix314(jpackageから使用される)
  • innosetup-6.4.2(インストーラー作成ツール)

システム環境変数設定

  • JAVA_HOME=C:\pleiades\2025-03\java\jdk-22.0.2(jdkを置いた場所)
  • WIX=C:\Program Files (x86)\WiX Toolset v3.14\(WIXインストール時に書き込まれている)
  • path=%JAVA_HOME%\bin(リストに追加)(Javaコマンド実行用)

以下手順です

まずはJava FXのプロジェクトを作ります。

eclipseでMavenを使ってJava FXアーキタイプ(ひながた)から作成します

プロジェクトができてビルドまでできました。このまま実行すると

アプリが動作します。

インストーラーを作成する。

プロジェクトをエクスポートします

jarファイルとlibフォルダが出力されます

次にカスタムJREを作成します。上図のパス上からコマンドラインを開きjlinkコマンドを実行します

jlink --module-path "C:\pleiades\2025-03\java\javafx-jmods-23.0.1" ^
--add-modules java.base,javafx.controls,javafx.fxml,javafx.graphics,java.management,java.naming ^
--output custom-jre

コマンドラインからjpackageコマンドを実行してMSI インストーラーを作成します。

jpackage --type msi ^
--input . ^
--main-jar jfxsample.jar ^
--main-class jp.co.abridge.jfxsample.App ^
--runtime-image custom-jre ^
--name JavaFXSample ^
--dest result

resultフォルダが出力されて中にmsiファイルがあります。これを実行してアプリをインストールします

インストールされました。ただしこれは仮のインストールでこれをもとに正式なインストーラーを作成します

Inno Setup を使って日本語インストーラーを作成する

Inno Setupを起動して以下のようなスクリプトを実行します

[Setup]
AppName=JavaFxSample
AppVersion=1.0
DefaultDirName={pf}\JavaFxSample
OutputBaseFilename=JavaFxSampleInstaller
DisableDirPage=false
CreateAppDir=true
PrivilegesRequired=admin
Compression=lzma
SolidCompression=no
UninstallDisplayIcon="{app}\JavaFxSample.exe"

[Languages]
Name: "Japanese"; MessagesFile: "compiler:Languages\Japanese.isl"

[Files]
Source: "C:/Program Files/JavaFxSample/app/*"; DestDir: "{app}/app"; Flags: ignoreversion
Source: "C:/Program Files/JavaFxSample/runtime/*"; DestDir: "{app}/runtime"; Flags: recursesubdirs
Source: "C:/Program Files/JavaFxSample/JavaFxSample.exe"; DestDir: "{app}"; Flags: ignoreversion

[UninstallDelete]
Type: filesandordirs; Name: "{userappdata}\JavaFxSample"

~/Documents/Outputフォルダにファイルが出力されます。これが最終のインストーラーファイルです

インストーラーを実行すると

インストールされて、起動すると

アプリが動作します

以上です。

Laravel 12で追加された一部新機能について

Laravel 12の新機能について

この記事では、2025年2月にリリースされた Laravel 12 の一部新機能について紹介します。

Laravel 12

Laravel 12は、大きな変更というよりも改良がいくつか含まれているので、今回はその中の一部を紹介します。

1. セキュリティ強化 : secureValidate()

このメソッドが追加されたことで、フォームからの入力チェックがより安全になりました。

$request->secureValidate([
'password' => ['required', 'min:8', 'strong'],
]);

バリデーション(validation)とは、ユーザーが入力したデータが正しいかどうかをチェックする仕組みです。

例えば

  • メールアドレスの形式が正しいか?
  • パスワードの長さは十分か?
  • 必須項目が空になっていないか?
    など。

Laravelでは、従来から $request->validate() を使ってこのバリデーションを行ってきました。

secureValidate() とは?

secureValidate() は、Laravel 12で新たに追加されたメソッドで、従来の validate() と同じように使えますが、セキュリティに配慮したルール(例:強力なパスワード)を簡単に適用できるのが特徴です。

$request->secureValidate([
'password' => ['required', 'min:8', 'strong'],
]);

この例の意味

 

strongルールの意味とは?

strong というルールは、安全なパスワードを推奨するための組み込みルールで、Laravel 12において以下のようなチェックを行うことができます。

  • 英大文字、小文字、数字、記号の組み合わせが含まれているか
  • 辞書にあるような簡単な単語を避けているか
  • 繰り返しや連番(”1234″ や “aaaa”)が含まれていないかこうしたチェックを自前で書くのは大変ですが、strongルールを使えば一発で適用できます。

なぜ secureValidate() を使うべきか?

  • セキュリティ対策が標準で強化される
  • 独自のカスタムバリデーションを定義しなくてよくなる
  • コードがシンプルで読みやすい

2. クエリがもっと読みやすくなる nestedWhere() が追加された

nestedWhere() は複雑な条件のクエリをより直感的・読みやすく記述できるようにするための新機能です。

そもそも WHERE 条件って何?

Laravelのクエリビルダでは、where() を使って条件付きのデータを取得できます。

$users = User::where('status', 'active')->get();

条件が複雑になってくるとwhere 条件のネストが必要になり、関数の中に関数が入るためとても難解です。

$users = User::where(function ($query) {
$query->where('age', '>', 25)
->orWhere('city', 'Tokyo');
})
->where('status', 'active')
->get();

nestedWhere() の登場

Laravel 12では、このネストを簡単に書けるようにする nestedWhere() が追加されました。

$users = User::where('status', 'active')
->nestedWhere('age', '>', 25, 'or', 'city', 'Tokyo')
->get();

普通のSQLに変換するとこうなります。

WHERE status = 'active'
AND (age > 25 OR city = 'Tokyo')

nestedWhere() の構文

->nestedWhere($column1, $operator1, $value1, $boolean, $column2, $value2)

使いどころ

  • AND (…) や OR (…) などの複雑な論理条件を含むクエリを書くとき
  • ネストの書き方が苦手な初心者
  • チーム開発で読みやすいコードを書きたいとき

まとめ

Laravelは初心者にもやさしく使いやすい機能が満載なので、これからWebアプリを始めるならおすすめです。

初心者にも分かりやすいPHP言語のフレームワークとなっているので、まずは気軽に触ってみて、その便利さを体感してみてください!

Figmaのアイコンプラグイン『Iconify』

『Iconify』は、FontAwesomeやMaterial Design Iconsなど、有名なサービスのアイコンをはじめ、150以上のアイコンセットを一括検索して配置できるFigmaのプラグインです。

→Iconify

 

例えば「user」で検索すると、全アイコンセットからuserアイコンを抽出してくれます。

 

追加したいアイコンを選択すると、サイズと色を設定できます。

 

 

ライセンスはアイコンセットによって違いますが、それぞれ確認できます。

 

 

 

 

 

 

さくっとアイコンを選んで配置できるので、プロトタイプをイイ感じに早く仕上げることができますね。

チャットボット構築サービス「Dialogflow」を使ってみた

チャットボットを調べる機会があったので「Dialogflow」でサービスを作ってWEBサイト上で動かすまでをまとめてみました。

1.「Dialogflow」サイトへ行き(GoogleアカウントでDialogflowを開始して)CREATE AGENTします。

2.AGENT情報を入力します。名称と言語とタイムゾーンを入力してCREATE

3.Intents画面になるのでCREATE INTENTS

4.Intentsのタイトルを入力してSAVE

5.Training phrasesとResponsesを入力してSAVE

6.右のパネルでテストしてみます。応答がありました

7.動作が確認できたのでチャットボットをWEBサイトに設置します。IntegrationsのページからDialogflow Messangerを選択します。

8.htmlに張り付けるソースコードが表示されるのでコピーします

9.適当さWEBサイト(今回は私が課題制作しているlocalhost上のWEBサイト)を用意します

10.該当のhtmlソースにコピーしたスクリプトを貼り付けます

11.WEB画面を開いてみます。チャットボットが現れます

12.質問すると応答があります

以上です。

バス移動・通勤を便利にするサービスを構築している中でチャットボットを+αの便利機能として付加させてみました。今後はIntentsを増やして対応する路線、停留所を増やす。Entity(同義語登録)を増やして音声入力に対応する。ほかサービスとの連携。など拡充していきます。