Heim> Java> Hauptteil

Laden Sie JavaFX-Bilder und speichern Sie sie in der Datenbank

WBOY
Freigeben: 2024-02-22 14:49:06
nach vorne
1138 Leute haben es durchsucht

JavaFX ist ein grafisches Benutzeroberflächen-Toolkit für die Programmiersprache Java, mit dem sich auf einfache Weise umfangreiche, moderne Benutzeroberflächen erstellen lassen. In der tatsächlichen Entwicklung ist es manchmal erforderlich, JavaFX-Bilder zu laden und in der Datenbank zu speichern. Dieser Artikel stellt Ihnen die Vorgehensweise vor und hilft Ihnen, dieses Problem durch einfache und leicht verständliche Schritte zu lösen. Lassen Sie uns gemeinsam darüber diskutieren!

Frageninhalt

Ich versuche gerade, ein kleines Bild in einer Datenbank zu speichern und es zu laden, um es als javafx.scene.image.Image zu verwenden. Einige Lösungen, die ich ausprobiert habe, beinhalten die Verwendung von SwingFXUtils.fromFXImage und SwingFXUtils.toFxImage, aber diese Klasse scheint einen Eintrag in der Datei module-info.java zu erfordern, den ich gar nicht zu verwenden versuche.

Beim Versuch, SwingFXUtils zu verwenden, ist diese Ausnahme aufgetreten:java.lang.NoClassDefFoundError: javafx/embed/swing/SwingFXUtils.

Als ich das Modulsystem verwendet habe, hat es eine andere Bibliothek, die ich verwendet habe, kaputt gemacht (itextpdf). Deshalb möchte ich dies vermeiden und einfach eine andere Möglichkeit finden, JavaFX-Bilder aus der Datenbank zu speichern und zu laden. Irgendwelche Vorschläge?

Lösung

Sie haben erwähnt:

Das ist nicht wahr. Obwohl Javafx nur das Laden von1als benannte Module unterstützt, erfordert Javafx nicht, dass Ihr eigener Code modular ist. Die einzige Möglichkeit,zu erhalten, besteht darin, die Klasse zur Laufzeit nicht in den Modulpfad/Klassenpfad aufzunehmen (sie muss zur Kompilierungszeit vorhanden sein, sonst wird Ihr Code nicht kompiliert). Ich empfehle die Lektüre von „Erste Schritte mit JavaFX“, um zu erfahren, wie man eine einfache JavaFX-Anwendung mit einer der wichtigsten Java-IDEs und/oder Build-Tools einrichtet. Ohne zu wissen, wie Sie Ihr Projekt konfigurieren und ausführen, können wir Ihnen jedoch nicht sagen, was genau mit Ihrem Setup nicht stimmt.Das heißt, das Gesamtziel, das Sie erreichen möchten, ist tatsächlich möglich. Unten finden Sie ein Beispiel, mit dem Sie auf Ihrem Computer nach Bildern suchen und diese in einer speicherinternen h2-Datenbank speichern können. Die ID und der Name des Bildes werden in die Klasseeingefügt, die zum Konvertieren von JavaFX-Bildern in PNG-„Dateien“noclassdeffounderror2

verwendet wird.

tableview中,其中包含一个带有“打开”按钮的列,可让您查看从内存数据库加载的图像。图像以 png 格式作为 blob 存储在数据库中,无论其原始格式如何。swingfxutilsimageioDas Beispiel zeigt Ihnen nicht, wie Sie die Anwendung bereitstellen (z. B. über).Version

Hier sind die Versionen der Bibliotheken und Tools, die ich zum Erstellen und Ausführen der Beispiele verwendet habe.

jpackage

Java 21.0.1 (Eclipse Adoptium/Temurin)

    javafx 21.0.1
  • h2 2.2.224
  • Gradle 8.4
  • JavaFX Gradle Plugin

    0.1.0

  • ImKommentarzur

    vorherigen Frage

