I want to display a WritableImage in imageview, but I want that image to change when the user loads in a new file from the file browser. I know that there is a bind() function for strings that change over time, but I could not find a similar option for images. I could solve the problem for images that are the same size as the default loaded one (with writing through the pixels), but that only works if they are the same size, since I cant modify the size of the image that I displayed. My Kotlin code so far:
class PhotoView : View("Preview") {
val mainController: mainController by inject()
override val root = hbox {
imageview{
image = mainController.moddedImg
}
hboxConstraints {
prefWidth = 1000.0
prefHeight = 1000.0
}
}
class ControlView: View(){
val mainController: mainController by inject()
override val root = hbox{
label("Controls")
button("Make BW!"){
action{
mainController.makeBW()
}
}
button("Choose file"){
action{
mainController.setImage()
mainController.update()
}
}
}
}
class mainController: Controller() {
private val ef = arrayOf(FileChooser.ExtensionFilter("Image files (*.png, *.jpg)", "*.png", "*.jpg"))
private var sourceImg=Image("pic.png")
var moddedImg = WritableImage(sourceImg.pixelReader, sourceImg.width.toInt(), sourceImg.height.toInt())
fun setImage() {
val fn: List<File> =chooseFile("Choose a photo", ef, FileChooserMode.Single)
sourceImg = Image(fn.first().toURI().toString())
print(fn.first().toURI().toString())
}
fun makeBW() {
val pixelReader = sourceImg.pixelReader
val pixelWriter = moddedImg.pixelWriter
// Determine the color of each pixel in a specified row
for (i in 0 until sourceImg.width.toInt()) {
for (j in 0 until sourceImg.height.toInt()) {
val color = pixelReader.getColor(i, j)
pixelWriter.setColor(i, j, color.grayscale())
}
}
}
fun update() {
val pixelReader = sourceImg.pixelReader
val pixelWriter = moddedImg.pixelWriter
// Determine the color of each pixel in a specified row
for (i in 0 until sourceImg.width.toInt()) {
for (j in 0 until sourceImg.height.toInt()) {
val color = pixelReader.getColor(i, j)
pixelWriter.setColor(i, j, color)
}
}
}
}
ImageView
has a property for the image that you can bind:
class PhotoView : View("Preview") {
val main: MainController by inject()
val root = hbox {
imageview { imageProperty().bind(main.currentImageProperty) }
...
}
...
}
class MainController : Controller() {
val currentImageProperty = SimpleObjectProperty<Image>(...)
var currentImage by currentImageProperty // Optional
...
}
From there, any time you set the currentImage
in MainController
, it will update in the PhotoView
.