Compose跨平台第一弹:体验Compose for Desktop

news2024/12/25 1:21:47

前言

Compose是Android官方提供的声明式UI开发框架,而Compose Multiplatform是由JetBrains 维护的,对于Android开发来说,个人认为学习Jetpack Compose是必须的,因为它会成为Android主流的开发模式,而compose-jb作为一个扩展能力,我们可以有选择的去尝试。今天我们先来了解一下使用compose-jb开发一个桌面端应用的流程。

接下来还会有第二弹,第三弹...

环境要求

开发Compose for Desktop环境要求主要有两点:

  • JDK 11或更高版本

  • IntelliJ IDEA 2020.3 或更高版本(也可以使用AS,这里为了使用IDEA提供的项目模板)

接着我们来一步步体验Compose for Desktop的开发流程。

开发流程

创建项目

下载好IDEA后,我们直接新建项目,选择Compose Multipalteform类型,输入项目名称,这里只选择Single platform且平台为Desktop即可。

 创建好项目后,来看项目目录结构,目录结构如下图所示。

 

在配置文件中指定了程序入口为MainKt以及包名、版本号等。MainKt文件代码如下所示。

@Composable
@Preview
fun App() {
    var text by remember { mutableStateOf("Hello, World!") }

    MaterialTheme {
        Button(onClick = {
            text = "Hello, Desktop!"
        }) {
            Text(text)
        }
    }
}

fun main() = application {
    Window(onCloseRequest = ::exitApplication) {
        App()
    }
}

在MainKt文件中,入口处调用了App()方法,App方法中绘制了一个按钮,运行程序,结果如下图所示。

我们可以看到一个Hello World的桌面端程序就显示出来了。接下来我们来添加一些页面元素。

添加输入框

为了让桌面端程序更“像样子”,我们首先修改桌面程序的标题为“学生管理系统”,这毕竟是我们学生时代最喜欢的名字。代码如下所示:

fun main() = application {
    Window(onCloseRequest = ::exitApplication, title = "学生管理系统") {
        App()
    }
}

在App方法中,添加两个输入框分别为学号、密码,添加一个登陆按钮,写法与Android中的Compose一致,代码如下所示。

MaterialTheme {
    var name by remember {
        mutableStateOf("")
    }
    var password by remember {
        mutableStateOf("")
    }
    Column {
        TextField(name, onValueChange = {
            name = it
        }, placeholder = {
            Text("请输入学号")
        })
        TextField(password, onValueChange = {
            password = it
        }, placeholder = {
            Text("请输入密码")
        })
        Button(onClick = {

        }) {
            Text("登陆")
        }
    }

}

再次运行程序,页面如下所示。

 

添加头像

接着我们再来添加头像显示,我们将下载好的图片资源放在resources目录下

然后使用Image组件将头像显示出来即可,代码如下所示。

Image(
    painter = painterResource("photo.png"),
    contentDescription = null,
    modifier = Modifier.size(width = 100.dp, height = 100.dp)
        .clip(CircleShape)
)

再次运行程序,结果如下所示。

 

当然我们还可以将布局稍微修饰一下,使得布局看起来更好看一些。但这并不是这里的重点。

添加退出弹窗

当我们点击左上角(macOS)的X号时,应用程序就直接退出了,这是因为在Window函数中指定了退出事件,再来看一下这部分代码,如下所示。

fun main() = application {
    Window(onCloseRequest = ::exitApplication, title = "学生管理系统") {
        App()
    }
}

接下来我们增加一个确认退出的弹窗提醒。代码如下所示。

fun main() = application {

    var windowsOpen by remember {
        mutableStateOf(true)
    }
    var isClose by remember {
        mutableStateOf(false)
    }
    if (windowsOpen) {
        Window(onCloseRequest = { isClose = true }, title = "学生管理系统") {
            App()
            if (isClose) {
                Dialog(onCloseRequest = { isClose = false }, title = "确定退出应用程序吗?") {
                    Row {
                        Button(onClick = {
                            windowsOpen = false
                        }) {
                            Text("确定")
                        }
                    }
                }
            }
        }
    }

}

这里我们新增了两个变量windowsOpen、isClose分别用来控制应用程序的Window是否显示与确认弹窗的显示。这部分代码相信使用过Jetpack Compose的都可以看得懂。

运行程序,点击X号,弹出退出确认弹窗,点击确定,应用程序将退出。效果如下图所示。

 

实现一个网络请求功能

在 Kotlin 跨平台开发入门 中我们借用「wanandroid」中「每日一问」接口实现了一个网络请求,现在我们将这部分功能移植到Desktop程序中,网络请求框架仍然使用Ktor,当然其实你也可以使用Retrofit,这一点并不重要。

首先添加Ktor的依赖,代码如下所示。