2haben Sie angegeben, dass Sie Gradle verwenden, daher verwende ich Gradle im Beispiel.QuellcodeKeineDatei.

imagerecord.java

package com.example; public record imagerecord(int id, string name) {}
Nach dem Login kopieren
module-info.java

main.java

package com.example; import java.io.file; import java.util.concurrent.executor; import java.util.concurrent.executors; import java.util.function.consumer; import javafx.application.application; import javafx.beans.property.simpleintegerproperty; import javafx.beans.property.simpleobjectproperty; import javafx.beans.property.simplestringproperty; import javafx.concurrent.task; import javafx.geometry.insets; import javafx.geometry.pos; import javafx.scene.scene; import javafx.scene.control.button; import javafx.scene.control.scrollpane; import javafx.scene.control.tablecell; import javafx.scene.control.tablecolumn; import javafx.scene.control.tableview; import javafx.scene.image.image; import javafx.scene.image.imageview; import javafx.scene.layout.borderpane; import javafx.scene.layout.hbox; import javafx.stage.filechooser; import javafx.stage.stage; import javafx.stage.stagestyle; import javafx.stage.window; public class main extends application { private final executor executor = executors.newvirtualthreadpertaskexecutor(); private final imagesdatabase db = new imagesdatabase("test"); private final imagerepository imagerepo = new imagerepository(db); private file lastdirectory; @override public void start(stage primarystage) { var table = createtable(record -> displayimage(primarystage, record)); var choosebtn = new button("choose image..."); choosebtn.setonaction( e -> { e.consume(); var image = chooseimage(primarystage); if (image != null) { executor.execute(createsaveimagetask(image, table.getitems()::add)); } }); var root = new borderpane(); root.settop(choosebtn); root.setcenter(table); borderpane.setalignment(choosebtn, pos.center); borderpane.setmargin(choosebtn, new insets(10)); primarystage.setscene(new scene(root, 600, 400)); primarystage.show(); } @override public void stop() throws exception { db.close(); } private image chooseimage(window owner) { var chooser = new filechooser(); chooser.settitle("choose image file"); chooser .getextensionfilters() .add(new filechooser.extensionfilter("image files", "*.jpeg", "*.jpg", "*.png")); if (lastdirectory != null) { chooser.setinitialdirectory(lastdirectory); } var file = chooser.showopendialog(owner); if (file != null) { lastdirectory = file.getparentfile(); return new image(file.touri().tostring()); } return null; } private void displayimage(window owner, imagerecord record) { var view = new imageview(); var task = creategetimagetask(record, view::setimage); executor.execute(task); var sp = new scrollpane(view); sp.setpannable(true); var window = new stage(stagestyle.utility); window.initowner(owner); window.settitle(record.name()); window.setscene(new scene(sp, 500, 300)); window.setonhiding(e -> task.cancel()); window.show(); } private tableview createtable(consumer onopen) { var table = new tableview(); table.setcolumnresizepolicy(tableview.constrained_resize_policy_flex_last_column); var idcol = new tablecolumn("id"); idcol.setcellvaluefactory(data -> new simpleintegerproperty(data.getvalue().id())); table.getcolumns().add(idcol); var namecol = new tablecolumn("name"); namecol.setcellvaluefactory(data -> new simplestringproperty(data.getvalue().name())); table.getcolumns().add(namecol); var openbtncol = new tablecolumn(); openbtncol.setcellvaluefactory(data -> new simpleobjectproperty<>(data.getvalue())); openbtncol.setcellfactory(tc -> createopenbuttoncell(onopen)); table.getcolumns().add(openbtncol); return table; } private tablecell createopenbuttoncell(consumer onopen) { return new tablecell<>() { final hbox container = new hbox(); final button openbutton = new button("open"); { container.getchildren().add(openbutton); container.setalignment(pos.center); openbutton.setonaction( e -> { e.consume(); var item = isempty() ? null : getitem(); if (item != null) { onopen.accept(item); } }); } @override protected void updateitem(imagerecord item, boolean empty) { super.updateitem(item, empty); if (empty || item == null) { setgraphic(null); } else { setgraphic(container); } } }; } private task createsaveimagetask(image image, consumer onsuccess) { return new task() { @override protected imagerecord call() throws exception { return imagerepo.insertimage(image); } @override protected void succeeded() { onsuccess.accept(getvalue()); } @override protected void failed() { getexception().printstacktrace(); } }; } private task creategetimagetask(imagerecord record, consumer onsuccess) { return new task() { @override protected image call() throws exception { return imagerepo.getimage(record).orelsethrow(); } @override protected void succeeded() { onsuccess.accept(getvalue()); } @override protected void failed() { getexception().printstacktrace(); } }; } }
Nach dem Login kopieren

