@@ -12,23 +12,52 @@ import androidx.compose.ui.Modifier
1212import androidx.compose.ui.tooling.preview.Preview
1313import com.pythonnative.pythonnative.ui.theme.PythonnativeTheme
1414
15+ import android.graphics.BitmapFactory
16+ import android.widget.Toast
17+ import androidx.compose.foundation.Image
18+ import androidx.compose.foundation.layout.Arrangement
19+ import androidx.compose.foundation.layout.Column
20+ import androidx.compose.foundation.layout.fillMaxWidth
21+ import androidx.compose.foundation.layout.padding
22+ import androidx.compose.foundation.layout.wrapContentHeight
23+ import androidx.compose.material3.ExperimentalMaterial3Api
24+ import androidx.compose.material3.OutlinedTextField
25+ import androidx.compose.runtime.*
26+ import androidx.compose.ui.graphics.asImageBitmap
27+ import androidx.compose.ui.layout.ContentScale
28+ import androidx.compose.ui.platform.LocalContext
29+ import androidx.compose.ui.unit.dp
30+ import com.chaquo.python.PyException
31+ import com.chaquo.python.Python
32+ import com.chaquo.python.android.AndroidPlatform
33+ import kotlinx.coroutines.Dispatchers
34+ import kotlinx.coroutines.launch
35+ import kotlinx.coroutines.withContext
36+ import androidx.compose.material3.Button
37+ import androidx.compose.material3.Text
38+ import androidx.compose.ui.ExperimentalComposeUiApi
39+ import androidx.compose.ui.platform.LocalSoftwareKeyboardController
40+
41+
42+
43+
1544class MainActivity : ComponentActivity () {
1645 override fun onCreate (savedInstanceState : Bundle ? ) {
1746 super .onCreate(savedInstanceState)
1847 setContent {
1948 PythonnativeTheme {
20- // A surface container using the 'background' color from the theme
2149 Surface (
2250 modifier = Modifier .fillMaxSize(),
2351 color = MaterialTheme .colorScheme.background
2452 ) {
25- Greeting ( " Android " )
53+ MainScreen ( )
2654 }
2755 }
2856 }
2957 }
3058}
3159
60+
3261@Composable
3362fun Greeting (name : String , modifier : Modifier = Modifier ) {
3463 Text (
@@ -43,4 +72,70 @@ fun GreetingPreview() {
4372 PythonnativeTheme {
4473 Greeting (" Android" )
4574 }
46- }
75+ }
76+
77+ @OptIn(ExperimentalMaterial3Api ::class , ExperimentalComposeUiApi ::class )
78+ @Composable
79+ fun MainScreen () {
80+ val context = LocalContext .current
81+ var bitmap by remember { mutableStateOf< android.graphics.Bitmap ? > (null ) }
82+ val coroutineScope = rememberCoroutineScope()
83+
84+ // Initialize Chaquopy
85+ if (! Python .isStarted()) {
86+ Python .start(AndroidPlatform (context))
87+ }
88+ val py = Python .getInstance()
89+ val plotModule = py.getModule(" plot" )
90+
91+ // Variables to keep the user's input
92+ var xInput by remember { mutableStateOf(" " ) }
93+ var yInput by remember { mutableStateOf(" " ) }
94+
95+ val keyboardController = LocalSoftwareKeyboardController .current
96+
97+ Column (
98+ modifier = Modifier .padding(16 .dp),
99+ verticalArrangement = Arrangement .spacedBy(16 .dp)
100+ ) {
101+ OutlinedTextField (
102+ value = xInput,
103+ onValueChange = { xInput = it },
104+ label = { Text (" Input X" ) }
105+ )
106+ OutlinedTextField (
107+ value = yInput,
108+ onValueChange = { yInput = it },
109+ label = { Text (" Input Y" ) }
110+ )
111+ Button (onClick = {
112+ coroutineScope.launch {
113+ try {
114+ val bytes = plotModule.callAttr(
115+ " plot" ,
116+ xInput,
117+ yInput
118+ ).toJava(ByteArray ::class .java)
119+ withContext(Dispatchers .IO ) {
120+ bitmap = BitmapFactory .decodeByteArray(bytes, 0 , bytes.size)
121+ }
122+ } catch (e: PyException ) {
123+ Toast .makeText(context, e.message, Toast .LENGTH_LONG ).show()
124+ }
125+ keyboardController?.hide()
126+ }
127+ }) {
128+ Text (text = " Generate Plot" )
129+ }
130+ bitmap?.let {
131+ Image (
132+ bitmap = it.asImageBitmap(),
133+ contentDescription = " Generated plot" ,
134+ modifier = Modifier
135+ .fillMaxWidth()
136+ .wrapContentHeight(),
137+ contentScale = ContentScale .FillWidth
138+ )
139+ }
140+ }
141+ }
0 commit comments