0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

CMP(Compose Multiplatform)でデスクトップアプリを作ったらだいぶ楽だった話

Last updated at Posted at 2025-05-08

最近デスクトップアプリを作りたいと思い、最初はWindowsだけでいいかとおもってUWPで作ろうと思っていたが、自分がAndroidエンジニアなこともあり、せっかくならCMPで作ってみようと思って作ったが意外とそんなに困ることがなく、OSにそこまで依存しないアプリならこれでもいいのではとなったお話

目次

DB周り

DesktopでもRoomを使うことが可能です。
具体的には、androidと違いContextを渡しますが、desktopではfileを渡します。

fun getDatabaseBuilder(): RoomDatabase.Builder<AppDatabase> {
    val dbFile = File(System.getProperty("java.io.tmpdir"), "my_room.db")
    return Room.databaseBuilder<AppDatabase>(
        name = dbFile.absolutePath,
    )
}

これ以外の違いはあんまりなく、通常通り使えば使用できます。

Paging周り

Pagingについては少々癖があります。
androidのpagingライブラリはkmpには対応していますが、cmpには対応していません。
つまり、

  • androidx.paging:paging-common <- 使用可能
  • androidx.paging:paging-compose <- 使用不可能

ということです。
じゃあ、Composeで使う場合Pagingは自分で実装しなきゃいけないじゃん

一応CashAppからmultiplatform-pagingというライブラリが出ており、そちらを使用することが可能です。
こちらのライブラリは、AndroidXのPagingにMultiPlatform用の処理を追加したり、ios用のpaging-uikitなどを追加したりするライブラリになっています。

READMEのInteroperability with AndroidX Pagingを見ていただくとpaging-commonの実装は同じであり,AndroidXのpagingライブラリと相互運用も可能と書いてあります(Paging3に限る)。

そのため、KmpとしてPaging3ですでに書いてあってもrefactorする必要はなく、CMPで使用したい場合は、cashappのpaging-compose-commonを追加して、実装することが可能です。

# これが可能
androidx-paging-common = { group = "androidx.paging", name = "paging-common", version.ref = "androidx-paging" }
cashapp-paging-compose = { group = "app.cash.paging", name = "paging-compose-common", version.ref = "paging-compose" }

File指定

Desktopアプリでは、たびたびFileを指定して何かをすることが多々あると思います。自分で作るとだいぶめんどうな部類の話になると思いますが、Filekitを使うと特にそこまで困ることはなく実装できます。
※一応beta段階なので今後に期待

// main.ktのapplication内
FileKit.init(appId = "MyApplication")

// compose内
val launcher = rememberFilePickerLauncher(
    mode = FileKitMode.Multiple(),
    type = FileKitType.Image,
) { files ->
    // file listが帰ってくる
}

// file選択の実行
launcher.launch()

これでFile選択を実装することができます。modeやtypeなどは必要に応じて指定するとUserが指定したfileを取得することができます。

Mouse操作

Mouse操作に関してもExperimentalではあるものの実装できます。

  • Mouseの移動イベント
Box(
    modifier = Modifier
        .onPointerEvent(PointerEventType.Move) {
            val position = it.changes.first().position
        }
){}
  • MouseのHoverイベント
Box(
    modifier = Modifier
        .onPointerEvent(PointerEventType.Enter) { 
            // hover
        }
        .onPointerEvent(PointerEventType.Exit) { 
            // leave
        },
){}
  • MouseのScrollイベント
Box(
    modifier = Modifier
        .onPointerEvent(PointerEventType.Scroll) {
            val dy = it.changes.first().scrollDelta.y
        }
){}
  • MouseのDrugイベント
Box(
    modifier = Modifier
        .onDrag {
            val offset: Offset it
        }
){}

まとめ

新しくアプリを作るのであれば、CMPという手段もなしではないと思う。
しかし、Win32APIなどOSのAPIを使用したりする場合、C Interopなどを実装しなくては行けなく、自分なら使わないかなぁと思う。

意外とそこまで困ることもそんなになくいけんくない
使ったっていいし、使わなくったっていい

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?