imagerepository.java

package com.example; import static java.sql.statement.return_generated_keys; import java.io.bytearrayinputstream; import java.io.bytearrayoutputstream; import java.io.ioexception; import java.io.inputstream; import java.io.uncheckedioexception; import java.sql.sqlexception; import java.util.arraylist; import java.util.list; import java.util.objects; import java.util.optional; import java.util.concurrent.atomic.atomicinteger; import javafx.embed.swing.swingfxutils; import javafx.scene.image.image; import javax.imageio.imageio; public class imagerepository { private static final string select_all_records_sql = "select id, name from images"; private static final string select_image_sql = "select image from images where id = ?"; private static final string insert_sql = "insert into images (name, image) values (?, ?)"; private final atomicinteger generatednamecount = new atomicinteger(); private final imagesdatabase db; public imagerepository(imagesdatabase db) { this.db = db; } public list getrecords() throws sqlexception { return db.execute( conn -> { try (var stat = conn.createstatement()) { var result = stat.executequery(select_all_records_sql); var records = new arraylist(); while (result.next()) { int id = result.getint(1); var name = result.getstring(2); records.add(new imagerecord(id, name)); } return records; } }); } public optional getimage(imagerecord record) throws sqlexception { return getimage(record.id()); } public optional getimage(int recordid) throws sqlexception { if (recordid <= 0) { throw new illegalargumentexception("recordid <= 0: " + recordid); } return db.execute( conn -> { try (var stat = conn.preparestatement(select_image_sql)) { stat.setint(1, recordid); var result = stat.executequery(); if (result.next()) { var image = new image(result.getbinarystream(1)); return optional.of(image); } else { return optional.empty(); } } }); } public imagerecord insertimage(image image) throws sqlexception { objects.requirenonnull(image); return db.execute( conn -> { try (var stat = conn.preparestatement(insert_sql, return_generated_keys)) { var name = getimagename(image); stat.setstring(1, name); stat.setbinarystream(2, imagetoinputstream(image)); stat.executeupdate(); var keys = stat.getgeneratedkeys(); if (keys.next()) { int id = keys.getint(1); return new imagerecord(id, name); } else { throw new illegalstateexception("generated key not returned"); } } }); } private string getimagename(image image) { var source = image.geturl(); return source == null ? generateimagename() : source; } private string generateimagename() { return "generated image name " + generatednamecount.incrementandget(); } private inputstream imagetoinputstream(image image) { var out = new bytearrayoutputstream(); try { imageio.write(swingfxutils.fromfximage(image, null), "png", out); } catch (ioexception ex) { throw new uncheckedioexception(ex); } return new bytearrayinputstream(out.tobytearray()); } }
Nach dem Login kopieren

imagesdatabase.java