val jvmMain by getting {
    dependencies {
        implementation(compose.desktop.currentOs)
        implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4")
        val ktorVersion = "2.1.2"
        implementation("io.ktor:ktor-client-core:$ktorVersion")
        implementation("io.ktor:ktor-client-content-negotiation:$ktorVersion")
        implementation("io.ktor:ktor-serialization-kotlinx-json:$ktorVersion")
        implementation("io.ktor:ktor-client-android:$ktorVersion")
    }
}

添加一个Api接口

object Api {
    val dataApi = "https://wanandroid.com/wenda/list/1/json"
}

创建HttpUtil类,用于创建HttpClient对象和获取数据的方法,代码如下所示。

import io.ktor.client.*
import io.ktor.client.call.*
import io.ktor.client.plugins.contentnegotiation.*
import io.ktor.client.request.*
import io.ktor.serialization.kotlinx.json.*
import kotlinx.serialization.json.Json

class HttpUtil {
    private val httpClient = HttpClient {
        install(ContentNegotiation) {
            json(Json {
                prettyPrint = true
                isLenient = true
                ignoreUnknownKeys = true
            })
        }
    }

    /**
     * 获取数据
     */
    suspend fun getData(): String {
        val rockets: DemoReqData =
            httpClient.get(Api.dataApi).body()
        return "${rockets.data} "
    }
}

DemoReqData是接口返回数据对应映射的实体类,这里就不再给出了。

然后我们编写UI,点击按钮开始网络请求,代码如下所示。

Column() {
    val scope = rememberCoroutineScope()
    var demoReqData by remember { mutableStateOf(DemoReqData()) }
    Button(onClick = {
        scope.launch {
            try {
                demoReqData = HttpUtil().getData()
            } catch (e: Exception) {
            }
        }
    }) {
        Text(text = "请求数据")
    }

    LazyColumn {
        repeat(demoReqData.data?.datas?.size ?: 0) {
            item {
                Message(demoReqData.data?.datas?.get(it))
            }
        }
    }
}

获取数据后,通过Message方法将数据展示出来,这里只将作者与标题内容显示出来,代码如下所示。

@Composable
fun Message(data: DemoReqData.DataBean.DatasBean?) {
    Card(
        modifier = Modifier
            .background(Color.White)
            .padding(10.dp)
            .fillMaxWidth(), elevation = 10.dp
    ) {
        Column(modifier = Modifier.padding(10.dp)) {
            Text(
                text = "作者:${data?.author}"
            )
            Text(text = "${data?.title}")
        }
    }
}

运行程序,点击“请求数据”,结果如下图所示。

 

这样我们就实现了一个简单的桌面端数据请求与显示功能。

写在最后

当然,在Compose For Desktop中还有许多的组件,比如Tooltips、Context Menu等等,这里无法一一介绍,需要我们在使用的时候去实践,我们将在后面的N弹中持续探索...

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/144458.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

TikTok三大流行趋势 钛动带你看懂TikTok

武汉瑞卡迪电子商务有限公司:近日,TikTok for Business发布了《Whats Next 2023 TikTok 全球流行趋势报告》,就2023年TikTok三大趋势主题进行了介绍。 钛动科技作为TikTok官方授权代理商,是TikTok生态服务最齐全的出海服务商,凭借出色的技术与服务能力,钛动斩获了T…

论 G1 收集器的架构和如何做到回收时间用户设定

目录G1 概念JVM的内存分代假设让用户设置应用的暂停时间G1 概念 G1其实是Garbage First的意思,它不是垃圾优先的意思,而是优先处理那些垃圾多的内存块的意思。 在大的理念上,它还是遵循JVM的内存分代假设。 JVM的内存分代假设 JVM的内存分代…

https如何加密解密?

背景 我们知道,https,在网络传输中,加密。具体来说是数据加密。//客户端和服务器,写数据的时候,都会加密。即1.客户端——》服务器 2.服务器——》客户端。 如何加密 解密? 加密解密 想要加密和解密&am…

【Mysql篇】数据库事务

