案例分析
在使用Compose Desktop的时候,对多个Windows的窗口管理起来总是非常麻烦,因此,这里给出了一种示例,来解决这个问题。
官方案例
如果应用程序有多个窗口,那么最好将其状态放入单独的类中,并打开/关闭窗口以响应更改(有关更复杂的用例,请参阅记事本示例):mutableStateListOf
官方也只是简单的实现了一下,实际上,也说了多窗口需要放入单独的类来实现,这里就给出我的结局方案。
我的代码
废话少说,代码如下,解析附后。
/*
* Copyright (C) 2023 Frank Miles - Frms
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import androidx.compose.runtime.*
object WindowManager
{
private val map = mutableStateMapOf<Int, Pair<@Composable WindowManager.() -> Unit, Boolean> >()
/**
* add key to target content.
*/
fun addWindow(key : Int, defaultDisplay: Boolean = true, content : @Composable WindowManager.() -> Unit) =
map.put(key, content to defaultDisplay)
fun removeWindow(key: Int) : Boolean = (map.remove(key) != null)
/**
* Set display status in existing window.
* @param key Int
* @param display Boolean, display or not
*/
fun setDisplayWindow(key: Int, display : Boolean) {
if(map[key] == null || map[key]!!.second == display) {
return
}
val data = map.remove(key)!!
map[key] = data.first to display
}
/**
* Return window's status if existing else false value.
* @param key Int
* @return Boolean
*/
fun getContentStatus(key: Int) : Boolean = map[key].let {
if(it == null) {
false
} else {
map[key]!!.second
}
}
@Composable
fun showWindows() {
map.forEach {
key(map) {
if(it.value.second) {
it.value.first(WindowManager)
}
}
}
}
}
实现的功能有:添加、隐藏、移除窗口(可以引申为更加宽泛的compose组件,下文一律以窗口替代)。对于添加的窗口,都会有初始键,方便对每个窗口进行操作。操作后,会自动刷新。
比如说:
fun main()
{
WindowManager.addWindow(0) {
Window(onCloseRequest = {}) {
Button(onClick = {}) {
Text("ssss")
}
}
}
WindowManager.addWindow(1)
{
Window(onCloseRequest = {})
{
Button(onClick = {
setDisplayWindow(0, getContentStatus(0).not())
}) {
Text("saaaa")
}
}
}
application {
WindowManager.showWindows()
}
}
这段代码里,添加了两个窗口,第二个窗口点击按钮后,会设置前一个窗口的状态。因为接受的窗口参数类型是@Composable WindowManager.() -> Unit
,因此,在点击时,可以直接使用内部方法setDisplayWindow
等。