You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

225 lines
7.2 KiB

# Integration Compose for Desktop into Swing-based application
## What is covered
In this tutorial, we will show you how to use ComposePanel and SwingPanel in your application.
## Using ComposePanel
4 years ago
ComposePanel lets you create a UI using Compose for Desktop in a Swing-based UI. To achieve this you need to create an instance of ComposePanel, add it to your Swing layout, and describe the composition inside `setContent`. You may also need to clear the CFD application events via `AppManager.setEvents`.
```kotlin
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
3 years ago
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Button
import androidx.compose.material.Surface
3 years ago
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
3 years ago
import androidx.compose.ui.awt.ComposePanel
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import java.awt.BorderLayout
import java.awt.Dimension
import javax.swing.JButton
3 years ago
import javax.swing.JFrame
import javax.swing.SwingUtilities
import javax.swing.WindowConstants
val northClicks = mutableStateOf(0)
val westClicks = mutableStateOf(0)
val eastClicks = mutableStateOf(0)
3 years ago
fun main() = SwingUtilities.invokeLater {
val window = JFrame()
// creating ComposePanel
val composePanel = ComposePanel()
window.defaultCloseOperation = WindowConstants.EXIT_ON_CLOSE
window.title = "SwingComposeWindow"
3 years ago
window.contentPane.add(actionButton("NORTH", action = { northClicks.value++ }), BorderLayout.NORTH)
window.contentPane.add(actionButton("WEST", action = { westClicks.value++ }), BorderLayout.WEST)
window.contentPane.add(actionButton("EAST", action = { eastClicks.value++ }), BorderLayout.EAST)
window.contentPane.add(
actionButton(
text = "SOUTH/REMOVE COMPOSE",
action = {
window.contentPane.remove(composePanel)
}
),
BorderLayout.SOUTH
)
// addind ComposePanel on JFrame
window.contentPane.add(composePanel, BorderLayout.CENTER)
// setting the content
composePanel.setContent {
ComposeContent()
}
window.setSize(800, 600)
3 years ago
window.isVisible = true
}
3 years ago
fun actionButton(text: String, action: () -> Unit): JButton {
val button = JButton(text)
3 years ago
button.toolTipText = "Tooltip for $text button."
button.preferredSize = Dimension(100, 100)
button.addActionListener { action() }
return button
}
@Composable
fun ComposeContent() {
Box(
modifier = Modifier.fillMaxSize(),
4 years ago
contentAlignment = Alignment.Center
) {
Row {
Counter("West", westClicks)
Spacer(modifier = Modifier.width(25.dp))
Counter("North", northClicks)
Spacer(modifier = Modifier.width(25.dp))
Counter("East", eastClicks)
}
}
}
@Composable
fun Counter(text: String, counter: MutableState<Int>) {
Surface(
modifier = Modifier.size(130.dp, 130.dp),
color = Color(180, 180, 180),
shape = RoundedCornerShape(4.dp)
) {
Column {
Box(
modifier = Modifier.height(30.dp).fillMaxWidth(),
4 years ago
contentAlignment = Alignment.Center
) {
Text(text = "${text}Clicks: ${counter.value}")
}
Spacer(modifier = Modifier.height(25.dp))
Box(
modifier = Modifier.fillMaxSize(),
4 years ago
contentAlignment = Alignment.Center
) {
Button(onClick = { counter.value++ }) {
Text(text = text, color = Color.White)
}
}
}
}
}
```
![IntegrationWithSwing](screenshot.png)
3 years ago
## Adding a Swing component to CFD composition using SwingPanel
SwingPanel lets you create a UI using Swing in a Compose-based UI. To achieve this you need to create Swing `JComponent` in the `factory` parameter of `SwingPanel`.
```kotlin
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.size
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
3 years ago
import androidx.compose.ui.awt.SwingPanel
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
3 years ago
import androidx.compose.ui.window.singleWindowApplication
import java.awt.Component
import javax.swing.BoxLayout
import javax.swing.JButton
import javax.swing.JPanel
3 years ago
fun main() = singleWindowApplication {
val counter = remember { mutableStateOf(0) }
3 years ago
val inc: () -> Unit = { counter.value++ }
val dec: () -> Unit = { counter.value-- }
3 years ago
Box(
modifier = Modifier.fillMaxWidth().height(60.dp).padding(top = 20.dp),
contentAlignment = Alignment.Center
) {
Text("Counter: ${counter.value}")
}
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center
) {
Column(
modifier = Modifier.padding(top = 80.dp, bottom = 20.dp)
) {
3 years ago
Button("1. Compose Button: increment", inc)
Spacer(modifier = Modifier.height(20.dp))
SwingPanel(
background = Color.White,
modifier = Modifier.size(270.dp, 90.dp),
factory = {
JPanel().apply {
layout = BoxLayout(this, BoxLayout.Y_AXIS)
add(actionButton("1. Swing Button: decrement", dec))
add(actionButton("2. Swing Button: decrement", dec))
add(actionButton("3. Swing Button: decrement", dec))
}
3 years ago
}
)
3 years ago
Spacer(modifier = Modifier.height(20.dp))
Button("2. Compose Button: increment", inc)
}
}
}
@Composable
fun Button(text: String = "", action: (() -> Unit)? = null) {
Button(
modifier = Modifier.size(270.dp, 30.dp),
onClick = { action?.invoke() }
) {
Text(text)
}
}
fun actionButton(
text: String,
3 years ago
action: () -> Unit
): JButton {
val button = JButton(text)
3 years ago
button.alignmentX = Component.CENTER_ALIGNMENT
button.addActionListener { action() }
return button
}
```
![IntegrationWithSwing](swing_panel.gif)