目录 数据库事务数据库事务介绍 JDBC事务处理 事务的ACID属性 数据库的并发问题 数据库提供的4种事务隔离级别: 在MySql中设置隔离级别 数据库事务数据库事务介绍 事务:一组逻辑操作单元,使数据从一种状态变换到另一种状态。 事务处理(…

Day1. Spring

1 课程描述IoC基础容器,主要涉及Bean对象的管理。AOP面向切面编程,主要涉及切面配置,声明式事务控制Spring整合Web环境。Web层解决方案-SpringMVC.1.1 IoC、DI和AOP思想的提出由于传统的JavaWeb出现的问题:问题1:层与层…

【问题记录】Process finished with exit code -1073740791 (0xC0000409) 注:LSTM股票预测案例中

目录 1. 问题来源2. 问题解决1. 问题来源 在跑一段 LSTM&神经网络 股票预测的代码时,遇到了下述报错,报错提示为: Process finished with exit code -1073740791 (0xC0000409) 报错截图为: 下面是整个报错的内容,这里我也截取下来了: H:\Python学习专用\深度学习\LS…

ECMAScript基础入门

JavaScript(浏览器端)ECMAScript(语法API)DOMBOM es6开始let代替var声明变量(初始化后可重新赋值),而const声明常量(初始化后不可重新赋值,否则会报错) con…

Java调用百度OCR接口实现文字识别

博主在项目开发中需要完成一个文字识别功能,由于之前有过使用百度云平台接口进行身份证识别的经历,因此这次也是自然而然的再次选择了百度AI平台,首先需要开通百度通用文字识别功能。 然后我们需要创建一个应用: 然后我们就可以…

TensorFlow 基础(一)张量

文章目录BasicsAbout shapesIndexingSingle-axis indexingMulti-axis indexingManipulating ShapesMore on dtypesReferencesimport tensorflow as tf import numpy as npBasics 张量是具有统一类型(dtype)的多维数组。它和 NumPy 中的 np.arrays 是非常…

C进阶_C语言_函数与指针_C语言指针进阶

上一篇博客http://t.csdn.cn/GYCiM 我们了解了指针相关知识,今天来了解函数和指针的关系。 目录 函数指针 函数指针数组 指向函数指针数组的指针 回调函数 qsort 冒泡排序模拟实现qsort 函数指针 我们知道,数组指针是指向数组的指针。 int arr[…

Ribbon负载均衡服务调用

文章目录一. 什么是Ribbon二. Ribbon负载均衡三. Ribbon负载均衡策略四. Ribbon饥饿加载一. 什么是Ribbon PS: 本篇文章文作者学习笔记,技术参考价值不大。 Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端,负载均衡的工具。 简单的说&#x…

Allegro174版本新功能介绍之改变报表字体大小

Allegro174版本新功能介绍之改变报表字体大小 Allegro在升级到174的时候,默认show element的字体是非常小的,类似下图,辨认起来非常困难 但是174是支持把字体调整的大一些的,具体操作如下 选择Setup选择User Preferences

SpringBoot整合java诊断工具Arthas

一、Arthas官方文档https://arthas.aliyun.com/doc/二、springBoot整合方式1、pom文件引入<dependency><groupId>com.taobao.arthas</groupId><artifactId>arthas-spring-boot-starter</artifactId><version>3.6.7</version> </d…

机器学习:机器学习常见的算法分类和算法优缺点汇总

机器学习实战教程(13篇)_M_Q_T的博客-CSDN博客这些网址非常适合想学习机器学习&#xff0c;却苦于没有项目&#xff08;尤其缺少数据&#xff09;的人。无意中看到&#xff0c;给自己做一个记录。目录大类&#xff1a;学习方式监督式学习&#xff1a;非监督式学习&#xff1a;半…

ES6 课程概述③

文章目录5-1. 新增的对象字面量语法5-2. Object 的新增 API5-4 类&#xff1a;构造函数的语法糖传统的构造函数的问题类的特点5-5. 类的其他书写方式5-1. 新增的对象字面量语法 成员速写 如果对象字面量初始化时&#xff0c;成员的名称来自于一个变量&#xff0c;并且和变量的…

2023/01/05 java面试题每日10问

1.What is Java? Java is object-oriented, platform-independent, Multithreaded, and portable programming language.it provides its own JRE and API. 2.What is the difference between JDK, JRE, and JVM? JVM Java Virtual Machine provides the runtime environm…

小小闭门会,揭示SaaS大趋势

从2014年中国的SaaS领域开始有融资到现在已经8年&#xff0c;从最开始的一张云图填不满到现在的密密麻麻&#xff0c;厂商和产品如雨后春笋般的多了起来&#xff0c;但很多SaaS依然在孤军奋战&#xff0c;很多厂商陷入定制化泥潭。有人说中国的SaaS有特殊国情&#xff0c;大企业…

【bioinfo】酶切法片段化建库相比超声打断建库引入softclip使用FADE软件识别/去除

FADE软件参考文献 参考文献&#xff1a;片段化酶诱导的双链伪影的表征和缓解 - PMC (nih.gov) 文献提供的酶切产生的错误识别和去除软件FADE&#xff1a;软件git地址 文献补充材料图&#xff1a;由酶切产生的人工错误序列的碱基质量值偏高&#xff0c;相对其他softclip的质量…

适配Dell R750xs server Broadcom BCM57412 NetXtreme-E 10Gb SFP+ 网卡

摘要 The Issue is to handle Scaler v8.2-385 (baf7f3a) on Dell R750xs server, the 10G NIC card is Broadcom BCM57412 NetXtreme-E 10Gb SFP. Firmware is the latest, but driver is not. The symptom is that only one port or no port could be recognized. After patc…

基于MAX7800羽毛板语音控制ESP8266小车

1. 项目介绍 基于MAX7800羽毛板语音控制ESP8266小车 采用现成的KWS20关键词&#xff0c;[up, down, left, right, stop, go, yes, no, on, off, one, two, three, four, five, six, seven, eight, nine, zero]&#xff0c;进行语音关键字识别远程控制小车。 2. 项目设计思路 搭…