Compose for Desktopとは
Android Jetpack ComposeをデスクトップOS向けに移植したライブラリ。
公式はCompose for Desktop UI Framework | JetBrains: Developer Tools for Professionals and Teams
AWTとSwingなどとの相互互換性を持ち、Skiaのグラフィックライブラリを使ってクロスプラットフォームを実現している。
実行ファイルにはJRE(JDKかな?)が同梱されるため、ファイルサイズは大きくなるが単体で実行可能。
この記事は?
とりあえず思いつく限りのコンポーネントを表示して、そのコードを示す。
殆どはAndroid JetPack Composeと同じ。一部使えないinfixとかあるけど。
今回のコード全体
compose-desktop-sample/all_widgets at main · iwahara/compose-desktop-sample
試したバージョン
kotlin: 1.4.20
compose for desktop : 0.2.0-build131
ベースウィンドウ
各ボタンをクリックすると、それぞれのコンポーネントを使ったウィンドウが新規表示される。
Text
文字列を表示するコンポーネント。
@Composable
fun TextSample() {
val windowState = remember { mutableStateOf(false) }
Button(onClick = {
windowState.value = true
}) {
Text("Textのサンプル")
}
if (windowState.value) {
Window(title = "Textのサンプル", size = IntSize(600, 600), location = IntOffset(100, 100), centered = false,
onDismissRequest = {
windowState.value = false
}) {
Column {
Text("テキスト")
Divider() //区切り線
Text(AnnotatedString(
text = "複数のスタイルを割り当てる",
spanStyles = listOf(
AnnotatedString.Range(SpanStyle(fontStyle = FontStyle.Italic), 0, 5)
),
paragraphStyles = listOf(
AnnotatedString.Range(ParagraphStyle(textAlign = TextAlign.Center), 0, 6),
)
))
}
}
}
}
Card
@Composable
fun CardSample() {
val windowState = remember { mutableStateOf(false) }
Button(onClick = {
windowState.value = true
}) {
Text("Cardのサンプル")
}
if (windowState.value) {
Window(title = "Cardのサンプル", size = IntSize(600, 600), location = IntOffset(100, 100), centered = false,
onDismissRequest = {
windowState.value = false
}) {
Column {
Card(Modifier.fillMaxWidth().padding(8.dp), elevation = 8.dp) {
Text("カードだよ")
}
}
}
}
}
TextField
@Composable
fun TextFieldSample() {
val windowState = remember { mutableStateOf(false) }
val textField = remember { mutableStateOf("") }
Button(onClick = {
windowState.value = true
}) {
Text("TextFieldのサンプル")
}
if (windowState.value) {
Window(title = "TextFieldのサンプル", size = IntSize(600, 600), location = IntOffset(100, 100),
centered = false,
onDismissRequest = {
windowState.value = false
}) {
Column {
TextField(value = textField.value, onValueChange = {
textField.value = it
}, label = {
Text("ラベル")
}, placeholder = {
Text("プレースホルダー")
})
Text(textField.value)
}
}
}
}
CheckBox
@Composable
fun CheckBoxSample() {
val windowState = remember { mutableStateOf(false) }
val checked = remember { mutableStateOf(true) }
Button(onClick = {
windowState.value = true
}) {
Text("CheckBoxのサンプル")
}
if (windowState.value) {
Window(title = "CheckBoxのサンプル", size = IntSize(600, 600), location = IntOffset(100, 100), centered = false,
onDismissRequest = {
windowState.value = false
}) {
Column {
Checkbox(checked = checked.value,
onCheckedChange = {
checked.value = it
})
Text(if (checked.value) "チェック済み!" else "チェックなし!")
}
}
}
}
RadioButton
@Composable
fun RadioButtonSample() {
val windowState = remember { mutableStateOf(false) }
val selected = remember { mutableStateOf(true) }
Button(onClick = {
windowState.value = true
}) {
Text("RadioButtonのサンプル")
}
if (windowState.value) {
Window(title = "RadioButtonのサンプル", size = IntSize(600, 600), location = IntOffset(100, 100), centered = false,
onDismissRequest = {
windowState.value = false
}) {
Column {
RadioButton(selected = selected.value, onClick = {
selected.value = !selected.value
})
Text(if (selected.value) "選択済み!" else "選択なし!")
}
}
}
}
Switch
@Composable
fun SwitchSample() {
val windowState = remember { mutableStateOf(false) }
val switchChecked = remember { mutableStateOf(false) }
Button(onClick = {
windowState.value = true
}) {
Text("Switchのサンプル")
}
if (windowState.value) {
Window(title = "Switchのサンプル", size = IntSize(600, 600), location = IntOffset(100, 100), centered = false,
onDismissRequest = {
windowState.value = false
}) {
Column {
Switch(checked = switchChecked.value, onCheckedChange = {
switchChecked.value = it
})
Text(if (switchChecked.value) "チェック済み!" else "チェックなし!")
}
}
}
}
Slider
@Composable
fun SliderSample() {
val windowState = remember { mutableStateOf(false) }
val sliderVal = remember { mutableStateOf(0.5f) }
Button(onClick = {
windowState.value = true
}) {
Text("Sliderのサンプル")
}
if (windowState.value) {
Window(title = "Sliderのサンプル", size = IntSize(600, 600), location = IntOffset(100, 100), centered = false,
onDismissRequest = {
windowState.value = false
}) {
Column {
Slider(value = sliderVal.value, onValueChange = {
sliderVal.value = it
}, modifier = Modifier.weight(1f))
Text("Slider ${sliderVal.value}", modifier = Modifier.weight(1f))
}
}
}
}
Progress
@Composable
fun ProgressSample() {
val windowState = remember { mutableStateOf(false) }
val progress = remember { mutableStateOf(0f) }
Button(onClick = {
windowState.value = true
}) {
Text("Progressのサンプル")
}
if (windowState.value) {
Window(title = "Progressのサンプル", size = IntSize(600, 600), location = IntOffset(100, 100), centered = false,
onDismissRequest = {
windowState.value = false
}) {
Column {
Text("progress ${progress.value}")
Slider(value = progress.value, onValueChange = {
progress.value = it
})
LinearProgressIndicator(progress = progress.value)
CircularProgressIndicator(progress = progress.value)
}
}
}
}
DropDownMenu
@Composable
fun DropdownDemo() {
val windowState = remember { mutableStateOf(false) }
val items = listOf("A", "B", "C", "D", "E", "F")
val showMenu = remember { mutableStateOf(false) }
val selectedIndex = remember { mutableStateOf(0) }
Button(onClick = {
windowState.value = true
}) {
Text("DropdownMenuのサンプル")
}
if (windowState.value) {
Window(title = "DropdownMenuのサンプル", size = IntSize(600, 600), location = IntOffset(100, 100), centered = false,
onDismissRequest = {
windowState.value = false
}) {
Column {
DropdownMenu(
toggle = {
Text(items[selectedIndex.value], modifier = Modifier.fillMaxWidth().clickable(onClick = { showMenu.value = true }))
},
expanded = showMenu.value,
onDismissRequest = { showMenu.value = false },
) {
items.forEachIndexed { index, s ->
DropdownMenuItem(
onClick = {
selectedIndex.value = index
showMenu.value = false
}
) {
Text(text = s)
}
}
}
}
}
}
}
SnackBar
@ExperimentalMaterialApi
@Composable
fun SnackBarSample(scaffoldState: ScaffoldState) {
val snackBarVisibleState = remember { mutableStateOf(false) }
val scope = rememberCoroutineScope()
Button(onClick = { snackBarVisibleState.value = true }) {
if (snackBarVisibleState.value) {
Text("Snackbarが表示されてます")
} else {
Text("Snackbarを表示")
}
}
if (snackBarVisibleState.value) {
scope.launch {
when (scaffoldState.snackbarHostState.showSnackbar("スナックバーやでー", "ボタンだよ")) {
SnackbarResult.ActionPerformed -> snackBarVisibleState.value = false
SnackbarResult.Dismissed -> snackBarVisibleState.value = false
}
}
}
}