package com.example; import java.sql.connection; import java.sql.sqlexception; import java.util.objects; import java.util.concurrent.locks.lock; import java.util.concurrent.locks.reentrantlock; import javax.sql.datasource; import org.h2.jdbcx.jdbcdatasource; public class imagesdatabase implements autocloseable { private static final string create_table_sql = "create table images (id identity, name varchar(255), image blob)"; @functionalinterface public interface sqlfunction { t execute(connection connection) throws sqlexception; } private final lock mutex = new reentrantlock(); private final datasource source; private connection connection; private boolean open = true; private boolean initialized; public imagesdatabase(string name) { if (name.isblank()) { throw new illegalargumentexception("blank name"); } var source = new jdbcdatasource(); source.seturl("jdbc:h2:mem:" + name + ";db_close_delay=-1"); this.source = source; } public  t execute(sqlfunction function) throws sqlexception { objects.requirenonnull(function); mutex.lock(); try { checkopen(); return function.execute(getoropenconnection()); } finally { mutex.unlock(); } } private connection getoropenconnection() throws sqlexception { if (connection == null || connection.isclosed()) { connection = source.getconnection(); initialize(connection); } return connection; } private void initialize(connection conn) throws sqlexception { if (!initialized) { try (var stat = conn.createstatement()) { stat.executeupdate(create_table_sql); } initialized = true; } } private void shutdown() throws sqlexception { if (initialized) { try (var conn = getoropenconnection(); var stat = conn.createstatement()) { stat.execute("shutdown"); } connection = null; } } private void checkopen() { if (!open) { throw new illegalstateexception("closed"); } } @override public void close() throws sqlexception { mutex.lock(); try { if (open) { open = false; shutdown(); } } finally { mutex.unlock(); } } }
Nach dem Login kopieren
Gradle-Datei

Ich habe Kotlin DSL verwendet, aber Sie können auch Groovy DSL verwenden, wenn Sie möchten.

settings.gradle.kts

rootproject.name = "h2images-example"
Nach dem Login kopieren

build.gradle.kts

plugins { id("org.openjfx.javafxplugin") version "0.1.0" application } group = "com.example" version = "1.0" javafx { modules("javafx.controls", "javafx.swing") version = "21.0.1" } application { mainclass.set("com.example.main") } repositories { mavencentral() } dependencies { implementation("com.h2database:h2:2.2.224") }
Nach dem Login kopieren
Ausführen

Sie können das Obige mit dem folgenden Befehl ausführen:

./gradlew run
Nach dem Login kopieren
Hinweis

ruft den

Gradle Wrapper

auf. Wenn auf Ihrem Computer eine Gradle-Version installiert ist, können Sie einen Wrapper für Version 8.4 generieren über:

gradle wrapper --gradle-version 8.4
Nach dem Login kopieren

./gradlew1.Javafx unterstützt das Laden aus dem Klassenpfad technisch nicht. Dies bedeutet, dass sich das Javafx-Modul idealerweise im Modulpfad befinden und in ein benanntes Modul aufgelöst werden sollte, auch wenn Ihr eigener Code und andere Abhängigkeiten aus dem Klassenpfad geladen werden. Allerdings weiß ich nicht, was passiertBreaks

, wenn sich Javafx im Klassenpfad befindet (zumindest ab Javafx 21), außer dass Ihre Hauptklasse nicht mehr sein kann

(Sie benötigen eine separate „Launcher-Klasse“ als Hauptklasse ). Beachten Sie jedoch, dass Probleme, die dadurch verursacht werden, dass sich Javafx im Klassenpfad befindet, wahrscheinlich nicht vom Javafx-Team behoben werden können.Bitte beachten Sie, dass die von openjfx bereitgestellten Gradle- und Maven-Plugins diese Build-Tools so konfigurieren, dass Javafx in den Modulpfad eingefügt wird.javafx.application 的子类。 application

2.Basierend auf dem Kontext Ihrer beiden Fragen konvertiert dieses BeispielimageObjekte in PNG-Bytes. Wenn Sie das Bild jedoch bereits in Bytes erhalten (d. h. als lokale oder Remote-Datei), ist es möglicherweise einfacher und effizienter, diese Bytes direkt in die Datenbank zu übertragen.

Das obige ist der detaillierte Inhalt vonLaden Sie JavaFX-Bilder und speichern Sie sie in der Datenbank. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:stackoverflow.com
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!