Swing에서 Jetpack Compose 데스크탑까지 #2

10977 단어 uxkotlinjava
Java Swing 앱을 데스크톱용 Jetpack Compose로 변환하는 여정에 대한 두 번째 게시물에 오신 것을 환영합니다. 오늘은 한 가지 주제만 선택하겠습니다. 즉, 작업을 시작하십시오. UI를 기억한다면 중복 파일을 검색하기 위한 기본 디렉토리를 포함하는 텍스트 필드가 있습니다.



아이디어는 유효한 경로를 입력한 다음 찾기를 클릭하는 것입니다. 분명히 해당 조건이 충족되는 경우에만 버튼이 활성화되어야 합니다. 컴포저블FirstRow은 현재 한 가지 상태를 기억합니다.

val name = remember { mutableStateOf(TextFieldValue("")) }


따라서 다음과 같이 버튼 코드를 쉽게 추가할 수 있습니다.

Button(
        onClick = {},
        modifier = Modifier.alignByBaseline(),
        enabled = File(name.value.text).isDirectory
) {
    Text("Find")
}


텍스트 필드는 기본 클립보드에서 작동하므로 경로가 문자열인 경우 Ctrl-V 또는 Cmd-V로 붙여넣을 수 있습니다. 그러나 그것은 특히 데스크탑 파이가 아닙니다. 데스크탑 운영 체제의 주요 기능은 다중 창을 지원하는 것입니다. 따라서 기본 파일 관리자에서 폴더를 선택하고 싶을 것입니다. 맞습니까?

저는 데스크톱용 Jetpack Compose 초보자이며 이것을 놓쳤을 수도 있지만 지금까지 드래그 앤 드롭 지원을 보지 못했습니다. 그래서 스스로 이 일을 하기로 했습니다. 데스크톱용 Jetpack Compose 최상위 창은 Swing과 쉽게 상호작용할 수 있으므로 여기에서 드래그 앤 드롭 기능을 빌릴 수 있습니다. 이것이 일반적으로 어떻게 작동하는지 봅시다:

val target = object : DropTarget() {
    @Synchronized
    override fun drop(evt: DropTargetDropEvent) {
        try {
            evt.acceptDrop(DnDConstants.ACTION_REFERENCE)
            val droppedFiles = evt
                    .transferable.getTransferData(
                            DataFlavor.javaFileListFlavor) as List<*>
            for (file in droppedFiles) {
                println((file as File).absolutePath)
            }
        } catch (ex: Exception) {
            ex.printStackTrace()
        }
    }
}
AppManager.windows.first().window.contentPane.dropTarget = target

DropTarget는 Swing 항목이므로 자세히 설명하지 않겠습니다. 하지만 이 코드는 드롭된 파일의 이름만 출력한다는 점을 명심하십시오. 텍스트 필드를 업데이트하려면 for 루프를 변경해야 합니다. 곧 이에 대해 자세히 알아보십시오. 하지만 먼저 마지막 줄을 살펴보겠습니다(말장난 의도 없음). AppManager.windows는 응용 프로그램의 모든 창 목록을 제공합니다. TKDupeFinder에는 기본 창 하나만 있습니다. 그래서 우리는 이것을 first()로 얻을 수 있습니다. 이것은 androidx.compose.desktop.AppFrame 의 인스턴스입니다. windowComposeWindow를 확장하는 JFrame입니다. 이것이 우리가 contentPane에 액세스하고 놓기 대상을 설정할 수 있는 이유입니다.

멋지죠? 이 세션을 마치기 위해 텍스트 필드를 업데이트하는 방법은 다음과 같습니다. 먼저 약간 변경된main() 기능:

fun main() {
    invokeLater {
        AppWindow(title = "TKDupeFinder",
                size = IntSize(600, 400)).show {
            TKDupeFinderContent()
        }
    }
}

TKDupeFinderContent는 컴포저블입니다. 보시다시피 name를 기억하고 FirstRow로 전달합니다(이것도 새로운 것임). 드래그 시 업데이트name가 필요하기 때문에 이렇게 합니다.

@Composable
fun TKDupeFinderContent() {
    val name = remember { mutableStateOf(TextFieldValue("")) }
    DesktopMaterialTheme {
        Column() {
            FirstRow(name)
            SecondRow()
            ThirdRow()
        }
    }
    val target = object : DropTarget() {
        @Synchronized
        override fun drop(evt: DropTargetDropEvent) {
            try {
                evt.acceptDrop(DnDConstants.ACTION_REFERENCE)
                val droppedFiles = evt
                        .transferable.getTransferData(
                                DataFlavor.javaFileListFlavor) as List<*>
                droppedFiles.first()?.let {
                    name.value = TextFieldValue((it as File).absolutePath)
                }
            } catch (ex: Exception) {
                ex.printStackTrace()
            }
        }
    }
    AppManager.windows.first().window.contentPane.dropTarget = target
}



내 코드는 하나의 파일 또는 폴더만 창으로 끌어온 것으로 가정합니다. 더 있으면 첫 번째 항목( droppedFiles.first() )을 사용합니다. 경로( absolutePath )는 TextFieldValue 로 래핑되어야 합니다. 다음 클립은 이것이 macOS에서 어떻게 보이는지 보여줍니다.



꽤 멋지죠? 다음 포스트는 중복에 대한 실제 검색을 다룰 것입니다. 계속 지켜봐주십시오. 첫 번째 부분을 놓친 경우 읽을 수 있습니다. TKDupeFinder 저장소가 켜져 있습니다GitHub.

좋은 웹페이지 즐겨찾기