JetBrains / compose-multiplatform

Compose Multiplatform, a modern UI framework for Kotlin that makes building performant and beautiful user interfaces easy and enjoyable.
https://jetbrains.com/lp/compose-multiplatform
Apache License 2.0
16.15k stars 1.17k forks source link

Changing window icon does not work #1600

Closed brolicious12 closed 1 month ago

brolicious12 commented 2 years ago

when I click the button in the example below, the icon is not changed. Am I doing something wrong or is it a bug?

import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.AccountBox
import androidx.compose.material.icons.filled.BrokenImage
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.graphics.vector.rememberVectorPainter
import androidx.compose.ui.window.Window
import androidx.compose.ui.window.application

val windowIcon = mutableStateOf(Icons.Filled.AccountBox)

fun main() = application {
    Window(onCloseRequest = this::exitApplication,
           icon = rememberVectorPainter(windowIcon.value)) {
        Button(onClick = {
            windowIcon.value = Icons.Filled.BrokenImage
        }) {
            Text("Change icon to BrokenImage")
        }
    }
}
id("org.jetbrains.kotlin.jvm") version ("1.6.10")
id("org.jetbrains.compose") version ("1.0.1-rc2")
Kanialdo commented 2 years ago

@brolicious12 maybe I'm wrong, but for me you passed directy windowIcon.value to rememberVectorPainter and compose isn't "observing" changing of this value and this is fine. You should move val windowIcon = mutableStateOf(Icons.Filled.AccountBox) to application {} block:

fun main() = application {
        val windowIcon = remember { mutableStateOf(Icons.Filled.AccountBox) }

    Window(onCloseRequest = this::exitApplication,
           icon = rememberVectorPainter(windowIcon.value)) {
        Button(onClick = {
            windowIcon.value = Icons.Filled.BrokenImage
        }) {
            Text("Change icon to BrokenImage")
        }
    }
}

thanks to this compose will know that you that it should be remembered and will perform recomposition after changing. Let me know if this helps you

brolicious12 commented 2 years ago

@Kanialdo thanks for the effort but unfortunately it doesn't work with your example either

KotlinGeekDev commented 2 years ago

Please @brolicious12 did you try making windowIcon a var ? (that is, var windowIcon)

brolicious12 commented 2 years ago

@AnonymousGeekDev val windowIcon as far as I understand is itself just an object that holds the state (windowIcon.value). I don't change the object, so it doesn't have to be var (although I tested it with var too, it doesn't work).

KotlinGeekDev commented 2 years ago

@brolicious12 Please did you try using delegation with the by keyword? That is, val windowIcon by remember {

brolicious12 commented 2 years ago

@AnonymousGeekDev I tried it but it didn't work either, I would be surprised if it worked that way and not the other way around without delegation

shenliuyang commented 2 years ago

rememberVectorPainter fun always return the same instance, even argument changed. I use pre allocate icons. it'work ` var titleState = mutableStateOf("new") var iconIndex = mutableStateOf(1) fun main() = application {

var icons = listOf(rememberVectorPainter(Icons.Filled.AccountCircle), rememberVectorPainter(Icons.Filled.Call))

Window(onCloseRequest = this::exitApplication, icon = icons[iconIndex.value % icons.size], title = titleState.value) {
    Button(onClick = {
        iconIndex.value++
    }) {
        Text(titleState.value)
    }
}

}`

KotlinGeekDev commented 2 years ago

@shenliuyang cool!

okushnikov commented 3 months ago

Please check the following ticket on YouTrack for follow-ups to this issue. GitHub issues will be closed in the coming weeks.