HugoKonrad Neitzels BlogBlog mit Computer-Themen, speziell Softwareentwickung2023-03-24T13:08:38+01:00https://blog.kneitzel.de/Java Modules: Nein Danke!https://blog.kneitzel.de/blog/2023-03-10-Java-Modules-Nein-Danke/Konrad Neitzel2023-03-10T06:33:00+02:002023-03-21T16:51:01+01:00
<p>Die Java Module, die mit Java 9 eingeführt wurden, sahen erst einmal fantastisch aus.</p>
<p>Zusammen mit JLink und JPackage konnte man seine modularisierten Java Anwendungen auch gut aufbereiten zur Weitergabe an Dritte.</p>
<p>Aber wie so oft, kommt da ein großes ABER: In der “Enterprise-Welt” wurden diese Module mehr oder weniger ignoriert. Jakarta EE, Spring Framework, … wollten davon (lange Zeit) nichts wissen. Erst mit den neuesten Versionen wird hier auch das Modulsystem unterstützt (Jakarta EE 10, Spring Framework 6, …)</p>
<p>Die Folge davon war, dass nicht nur die sehr alten Abhängigkeiten aber auch alle Abhängigkeiten, die erst zur Laufzeit dazu kommen, das Modulsystem nicht unterstützen. Die JAR Dateien hatten also keine module-info.class und damit wurden diese per “Auto-Module” eingebunden.</p>
<p>Soweit alles ganz toll und noch kein Problem sichtbar, aber wenn man dann mit JLink ein Image bauen wollte, war man aufgeschmissen: JLink unterstützt keine Auto-Module. Damit musste man hier nachträglich noch eine module-info.class unterschieben. Technisch kein Problem: jdeps kann dies bei Bedarf erstellen und mit Hilfe des Moditect Plugins liess sich das auch in Maven gut einbinden.</p>
<p>Somit gab es eine technische Lösung, die sich auch in Projekten umsetzen liess. Es sah so aus, als ob dieses Vorgehen so nun notwendig wäre und wurde von mir entsprechend umgesetzt und auch im Java Forum entsprechend als mögliches Vorgehen beworben.</p>
<p>Die immer wieder damit verbundenen Probleme haben aber klar aufgezeigt, dass dieser Weg alles andere als gut und gangbar ist. Und nach all den vielen Stunden Aufwand zeigt sich nun, dass es auch eine relativ einfache Lösung für diese Thematik gibt:</p>
<p>a) Wir bauen eine Anwendung ganz ohne eine Modulbeschreibung! Also keine module-info.java, keine Notwendigkeit, hier immer die requires Einträge zu machen (In IntelliJ immer relativ blöd, da man sich da etwas im Kreis dreht: Intellij schlägt bei einem import im Java File den requires Eintrag vor so dieser fehlt. Aber ohne den requires EIntrag erzeugt IntelliJ keinen import Eintrag für eine Klasse. Eins von beidem muss man schreiben. Ich lasse aber gerne beides direkt von IntelliJ erstellen.)</p>
<p>b) Bei JavaFX benötigen wir noch eine weitere Klasse mit einer main Methode. Üblicherweise startet man eine JavaFX Anwendung mit einer Klasse, die von Application erbt und die dann u.a. eine main Methode hat, die nur launch aufruft. Dies klappt leider bei JavaFX nicht, so dass eine weitere Klasse benötigt wird deren main mMthode dann nur die sonst übliche main Methode aufruft. Klingt dubios, aber ist leider so notwendig (die technischen Hintergründe erspare ich uns hier!)</p>
<p>c) Im Maven Projekt bauen wir nun noch etwas ein, dass die Abhängigkeiten für uns kopiert. Dabei wollen wir natürlich auch alle Abhängigkeiten mit Scope Runtime kopieren:</p>
<pre tabindex="0"><code><plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>${maven.dependency.plugin}</version>
<executions>
<!-- erstmal Abhängigkeiten für den Class-Path kopieren -->
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/modules</outputDirectory>
<includeScope>runtime</includeScope>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>false</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
</configuration>
</execution>
<!-- dazu noch das Projekt-JAR -->
<execution>
<id>copy</id>
<phase>install</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/modules</outputDirectory>
<artifactItems>
<artifactItem>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
<version>${project.version}</version>
<type>${project.packaging}</type>
<destFileName>${project.build.finalName}.jar</destFileName>
</artifactItem>
</artifactItems>
<overWriteIfNewer>true</overWriteIfNewer>
</configuration>
</execution>
</executions>
</plugin>
</code></pre><p>d) Nun kann noch JPackage aufgerufen werden. Ganz ohne vorherigen JLink Aufruf:</p>
<pre tabindex="0"><code><plugin>
<groupId>com.github.akman</groupId>
<artifactId>jpackage-maven-plugin</artifactId>
<version>${jpackage.maven.plugin}</version>
<configuration>
<name>${appName}</name>
<type>IMAGE</type>
<mainclass>${main.class}</mainclass>
<input>${project.build.directory}/modules</input>
<mainjar>${jar.file}.jar</mainjar>
</configuration>
<executions>
<execution>
<phase>install</phase>
<goals>
<goal>jpackage</goal>
</goals>
</execution>
</executions>
</plugin>
</code></pre><p>Die einzelnen Properties müssen natürlich gesetzt sein. Beispielprojekte, die diese Nutzung aufzeigen, finden sich unter:</p>
<ul>
<li><a
class="gblog-markdown__link"
href="https://github.com/kneitzel/JavaMavenApp"
>https://github.com/kneitzel/JavaMavenApp</a></li>
<li><a
class="gblog-markdown__link"
href="https://github.com/kneitzel/JavaFXMavenApp"
>https://github.com/kneitzel/JavaFXMavenApp</a></li>
</ul>
<p>Bei Fragen und Anregungen stehe ich gerne per Email zur Verfügung oder kommt einfach in das Java Forum!</p>
Neustart des Blogshttps://blog.kneitzel.de/blog/2022-07-02-Neustart/Konrad Neitzel2023-01-16T23:26:18+02:002023-01-16T20:14:20+01:00
<p>Ich habe in der Vergangenheit erste Erfahrungen mit Blog und YouTube Videos sammeln
können. Der Aufwand ist - so wie ich es ursprünglich vorgesehen habe - aber kaum zu
bewältigen, so dass ich selbst mit dem, was ich veröffentlichen konnte, unzufrieden
bin / war.</p>
<p>Ich habe die letzten Monate genutzt, mir ein neues, besseres Konzept zu überlegen.
Dabei werde ich mich vor allem auf YouTube konzentrieren um so hoffentlich einen
hilfreichen Content in einer akzeptablen Qualität abliefern zu können.</p>
<p>Den Blog stelle ich um auf rein statische Seiten, welche ich mit Hugo erzeugen werde.
Dies vereinfacht das Handling für mich enorm, so daß ich hier weniger Aufwand
treiben muss.</p>
<p>Durch die statische Seite entfällt auch der Bedarf für Cookies und das ganze Thema
Datenschutz vereinfacht sich massiv.</p>
<p>Im Blog werden aber keine ausführlichen Dokumentationen mehr kommen.
Die Blog Einträge sollen lediglich:</p>
<ul>
<li>Neue YouTube Videos ankündigen</li>
<li>Links / Downloads zu den Videos bereit stellen</li>
<li>Teilweise zusätzliche Informationen geben, zu denen ich keine Videos erstelle.</li>
</ul>
<p>Derzeit bin ich aber noch dabei, die alten Beiträge aus Wordpress zu exportieren um
diese dann hier auch verfügbar zu machen. Daher wird zwischen Erstellug dieses Posts
und der online Verfügbarkeit eine gewisse Zeit vergehen.</p>
<p>In der Anfangszeit können noch Fehler in den konvertierten Seiten sein. Ich werde diese aber nach und nach weiter editieren und anpassen. Wenn etwas auffällt, dann können Sie mich aber gerne anschreiben: <a
class="gblog-markdown__link"
href="mailto:konrad@kneitzel.de"
>konrad@kneitzel.de</a></p>
Java Schnellstart mit IntelliJ IDEAhttps://blog.kneitzel.de/2020/11/17/java-schnellstart-mit-intellij-idea/2020-11-17T10:09:49+00:002023-01-19T22:51:40+01:00
<p>In dem Blog Beitrag JavaFX: Installation habe ich die Installation von Java behandelt, welches die wichtige Abhängigkeit ist, um mit JavaFX oder mit den Build Tools Maven oder Gradle zu entwickeln.</p>
<p>Es geht prinzipiell aber noch deutlich einfacher, denn die Entwicklungsumgebung IntelliJ IDEA, welche frei in der Community Edition verwendbar ist, bietet eine sehr gute Verwaltung von den JDKs.</p>
<p>Aus dem Grund kann auf die manuelle Installation eines JDKs verzichtet werden. Es reicht aus, IntelliJ IDEA zu installieren um dann innerhalb der Entwicklungsumgebung die JDKs zu verwalten.</p>
<p>In dem Video auf YouTube zeige ich, wie die JDKs verwaltet werden können, sowohl bei Anlage von neuen Projekten als auch beim Öffnen von bestehenden Projekten.</p>
<figure class="wp-block-embed-youtube wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper"><iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" height="371" loading="lazy" src="https://www.youtube.com/embed/hIyotxT6h7s?feature=oembed" title="Java Schnellstart mit IntelliJ" width="660"></iframe></div></figure>## Links
<ul>
<li>YouTube Video: <a
class="gblog-markdown__link"
href="https://youtu.be/hIyotxT6h7s"
>https://youtu.be/hIyotxT6h7s</a></li>
<li>IntelliJ IDEA: <a
class="gblog-markdown__link"
href="https://www.jetbrains.com/de-de/idea/"
>https://www.jetbrains.com/de-de/idea/</a></li>
</ul>
JavaFX: IntelliJhttps://blog.kneitzel.de/2020/11/02/javafx-intellij/2020-11-02T16:46:43+00:002023-01-19T22:51:40+01:00
<p>Ein schneller, kurzer Überblick über IntelliJ. Dies ist meine bevorzugte Entwicklungsumgebung daher möchte ich diese kurz Vorstellen.</p>
<p>Dies ist ein kurzer Blog – das Hauptgewicht liegt hier auf dem YouTube Video.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="teile-der-javafx-serie-aktualisiert">
Teile der JavaFX Serie (aktualisiert)
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/11/02/javafx-intellij/#teile-der-javafx-serie-aktualisiert" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Teile der JavaFX Serie (aktualisiert)" href="#teile-der-javafx-serie-aktualisiert">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<ul>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/29/javafx-uebersicht-planung/"
>JavaFX 01: Übersicht / Planung</a> (<a
class="gblog-markdown__link"
href="https://youtu.be/emCUpGFpf_Q"
>YouTube</a>)</li>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/24/javafx-uebersicht/"
>JavaFX 02: Installation</a> (<a
class="gblog-markdown__link"
href="https://youtu.be/ZmDUr7fwABM"
>YouTube</a>)</li>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/11/02/javafx-maven-und-gradle/"
>JavaFX 03: Maven & Gradle</a> (<a
class="gblog-markdown__link"
href="https://youtu.be/daVCphI0qZ0"
>YouTube</a>)</li>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/11/02/javafx-intellij/"
>JavaFX 04: IntelliJ</a> (<a
class="gblog-markdown__link"
href="https://youtu.be/Lh8MqSrHIb4"
>YouTube</a>)</li>
</ul>
<div class="gblog-post__anchorwrap flex align-center">
<h3 id="teile-der-javafx-serie-alt--geplant">
Teile der JavaFX Serie (alt / geplant)
</h3>
<a data-clipboard-text="https://blog.kneitzel.de/2020/11/02/javafx-intellij/#teile-der-javafx-serie-alt--geplant" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Teile der JavaFX Serie (alt / geplant)" href="#teile-der-javafx-serie-alt--geplant">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<ul>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/26/javafx-scene-builder/"
>JavaFX 05: Scene Builder</a></li>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/26/javafx-erlaeuterungen-der-applikation/"
>JavaFX –: Erläuterung der Applikation</a></li>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/26/javafx-model-view-controller/"
>JavaFX 06: Model / View / Controller</a></li>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/29/javafx-mvvm/"
>JavaFX 07: MVVM</a></li>
<li>JavaFX: Komplette MVVM Applikation (geplant)</li>
<li>JavaFX: Layouts (geplant)</li>
<li>JavaFX: Formulare einfach erstellen (geplant)</li>
<li>JavaFX: Multi Plattform (geplant)</li>
</ul>
<figure class="wp-block-embed-youtube wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper"><iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" height="371" loading="lazy" src="https://www.youtube.com/embed/Lh8MqSrHIb4?feature=oembed" title="JavaFX Series - 04 IntelliJ" width="660"></iframe></div></figure>## <a>Code der JavaFX Serie</a>
<p>Der Source Code sowie alle Dokumente finden sich auf GitHub: <a
class="gblog-markdown__link"
href="https://github.com/kneitzel/blog-javafx-series"
>https://github.com/kneitzel/blog-javafx-series</a></p>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="versionen">
Versionen
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/11/02/javafx-intellij/#versionen" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Versionen" href="#versionen">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>IntelliJ IDEA, oft einfach IntelliJ genannt, wird in zwei Versionen angeboten: Der freien Community Edition und der kostenpflichtigen Ultimate Edition.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h3 id="community-edition">
Community Edition
</h3>
<a data-clipboard-text="https://blog.kneitzel.de/2020/11/02/javafx-intellij/#community-edition" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Community Edition" href="#community-edition">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Die Community Edition ist komplett frei verwendbar und eine voll funktionstüchtige Entwicklungsumgebung. Lediglich gewisse Enterprise Funktionen sind nicht integriert, was in meinen Augen für Anfänger eher gut ist, da die Entwicklungsumgebung dadurch weniger Elemente bietet, die für den Benutzer uninteressant sind.</p>
<p>Ebenso gefällt mir die Aufgliederung in mehrere Entwicklungsumgebungen. Anders als Eclipse muss IntelliJ nicht alles abdecken. Für C/C++, PHP, JavaScript, … gibt es eigene, spezialisierte Entwicklungsumgebungen. Der Focus liegt bei IntelliJ auf Java – aber ohne darauf komplett beschränkt zu sein! So lässt sich ebenso auch HTML, JavaScript und co komfortabel in IntelliJ bearbeiten…</p>
<p>Die Nutzung beschränkt sich nicht auf nicht gewerbliche Nutzung. Die Community Edition ist auch kommerziell einsetzbar.</p>
<p>Und natürlich lassen sich auch Enterprise Applikationen mit IntelliJ schreiben. Lediglich gewisse Dinge sind dann nicht komfortabel in die IDE integriert.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h3 id="ultimate">
Ultimate
</h3>
<a data-clipboard-text="https://blog.kneitzel.de/2020/11/02/javafx-intellij/#ultimate" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Ultimate" href="#ultimate">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Die Ultimate Edition wurde um einige Enterprise Features erweitert. So werden viele Elemente aus dem Enterprise Umfeld erkannt und komfortabel in die Oberfläche integriert. Einige Aufgaben lassen sich so mit wenigen Klicks erledigen und die IDE bietet eine erweiterte Unterstützung in diesem Bereich. Daher kann ich diese Version, die ich auch im Einsatz habe, nur empfehlen.</p>
<p>JetBrains bietet die Tools nur im „Abo“ an, wobei nach einem Jahr auch eine dauerhafte Lizenz für die dann aktuelle Version erworben wird und das Abo nicht wie bei Anderen Anbietern wie Adobe, dauerhaft behalten werden muss. Da die Kosten vom ersten bis zum dritten Jahr sinken, kann ich nur empfehlen, das Abo beizubehalten, so man die Version dauerhaft nutzen möchte.</p>
<p>Die Preise für eine individuelle Lizenz sind aus meiner Sicht auch voll gerechtfertigt – für eine individuelle Lizenz für IntelliJ zahlt man derzeit 149€/Jahr und der Preis sinkt bis zum dritten Jahr auf 89€/Jahr. (Bzw. wenn man alle Tools von Jetbrains nutzen möchte: 249€ im ersten Jahr und der Preis sind bis zu 149€ im dritten Jahr.) Verglichen zu anderen Anbietern von (kommerziellen) Entwicklungsumgebungen ist das aus meiner Sicht ein geringer Preis.</p>
<table>
<thead>
<tr>
<th><strong>Wichtig</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td>Die Ultimate Edition ist nicht notwendig! Es muss kein Geld ausgegeben werden, um in Java zu entwickeln! Die Community Edition ist frei verfügbar und sehr gut. Und sollte diese nicht den Ansprüchen genügen, so kann Eclipse oder Netbeans vielleicht überzeugen.</td>
</tr>
</tbody>
</table>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="installation">
Installation
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/11/02/javafx-intellij/#installation" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Installation" href="#installation">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<div class="gblog-post__anchorwrap flex align-center">
<h3 id="manuelle-installation">
Manuelle Installation
</h3>
<a data-clipboard-text="https://blog.kneitzel.de/2020/11/02/javafx-intellij/#manuelle-installation" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Manuelle Installation" href="#manuelle-installation">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Beim Hersteller kann ein Installer von IntelliJ Community Edition heruntergeladen werden. Ein Setup führt einen dann mit wenigen Schritten durch die Installation so dass am Ende IntelliJ installiert ist.</p>
<p>Und der Start ist dann nach der Installation wie gewohnt möglich, d.h. das Setup trägt die Applikation entsprechend ein, so dass es auf Windows, gnome, KDE, … im Startmenü aufgeführt wird.</p>
<p>Wichtig ist: Updates müssen dann auch manuell installiert werden, also erneutes herunterladen, ggf. eine Deinstallation der alten Version und dann de manuelle Installation der neuen Version.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h3 id="toolbox">
Toolbox
</h3>
<a data-clipboard-text="https://blog.kneitzel.de/2020/11/02/javafx-intellij/#toolbox" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Toolbox" href="#toolbox">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>JetBrains bietet ein kleines Programm an, dass sich Toolbox nennt. Dieses sitzt im Systray und prüft regelmäßig, was für neue Versionen verfübar sind.</p>
<p>Es bietet einen einfachen Weg, die Jetbrains Produkte als auch das Android Studio zu installieren, upzudaten oder zu deinstallieren.</p>
<p>Des Weiteren können mehrere Versionen parallel installiert sein. Dies kann im Hintergrund passieren, d.h. bei einem Update wird per Default die alte Version noch nicht deinstalliert. Somit ist bei Problemen ein schneller Wechsel zur alten Version möglich. (Dieses Verhalten lässt sich natürlich konfigurieren, z.B. wenn Speicherplatz knapp sein sollte.)</p>
<p>Die Toolbox kann genutzt werden, die installierte Software zu starten. In den Entwicklungsumgebungen geöffnete Projekte (die dann dort auch beim Start aufgelistet werden, so nicht automatisch das letzte, geöffnete Projekt erneut geöffnet werden soll) ist ebenfalls über den Reiter Projekte direkt startbar.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="erster-start">
Erster Start
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/11/02/javafx-intellij/#erster-start" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Erster Start" href="#erster-start">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<div class="gblog-post__anchorwrap flex align-center">
<h3 id="konfiguration-aus-alter-version-übernehmen">
Konfiguration aus alter Version übernehmen
</h3>
<a data-clipboard-text="https://blog.kneitzel.de/2020/11/02/javafx-intellij/#konfiguration-aus-alter-version-übernehmen" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Konfiguration aus alter Version übernehmen" href="#konfiguration-aus-alter-version-%c3%bcbernehmen">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Wenn die Software das erste mal gestartet wird (es wird für diese Version noch keine Konfiguration gefunden), dann sucht IntelliJ nach früheren Versionen, dessen Konfiguration übernommen werden könnte.</p>
<p>Dann öffnet IntelliJ ein Fenster, in dem es fragt, von welcher Version eine Konfiguration übernommen werden soll. So eine frühere Version gefunden wurde, kann diese ausgewählt werden. Es kann aber auch eine Konfiguration selbst ausgesucht werden – z.B. um eine Vorgabe der Firma oder des Teams direkt zu übernehmen.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h3 id="erstkonfiguration">
Erstkonfiguration
</h3>
<a data-clipboard-text="https://blog.kneitzel.de/2020/11/02/javafx-intellij/#erstkonfiguration" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Erstkonfiguration" href="#erstkonfiguration">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>So keine Konfiguration importiert wurde, wird man über einen Konfigurations-Wizard geleitet. Dieser fragt das gewünschte Aussehen, PlugIns und Addons ab, die genutzt werden sollen.</p>
<p>Die Auswahl ist unkritisch, da dies alles jederzeit verändert werden kann. Daher einfach das im Augenblick bevorzugte Aussehen wählen und die Standards bei den weiteren Seiten beibehalten, so dass wir zum eigentlichen Startfenster von IntelliJ kommen.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="startfenster">
Startfenster
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/11/02/javafx-intellij/#startfenster" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Startfenster" href="#startfenster">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<table>
<thead>
<tr>
<th><strong>Wichtig</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td>Dieses Startfenster erscheint nur, wenn es kein zuletzt geöffnetes Projekt gibt (weil erster Start, der Bereich mit den zuletzt geöffneten Projekten ist dann auch nicht vorhanden) oder wenn die Standard Einstellung deaktiviert wurde, so dass nicht mehr das zuletzt geöffnete Projekt geöffnet wird.</td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr>
<th><strong>Empfehlung</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td>Ich selbst mag es nicht, wenn beim Start das letzte Projekt erneut geöffnet wird, denn ich arbeite zu oft an wechselnden Projekten. Daher ist meine Empfehlung diese Einstellung zu ändern. Diese findet sich in den Settings unter Appearance & Behaviour -> System Settings im Punkt Reopen Projects on Startup.</td>
</tr>
</tbody>
</table>
<p><img
src="https://blog.kneitzel.de/wp-content/uploads/2020/11/IntelliJ-Startfenster.png"
alt="IntelliJ-Startfenster"
/></p>
<p>Es finden sich mehrere Bereiche:</p>
<ol>
<li>Zuletzt geöffnete Projekte<br>
In der Liste der zuletzt geöffneten Projekte kann man schnell und einfach ein Projekt öffnen.<br>
Wenn man mit der Maus über ein Projekt geht, dann erscheint am rechten Rand ein X, mit dem ein Projekt aus der Liste entfernt werden kann.</li>
<li>Es kann in dem Menü entweder ein komplett neues Projekt erstellt werden oder ein bestehendes Projekt geöffnet / importiert werden. Dabei kann sogar direkt auf eine Source Verwaltung zugegriffen werden, um das Projekt erst lokal zu holen (z.B. per git von GitHub).</li>
<li>Beim Start überprüft IntelliJ, ob Updates für Plugins verfügbar sind und gibt einen Link mit dem man direkt zu den Plugins kommt mit Sicht auf alle aktualisierbaren Plugins.</li>
<li>In dem Configure Menü kann man verschiedene Konfigurationen aufrufen. Neben den Settings finden sich dort vor allem auch die Plugins. Aber auch viele weitere Einstellungen, auf die ich nicht näher eingehen möchte.</li>
</ol>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="projekt-von-sourceverwaltung-öffnen">
Projekt von SourceVerwaltung öffnen
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/11/02/javafx-intellij/#projekt-von-sourceverwaltung-öffnen" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Projekt von SourceVerwaltung öffnen" href="#projekt-von-sourceverwaltung-%c3%b6ffnen">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Startet wir, indem wir einfach ein Projekt von der Sourceverwaltung öffnen. Dazu können wir die Sourcen der Blog Serie als Beispiel nehmen:</p>
<ol>
<li>Wir wählen „Get from Version Control“ aus.</li>
<li>Im folgenden Fenster können wir die git URL eingeben. Wichtig: Dies ist nicht die Web-URL des Github Projekts, sondern die git Adresse, die man auf der Webseite angezeigt bekommt, wenn man auf den grünen „Code“ Knopf drückt. Für unser Projekt ist dies <a
class="gblog-markdown__link"
href="https://github.com/kneitzel/blog-javafx-series.git"
>https://github.com/kneitzel/blog-javafx-series.git</a>.<br>
Und unter der Adresse können wir den Ordner wählen, in welches die Sourcen kopiert werden sollen, z.B. c:\Projects\javafx-blog</li>
<li>Sollte auf unserem Rechner kein git installiert sein, dann meldet IntelliJ dies und bietet an, git für uns zu installieren.</li>
<li>So wir alles eingegeben haben, können wir mit dem Knopf „clone“ das Herunterladen starten.</li>
<li>Sobald IntelliJ alles heruntergeladen hat, wird der Ordner als Projekt geöffnet. IntelliJ erkennt die Build-Files der Gradle und Maven Projekte und bietet den Import an, welchen wir annehmen sollten.</li>
<li>Nun sollten wir uns erst einmal in Geduld üben: IntelliJ arbeitet nun alle Projekte ab, um diese richtig zu integrieren. Dies dauert einige Minuten und wir sollten IntelliJ diese Zeit geben.</li>
</ol>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="neues-projekt-erstellen">
Neues Projekt erstellen
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/11/02/javafx-intellij/#neues-projekt-erstellen" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Neues Projekt erstellen" href="#neues-projekt-erstellen">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Wenn wir ein neues Projekt erstellen wollen, dann bietet IntelliJ uns eine ganze Reihe an möglichen Projekten.</p>
<p>Wichtig ist, dass wir die Java Version, die open im Fenster eingeblendet ist, richtig setzen. So wir nur ein JDK installiert haben wird IntelliJ dieses korrekt erkannt und oben eingetragen haben. Aber wir können über das Dropdown nicht nur die richtige Version auswählen sondern wir können bereits installierte Versionen hinzufügen und sogar weitere JDKs installieren.</p>
<p>Bezüglich Auswahl des Projekt-Typs ist meine Empfehlung, dass man bei Gradle oder Maven bleibt. So bleibt man bei den Projekten unabhängig und ist nicht an eine spezielle Entwicklungsumgebung gebunden.</p>
<p>Die vielen Möglichkeiten der unterschiedlichen Projekte im Detail zu beschreiben würde den Rahmen des Blog Beitrages sprengen, so dass ich es bei diesem Ratschlag belasse.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="bestehendes-projekt-öffnen">
Bestehendes Projekt öffnen
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/11/02/javafx-intellij/#bestehendes-projekt-öffnen" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Bestehendes Projekt öffnen" href="#bestehendes-projekt-%c3%b6ffnen">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Bestehende Projekte lassen sich problemlos öffnen. Dazu muss lediglich der Ordner mit dem Projekt ausgewählt werden und IntelliJ öffnet es für einen.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="links">
Links
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/11/02/javafx-intellij/#links" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Links" href="#links">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<ul>
<li>IntelliJ IDEA: <a
class="gblog-markdown__link"
href="https://www.jetbrains.com/idea/"
>https://www.jetbrains.com/idea/</a></li>
<li>JetBrains Toolbox: <a
class="gblog-markdown__link"
href="https://www.jetbrains.com/toolbox-app/"
>https://www.jetbrains.com/toolbox-app/</a></li>
<li>Git Link für die Sourcen der JavaFX Serie: <a
class="gblog-markdown__link"
href="https://github.com/kneitzel/blog-javafx-series.git"
>https://github.com/kneitzel/blog-javafx-series.git</a></li>
</ul>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="änderungsnachweis">
Änderungsnachweis
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/11/02/javafx-intellij/#änderungsnachweis" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Änderungsnachweis" href="#%c3%a4nderungsnachweis">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<ul>
<li>2020-11-02 Erste Veröffentlichung und Überarbeitung.</li>
</ul>
JavaFX: Maven und Gradlehttps://blog.kneitzel.de/2020/11/02/javafx-maven-und-gradle/2020-11-02T16:46:09+00:002023-01-19T22:51:40+01:00
<p>Ein schneller, kurzer Überblick über Maven und Gradle. Dies kann keine Einführung in der Tiefe sein – dazu wäre jeweils eine ganze Blog-Serie notwendig und da ist es sinnvoller, die offizielle Dokumentation zu verwenden!</p>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="teile-der-javafx-serie-aktualisiert">
Teile der JavaFX Serie (aktualisiert)
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/11/02/javafx-maven-und-gradle/#teile-der-javafx-serie-aktualisiert" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Teile der JavaFX Serie (aktualisiert)" href="#teile-der-javafx-serie-aktualisiert">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<ul>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/29/javafx-uebersicht-planung/"
>JavaFX 01: Übersicht / Planung</a> (<a
class="gblog-markdown__link"
href="https://youtu.be/emCUpGFpf_Q"
>YouTube</a>)</li>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/24/javafx-uebersicht/"
>JavaFX 02: Installation</a> (<a
class="gblog-markdown__link"
href="https://youtu.be/ZmDUr7fwABM"
>YouTube</a>)</li>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/11/02/javafx-maven-und-gradle/"
>JavaFX 03: Maven & Gradle</a> (<a
class="gblog-markdown__link"
href="https://youtu.be/daVCphI0qZ0"
>YouTube</a>)</li>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/11/02/javafx-intellij/"
>JavaFX 04: IntelliJ</a> (<a
class="gblog-markdown__link"
href="https://youtu.be/Lh8MqSrHIb4"
>YouTube</a>)</li>
</ul>
<div class="gblog-post__anchorwrap flex align-center">
<h3 id="teile-der-javafx-serie-alt--geplant">
Teile der JavaFX Serie (alt / geplant)
</h3>
<a data-clipboard-text="https://blog.kneitzel.de/2020/11/02/javafx-maven-und-gradle/#teile-der-javafx-serie-alt--geplant" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Teile der JavaFX Serie (alt / geplant)" href="#teile-der-javafx-serie-alt--geplant">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<ul>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/26/javafx-scene-builder/"
>JavaFX 05: Scene Builder</a></li>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/26/javafx-erlaeuterungen-der-applikation/"
>JavaFX –: Erläuterung der Applikation</a></li>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/26/javafx-model-view-controller/"
>JavaFX 06: Model / View / Controller</a></li>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/29/javafx-mvvm/"
>JavaFX 07: MVVM</a></li>
<li>JavaFX: Komplette MVVM Applikation (geplant)</li>
<li>JavaFX: Layouts (geplant)</li>
<li>JavaFX: Formulare einfach erstellen (geplant)</li>
<li>JavaFX: Multi Plattform (geplant)</li>
</ul>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="code-der-javafx-serie">
Code der JavaFX Serie
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/11/02/javafx-maven-und-gradle/#code-der-javafx-serie" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Code der JavaFX Serie" href="#code-der-javafx-serie">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Der Source Code sowie alle Dokumente finden sich auf GitHub: <a
class="gblog-markdown__link"
href="https://github.com/kneitzel/blog-javafx-series"
>https://github.com/kneitzel/blog-javafx-series</a></p>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="was-sind-maven-und-gradle">
Was sind Maven und Gradle?
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/11/02/javafx-maven-und-gradle/#was-sind-maven-und-gradle" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Was sind Maven und Gradle?" href="#was-sind-maven-und-gradle">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Bei Maven und Gradle handelt es sich um Tools, mit denen ein Projekt verwaltet und gebaut werden kann. Ein wichtiges Feature ist dabei die Verwaltung von Abhängigkeiten, die vom Tool automatisch in der gewünschten Version von einem Repository heruntergeladen und bereitgestellt werden.</p>
<p>Dies verringert die Aufwände bezüglich Einrichtung eines Arbeitsplatzes enorm, da die Anzahl der Abhängigkeiten, die installiert werden müssen, minimiert werden.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h3 id="vorteile">
Vorteile
</h3>
<a data-clipboard-text="https://blog.kneitzel.de/2020/11/02/javafx-maven-und-gradle/#vorteile" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Vorteile" href="#vorteile">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Der große Vorteil dieser Build Tools ist, dass diese von den gängigen Entwicklungsumgebungen (IntelliJ, Eclipse, Netbeans) unterstützt werden. Damit ist ein Projekt unabhängig von einer Entwicklungsumgebung und jeder Entwickler kann mit der Umgebung arbeiten, die er bevorzugt.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="maven">
Maven
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/11/02/javafx-maven-und-gradle/#maven" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Maven" href="#maven">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<div class="gblog-post__anchorwrap flex align-center">
<h3 id="übersicht">
Übersicht
</h3>
<a data-clipboard-text="https://blog.kneitzel.de/2020/11/02/javafx-maven-und-gradle/#übersicht" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Übersicht" href="#%c3%bcbersicht">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Maven entstand im Jahr 2003 (Version 1.x) / 2004 (Version 1.0) und kann somit auf eine recht lange Entwicklungszeit zurückblicken.</p>
<p>Das Tool zeichnet sich dadurch aus, dass es ein festen Lebenszyklus vorgibt, der feste Phasen umfasst in dem viele Dinge standardmäßig verankert sind, so dass oft nur wenig Anpassungen notwendig sind.</p>
<p>Folgende Phasen sind in Maven vorgesehen:</p>
<div class="gblog-post__anchorwrap flex align-center">
<h4 id="archetype">
archetype
</h4>
<a data-clipboard-text="https://blog.kneitzel.de/2020/11/02/javafx-maven-und-gradle/#archetype" class="gblog-post__anchor clip flex align-center" aria-label="Anchor archetype" href="#archetype">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Dient u.a. der Erstellung von Templates, Abhängigkeiten werden aufgelöst und ggf. herunter geladen.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h5 id="validate">
validate
</h5>
<a data-clipboard-text="https://blog.kneitzel.de/2020/11/02/javafx-maven-und-gradle/#validate" class="gblog-post__anchor clip flex align-center" aria-label="Anchor validate" href="#validate">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Validierung des Projektes. Ist die Struktur des Projekts ok?</p>
<div class="gblog-post__anchorwrap flex align-center">
<h6 id="compile">
compile
</h6>
<a data-clipboard-text="https://blog.kneitzel.de/2020/11/02/javafx-maven-und-gradle/#compile" class="gblog-post__anchor clip flex align-center" aria-label="Anchor compile" href="#compile">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Übersetzen des Codes.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h6 id="test">
test
</h6>
<a data-clipboard-text="https://blog.kneitzel.de/2020/11/02/javafx-maven-und-gradle/#test" class="gblog-post__anchor clip flex align-center" aria-label="Anchor test" href="#test">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Ausführung der automatischen Tests mit Hilfe geeigneter Testframeworks.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h6 id="package">
package
</h6>
<a data-clipboard-text="https://blog.kneitzel.de/2020/11/02/javafx-maven-und-gradle/#package" class="gblog-post__anchor clip flex align-center" aria-label="Anchor package" href="#package">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Die Ergebnisse werden zusammengepackt. Häufig handelt es sich um eine jar Datei.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h6 id="integration-test">
integration-test
</h6>
<a data-clipboard-text="https://blog.kneitzel.de/2020/11/02/javafx-maven-und-gradle/#integration-test" class="gblog-post__anchor clip flex align-center" aria-label="Anchor integration-test" href="#integration-test">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Das erstellte Paket wird an einen anderen Ort kopiert und dort getestet. Dies kann z.B. ein Anwendungsserver sein.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h6 id="verify">
verify
</h6>
<a data-clipboard-text="https://blog.kneitzel.de/2020/11/02/javafx-maven-und-gradle/#verify" class="gblog-post__anchor clip flex align-center" aria-label="Anchor verify" href="#verify">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Das erstellte Softwarepaket wird überprüft, um sicher zu stellen, dass die Struktur korrekt ist.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h6 id="install">
install
</h6>
<a data-clipboard-text="https://blog.kneitzel.de/2020/11/02/javafx-maven-und-gradle/#install" class="gblog-post__anchor clip flex align-center" aria-label="Anchor install" href="#install">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Das Softwarepaket wird im lokalen Maven Repository bereitgestellt.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h6 id="deploy">
deploy
</h6>
<a data-clipboard-text="https://blog.kneitzel.de/2020/11/02/javafx-maven-und-gradle/#deploy" class="gblog-post__anchor clip flex align-center" aria-label="Anchor deploy" href="#deploy">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Das Softwarepaket wird im entfernten Maven Repository bereitgestellt.</p>
<p>Dies kann durch Plugins und Maven Archetypen erweitert und verändert werden, so dass z.B. Docker Container gebaut und verteilt werden können.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h3 id="wrapper">
Wrapper
</h3>
<a data-clipboard-text="https://blog.kneitzel.de/2020/11/02/javafx-maven-und-gradle/#wrapper" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Wrapper" href="#wrapper">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Zu Maven gibt es einen Wrapper, der es ermöglicht, dass Maven nicht mehr systemweit auf einem System installiert werden muss. Da unterschiedliche Projekte ggf. unterschiedliche, nicht zueinander kompatible, Versionen von Maven nutzen wollen, ist eine systemweite Installation nicht zielführend.</p>
<p>Stattdessen gibt es ein Script welches die notwendige Version von Maven herunter lädt und innerhalb des Projektverzeichnisses entpackt.</p>
<p><strong>Erzeugung des Wrappers</strong><br>
Es ist möglich, mittels maven ein Wrapper für ein Projekt zu erzeugen. Dazu geht man in das Verzeichnis des Projekts und ruft auf:<br>
„mvn -N io.takari:maven:wrapper“.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h3 id="installation">
Installation
</h3>
<a data-clipboard-text="https://blog.kneitzel.de/2020/11/02/javafx-maven-und-gradle/#installation" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Installation" href="#installation">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Auch wenn eine Installation nicht notwendig ist, ist dies natürlich jederzeit möglich. Das Tool kann einfach als ZIP File heruntergeladen werden. Eine komplexe Installation ist nicht notwendig. Es reicht, das ZIP an einer beliebigen Stelle zu entpacken.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h3 id="dateien-und-verzeichnisse">
Dateien und Verzeichnisse
</h3>
<a data-clipboard-text="https://blog.kneitzel.de/2020/11/02/javafx-maven-und-gradle/#dateien-und-verzeichnisse" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Dateien und Verzeichnisse" href="#dateien-und-verzeichnisse">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<div class="gblog-post__anchorwrap flex align-center">
<h6 id="pomxml">
pom.xml
</h6>
<a data-clipboard-text="https://blog.kneitzel.de/2020/11/02/javafx-maven-und-gradle/#pomxml" class="gblog-post__anchor clip flex align-center" aria-label="Anchor pom.xml" href="#pomxml">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Das Projekt wird in einer pom.xml (POM = Project Object Model) beschrieben, welches sich in dem Projektverzeichnis befindet.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h6 id="src">
src
</h6>
<a data-clipboard-text="https://blog.kneitzel.de/2020/11/02/javafx-maven-und-gradle/#src" class="gblog-post__anchor clip flex align-center" aria-label="Anchor src" href="#src">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Das src Verzeichnis enthält alle Sourcen der Projekts. Diese sind in der Regel aufgeteilt in mehrere Unterordner: src/main für das eigentliche Projekt und src/test für die automatisierten Tests, die nicht mit ausgeliefert werden. Java Quellcode kommt in ein weiteres Unterverzeichnis java und die Ressourcen in das weitere Unterverzeichnis resources.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h6 id="target">
target
</h6>
<a data-clipboard-text="https://blog.kneitzel.de/2020/11/02/javafx-maven-und-gradle/#target" class="gblog-post__anchor clip flex align-center" aria-label="Anchor target" href="#target">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Alle Dateien, die erzeugt werden, werden in dem Verzeichnis target erzeugt. Je nach Art der erzeugten Datei, werden diese in einem entsprechenden Unterverzeichnis angelegt, z.B. target/classes für die class Dateien.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h6 id="mvnw--mvnwcmd--mvn">
mvnw / mvnw.cmd / .mvn
</h6>
<a data-clipboard-text="https://blog.kneitzel.de/2020/11/02/javafx-maven-und-gradle/#mvnw--mvnwcmd--mvn" class="gblog-post__anchor clip flex align-center" aria-label="Anchor mvnw / mvnw.cmd / .mvn" href="#mvnw--mvnwcmd--mvn">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Scripte und Verzeichnis des Wrappers. Das Skript mvnw kann statt mvn bei Maven Aufrufen verwendet werden. Die Dateien des Wrappers incl. Konfiguration finden sich in .mvn/wrapper.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h3 id="beispiel-einer-pomxml">
Beispiel einer pom.xml
</h3>
<a data-clipboard-text="https://blog.kneitzel.de/2020/11/02/javafx-maven-und-gradle/#beispiel-einer-pomxml" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Beispiel einer pom.xml" href="#beispiel-einer-pomxml">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p><strong>03 helloword – maven/pom.xml</strong></p>
<pre tabindex="0"><code><pre class="wp-block-code">```
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>de.kneitzel</groupId>
<artifactId>hellofx</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>hellofx</name>
<url>https://blog.kneitzel.de</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>11.0.2</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>11.0.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.openjfx</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<version>0.0.3</version>
<configuration>
<mainClass>helloworld.HelloWorld</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
</code></pre><p>Diese Datei kann am Anfang immer so übernommen werden. Folgende Werte sind dabei anzupassen:</p>
<div class="gblog-post__anchorwrap flex align-center">
<h6 id="groupid--artifactid--version--name--url">
groupId / artifactId / version / name / url
</h6>
<a data-clipboard-text="https://blog.kneitzel.de/2020/11/02/javafx-maven-und-gradle/#groupid--artifactid--version--name--url" class="gblog-post__anchor clip flex align-center" aria-label="Anchor groupId / artifactId / version / name / url" href="#groupid--artifactid--version--name--url">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Die ersten drei Werte bilden die id des Projekts, welches eindeutig sein sollte. Die übrigen sollten aber auch angepasst werden.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h6 id="mavencompilersource--mavencompilertarget">
maven.compiler.source / maven.compiler.target
</h6>
<a data-clipboard-text="https://blog.kneitzel.de/2020/11/02/javafx-maven-und-gradle/#mavencompilersource--mavencompilertarget" class="gblog-post__anchor clip flex align-center" aria-label="Anchor maven.compiler.source / maven.compiler.target" href="#mavencompilersource--mavencompilertarget">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Dies kennzeichnet die Java Version, die wir nutzen wollen. In dem Beispiel ist dies Java 11.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h6 id="dependencies">
dependencies
</h6>
<a data-clipboard-text="https://blog.kneitzel.de/2020/11/02/javafx-maven-und-gradle/#dependencies" class="gblog-post__anchor clip flex align-center" aria-label="Anchor dependencies" href="#dependencies">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Die Abhängigkeiten sind hier einzutragen. Die vorhandenen Libraries auf maven central kann man sich auf <a
class="gblog-markdown__link"
href="https://mvnrepository.com/"
>https://mvnrepository.com/</a> ansehen.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h6 id="buildplugins">
build/plugins
</h6>
<a data-clipboard-text="https://blog.kneitzel.de/2020/11/02/javafx-maven-und-gradle/#buildplugins" class="gblog-post__anchor clip flex align-center" aria-label="Anchor build/plugins" href="#buildplugins">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Für JavaFX Applikationen wird das javafx-maven-plugin benötigt. Dieses muss eingebunden werden. Weiterhin wird die Klasse mit der main Methode angegeben, damit das plugin die Applikation auch starten kann.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h3 id="ausprobieren">
Ausprobieren
</h3>
<a data-clipboard-text="https://blog.kneitzel.de/2020/11/02/javafx-maven-und-gradle/#ausprobieren" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Ausprobieren" href="#ausprobieren">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Wir können maven einfach direkt mit dem Beispielprojekt ausprobieren. Dazu wechseln wir in das Verzeichnis „03 helloworld – maven“ und geben da einen der folgenden Befehle ein:</p>
<ul>
<li>mvnw clean<br>
Dies bereinigt das Projekt.</li>
<li>mvnw package<br>
Dies übersetzt das Projekt und baut ein jar File. Dies kann in dem Verzeichnis Target in den diversen Verzeichnissen etwas nachvollzogen werden.</li>
<li>mvnw javafx:run<br>
Dies baut das Projekt und führt die Anwendung danach aus.</li>
</ul>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="gradle">
Gradle
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/11/02/javafx-maven-und-gradle/#gradle" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Gradle" href="#gradle">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<div class="gblog-post__anchorwrap flex align-center">
<h3 id="übersicht-1">
Übersicht
</h3>
<a data-clipboard-text="https://blog.kneitzel.de/2020/11/02/javafx-maven-und-gradle/#übersicht-1" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Übersicht" href="#%c3%bcbersicht-1">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Gradle ist etwas jünger und entstand 2007. Es hat diverse Dinge von Maven übernommen wie z.B. die Verzeichnisstruktur und das automatische Laden von Abhängigkeiten aus Maven Repositories.</p>
<p>So wie Maven auch, gibt es weitgehende Standards, so dass die Projekt-Konfiguration sehr klein ausfallen kann. Für ein Java Projekt könnte eine Zeile „apply plugin: ‚java’“ ausreichend sein.</p>
<p>Statt einer XML Datei hat Gradle eine eigene Domänenspezifische Sprache für die Konfiguration.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h3 id="wrapper-1">
Wrapper
</h3>
<a data-clipboard-text="https://blog.kneitzel.de/2020/11/02/javafx-maven-und-gradle/#wrapper-1" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Wrapper" href="#wrapper-1">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>So wie bei Maven existiert auch für Gradle ein Wrapper.</p>
<div class="is-layout-flow wp-block-group"><div class="wp-block-group__inner-container">**Erzeugung des Wrappers**
Es ist möglich, mittels gradle ein Wrapper für ein Projekt zu erzeugen. Dazu geht man in das Verzeichnis des Projekts und ruft auf: „gradle wrapper“.
</div></div>### Installation
<p>Auch wenn eine Installation nicht notwendig ist, ist dies natürlich jederzeit möglich. Das Tool kann einfach als ZIP File heruntergeladen werden. Eine komplexe Installation ist nicht notwendig. Es reicht, das ZIP an einer beliebigen Stelle zu entpacken.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h3 id="dateien-und-verzeichnisse-1">
Dateien und Verzeichnisse
</h3>
<a data-clipboard-text="https://blog.kneitzel.de/2020/11/02/javafx-maven-und-gradle/#dateien-und-verzeichnisse-1" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Dateien und Verzeichnisse" href="#dateien-und-verzeichnisse-1">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<div class="gblog-post__anchorwrap flex align-center">
<h6 id="buildgradle--settingsgradle--gradleproperties">
build.gradle / settings.gradle / gradle.properties
</h6>
<a data-clipboard-text="https://blog.kneitzel.de/2020/11/02/javafx-maven-und-gradle/#buildgradle--settingsgradle--gradleproperties" class="gblog-post__anchor clip flex align-center" aria-label="Anchor build.gradle / settings.gradle / gradle.properties" href="#buildgradle--settingsgradle--gradleproperties">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Das Projekt wird in einer build.gradle beschrieben, welches sich in dem Projektverzeichnis befindet. Die anderen Dateien sind optional.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h6 id="src-1">
src
</h6>
<a data-clipboard-text="https://blog.kneitzel.de/2020/11/02/javafx-maven-und-gradle/#src-1" class="gblog-post__anchor clip flex align-center" aria-label="Anchor src" href="#src-1">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Das src Verzeichnis enthält alle Sourcen der Projekts. Diese sind in der Regel aufgeteilt in mehrere Unterordner: src/main für das eigentliche Projekt und src/test für die automatisierten Tests, die nicht mit ausgeliefert werden. Java Quellcode kommt in ein weiteres Unterverzeichnis java und die Ressourcen in das weitere Unterverzeichnis resources.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h6 id="gradlew--gradlewbat--gradle">
gradlew / gradlew.bat / gradle
</h6>
<a data-clipboard-text="https://blog.kneitzel.de/2020/11/02/javafx-maven-und-gradle/#gradlew--gradlewbat--gradle" class="gblog-post__anchor clip flex align-center" aria-label="Anchor gradlew / gradlew.bat / gradle" href="#gradlew--gradlewbat--gradle">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Scripte und Verzeichnis des Wrappers. Das Skript gradlew kann statt gradle bei Gradle Aufrufen verwendet werden. Die Dateien des Wrappers incl. Konfiguration finden sich in gradle/wrapper.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h3 id="beispiel-einer-buildgradle">
Beispiel einer build.gradle
</h3>
<a data-clipboard-text="https://blog.kneitzel.de/2020/11/02/javafx-maven-und-gradle/#beispiel-einer-buildgradle" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Beispiel einer build.gradle" href="#beispiel-einer-buildgradle">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<pre tabindex="0"><code><pre class="wp-block-code">```
plugins {
id 'application'
id 'org.openjfx.javafxplugin' version '0.0.8'
}
javafx {
version = "11.0.2"
modules = [ 'javafx.controls', 'javafx.fxml' ]
}
group 'de.kneitzel'
version '1.0-SNAPSHOT'
mainClassName = 'helloworld.HelloWorld'
repositories {
mavenCentral()
}
dependencies {
compile group: 'org.openjfx', name: 'javafx-controls', version: '11.0.2'
compile group: 'org.openjfx', name: 'javafx-fxml', version: '11.0.2'
testCompile group: 'junit', name: 'junit', version: '4.12'
}
</code></pre><p>Ähnlich wie in Maven findet sich die id der Projekts (group/version – name ist in settings.gradle) und es wird ein javafx Plugin eingebunden.</p>
<p>Die Klasse mit der main Methode wird benannt und die Dependencies aufgelistet.</p>
<p>Zusätzlich ist es aber noch notwendig, die javafx Version sowie die verwendeten Module anzugeben.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="links">
Links
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/11/02/javafx-maven-und-gradle/#links" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Links" href="#links">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<ul>
<li>Maven <a
class="gblog-markdown__link"
href="https://maven.apache.org/"
>https://maven.apache.org/</a></li>
<li>Gradle <a
class="gblog-markdown__link"
href="https://gradle.org/"
>https://gradle.org/</a></li>
<li>Maven Repository <a
class="gblog-markdown__link"
href="https://mvnrepository.com/"
>https://mvnrepository.com/</a></li>
</ul>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="änderungsnachweis">
Änderungsnachweis
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/11/02/javafx-maven-und-gradle/#änderungsnachweis" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Änderungsnachweis" href="#%c3%a4nderungsnachweis">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<ul>
<li>2020-11-02 Überarbeitung Layout</li>
<li>2020-10-30 Erste Veröffentlichung</li>
</ul>
JavaFX: Installationhttps://blog.kneitzel.de/2020/10/29/javafx-uebersicht/2020-10-29T10:45:01+00:002023-01-19T22:51:40+01:00
<p>Eine kleine Übersicht über die notwendigen Abhängigkeiten von JavaFX – das sich zum Glück rein auf die Abhängigkeit zu Java reduzieren lässt, so dass es in diesem Blog nach minimaler Einstufung von JavaFX in erster Linie um die Installation der „richtigen“ Java Version geht.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="teile-der-javafx-serie-aktualisiert">
Teile der JavaFX Serie (aktualisiert)
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/10/29/javafx-uebersicht/#teile-der-javafx-serie-aktualisiert" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Teile der JavaFX Serie (aktualisiert)" href="#teile-der-javafx-serie-aktualisiert">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<ul>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/29/javafx-uebersicht-planung/"
>JavaFX 01: Übersicht / Planung</a> (<a
class="gblog-markdown__link"
href="https://youtu.be/emCUpGFpf_Q"
>YouTube</a>)</li>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/24/javafx-uebersicht/"
>JavaFX 02: Installation</a> (<a
class="gblog-markdown__link"
href="https://youtu.be/ZmDUr7fwABM"
>YouTube</a>)</li>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/11/02/javafx-maven-und-gradle/"
>JavaFX 03: Maven & Gradle</a> (<a
class="gblog-markdown__link"
href="https://youtu.be/daVCphI0qZ0"
>YouTube</a>)</li>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/11/02/javafx-intellij/"
>JavaFX 04: IntelliJ</a> (<a
class="gblog-markdown__link"
href="https://youtu.be/Lh8MqSrHIb4"
>YouTube</a>)</li>
</ul>
<div class="gblog-post__anchorwrap flex align-center">
<h3 id="teile-der-javafx-serie-alt--geplant">
Teile der JavaFX Serie (alt / geplant)
</h3>
<a data-clipboard-text="https://blog.kneitzel.de/2020/10/29/javafx-uebersicht/#teile-der-javafx-serie-alt--geplant" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Teile der JavaFX Serie (alt / geplant)" href="#teile-der-javafx-serie-alt--geplant">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<ul>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/26/javafx-scene-builder/"
>JavaFX 05: Scene Builder</a></li>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/26/javafx-erlaeuterungen-der-applikation/"
>JavaFX –: Erläuterung der Applikation</a></li>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/26/javafx-model-view-controller/"
>JavaFX 06: Model / View / Controller</a></li>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/29/javafx-mvvm/"
>JavaFX 07: MVVM</a></li>
<li>JavaFX: Komplette MVVM Applikation (geplant)</li>
<li>JavaFX: Layouts (geplant)</li>
<li>JavaFX: Formulare einfach erstellen (geplant)</li>
<li>JavaFX: Multi Plattform (geplant)</li>
</ul>
<figure class="wp-block-embed-youtube wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper"><iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" height="371" loading="lazy" src="https://www.youtube.com/embed/ZmDUr7fwABM?feature=oembed" title="JavaFX Blog Serie - 02 Java Installation" width="660"></iframe></div></figure>## Code der JavaFX Serie
<p>Der Source Code sowie alle Dokumente finden sich auf GitHub: <a
class="gblog-markdown__link"
href="https://github.com/kneitzel/blog-javafx-series"
>https://github.com/kneitzel/blog-javafx-series</a></p>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="übersicht-über-javafx">
Übersicht über JavaFX
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/10/29/javafx-uebersicht/#übersicht-über-javafx" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Übersicht über JavaFX" href="#%c3%bcbersicht-%c3%bcber-javafx">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>JavaFX ist ein modernes Framework zur Erstellung von graphischen Oberflächen in Java. JavaFX ist eine eigenständige Komponente, die oft nicht im Java Development Kit integriert ist. Bei Oracle / OpenJDK war JavaFX in den Downloads ab Java SE 7 Update 2 bis einschließlich Version 10. Ab Version 11 war dies nicht mehr dabei. Es gibt aber teilweise Anbieter, die auch aktuelle OpenJDK Versionen mit integriertem JavaFX anbieten.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="unterschied-zu-swing">
Unterschied zu Swing
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/10/29/javafx-uebersicht/#unterschied-zu-swing" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Unterschied zu Swing" href="#unterschied-zu-swing">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Ein wichtiger Unterschied zu Swing ist, dass eine Oberfläche in einem separaten File beschrieben werden kann, statt diese in Java selbst zusammen zu stellen (deklarative Oberfläche im Gegensatz zu der programmierten Oberfläche).</p>
<p>Des Weiteren bietet JavaFX einige technische Aspekte wie z.B. das Binding von Controls an Modelle.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="installation">
Installation
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/10/29/javafx-uebersicht/#installation" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Installation" href="#installation">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Da es nicht mehr fester Bestandteil von Java ist, sind manuelle Aktivitäten notwendig. Dazu gibt es zwei Möglichkeiten:</p>
<div class="gblog-post__anchorwrap flex align-center">
<h3 id="eigenständige-installation">
Eigenständige Installation
</h3>
<a data-clipboard-text="https://blog.kneitzel.de/2020/10/29/javafx-uebersicht/#eigenständige-installation" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Eigenständige Installation" href="#eigenst%c3%a4ndige-installation">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Es zwei Möglichkeiten für eine Installation. Zum einen kann auf ein JDK zurückgegriffen werden, in dem das JavaFX noch eingebunden ist. Dies ist sehr einfach, aber alle Entwickler am Projekt müssen genau solch eine Installation wählen.</p>
<p>Oder das JavaFX wird eigenständig installiert. Damit dies aber gefunden wird, muss der Ort konfiguriert werden, indem ein Module Path gesetzt wird. Dies erfordert Angaben bei in der Entwicklungsumgebung oder auf der Kommandozeile, die dann auch jeder Entwickler machen muss.</p>
<p>Wenn dieser Weg gewählt wird, dann kann auch ein JDK mit eingebautem JavaFX benutzt werden. Dann ist keine komplexe Konfiguration notwendig, aber die Entwickler sind auf eines der eher raren Angebote angewiesen. Ein solches JDK findet sich u.a. auf <a
class="gblog-markdown__link"
href="https://bell-sw.com/"
>https://bell-sw.com/</a>.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h3 id="gradle--maven-build-tool">
Gradle / Maven Build Tool
</h3>
<a data-clipboard-text="https://blog.kneitzel.de/2020/10/29/javafx-uebersicht/#gradle--maven-build-tool" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Gradle / Maven Build Tool" href="#gradle--maven-build-tool">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>JavaFX kann als Abhängigkeit in den Build Tools Gradle oder Maven eingetragen werden. Neben den Abhängigkeiten sind auch noch ein paar weitere Einträge notwendig, aber diese sind für alle Entwickler an einem Projekt gleich. Die Entwickler müssen auf ihren Computern keine weiteren Dinge installieren.</p>
<p>Dies ist die Methode, welche ich im Rahmen der JavaFX Serie nutzen werde und euch im Detail vorstellen werde. Dabei werde ich mich vor allem auf Gradle konzentrieren, aber ich werde auch ein Maven Projekt kurz vorstellen.</p>
<figure class="wp-block-table">| **Hinweis** |
|---|
| Bei den Build Tools ist in der Regel keine systemweite Installation notwendig. Statt dessen wird ein sogenannter Wrapper im Projekt integriert, der die korrekte Version des Build Tools im Projektverzeichnis zur Verfügung stellt. |
</figure>## Java Version
<p>Bei der Auswahl der richtigen Java Installation sind ein paar Punkte zu beachten.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h3 id="jre-vs-jdk">
JRE vs. JDK
</h3>
<a data-clipboard-text="https://blog.kneitzel.de/2020/10/29/javafx-uebersicht/#jre-vs-jdk" class="gblog-post__anchor clip flex align-center" aria-label="Anchor JRE vs. JDK" href="#jre-vs-jdk">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Generell wird bei Java zwischen dem Runtime Environment (JRE) und dem Development Kit (JDK) unterschieden.</p>
<p>Um Java Programme auszuführen wird nur ein JRE benötigt. Das JDK enthält neben einem JRE noch alle Komponenten, die der Entwicklung von Java Programmen dienen, z.B. den Java Compiler.</p>
<figure class="wp-block-table">| **Wichtig** |
|---|
| Wir benötigen somit auf jeden Fall ein JDK. |
| **Achtung** |
| Oracle bietet auf [http://java.com](http://java.com/) ein altes JRE an. Dieses sollte man nicht installieren! Es wird nicht benötigt und neigt eher dazu, Probleme zu bereiten! |
</figure>### Java vs. OpenJDK
<p>Es gibt das Produkt Java von Oracle, welches unter einer speziellen Lizenz von Oracle steht und frei heruntergeladen werden kann. Des Weiteren gibt es das OpenJDK, welches die open source Variante ist und einem vollwertigen Java entspricht und das auch von vielen Firmen aktiv weiterentwickelt wird. (z.B. IBM, Azul, …)</p>
<figure class="wp-block-table">| **Tipp** |
|---|
| Die OpenJDK Lizenz gibt einem deutlich mehr Freiheiten und birgt bei der Nutzung deutlich geringere Risiken einer Lizenzverletzung. Oracle Java lässt sich meist frei nutzen, aber es ist die Lizenz zu prüfen um sicher zu gehen, dass die Nutzung abgedeckt ist und keine kommerzielle Lizenz erworben werden muss! |
</figure>### LTS vs. aktueller Version
<p>Java wird aktiv weiterentwickelt und es kommen regelmäßig neue Versionen. Aktuell sind wir zum Zeitpunkt dieser Bearbeitung bei Java 15. Sobald eine neue Version herausgegeben wurde, wird die alte Version in der Regel nicht mehr aktualisiert. Für Security Updates ist es dann notwendig, dass die neue Version installiert wird – was leider auch zu Kompatibilitätsproblemen führen kann.</p>
<p>Diese Problematik wird gelöst, indem sogenannte Long Time Support (LTS) Version bereitgestellt werden. Diese Versionen werden deutlich länger mit Updates versorgt und verringern die Wahrscheinlichkeit, dass es bei dem Installieren eines neueren Builds der LTS Version zu Problem kommt. Derzeit werden die LTS Version Java 8 und Java 11 bereitgestellt.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h3 id="diverse-jvm">
Diverse JVM
</h3>
<a data-clipboard-text="https://blog.kneitzel.de/2020/10/29/javafx-uebersicht/#diverse-jvm" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Diverse JVM" href="#diverse-jvm">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Es gibt teilweise unterschiedliche Java Virtual Machines (JVM). Die original JVM ist die HotSpot JVM von Oracle. Die Eclipse Foundation hat die OpenJ9 JVM entwickelt, die mehr Wert auf schnelle Startzeit und geringen Speicherverbrauch legt. Bei AdoptOpenJDK kann zwischen den beiden Varianten gewählt werden. Da beide universell einsetzbar sein, ist dies eine Wahl, bei der man nicht viel falsch machen kann.</p>
<figure class="wp-block-table">| **Empfehlung** |
|---|
| Ich rate zu der Version 11 eines OpenJDK. Unter Windows / macOS kann auf ein JDK von [https://adoptopenjdk.net](https://adoptopenjdk.net/) zurück gegriffen werden. Unter Linux wird einfach das OpenJDK aus dem Repository verwendet, z.B. mittels sudo apt-get install openjdk-11-jdk |
</figure>## Links
<ul>
<li>JavaFX / openjfx Homepage: <a
class="gblog-markdown__link"
href="https://openjfx.io/"
>https://openjfx.io/</a></li>
<li>Java OpenJDK AdoptOpenJDK</li>
<li>Entwicklungsumgebungen: JetBrains IntelliJ Community, Eclipse, Netbeans</li>
<li>Repository mit Code für diese JavaFX Blog Serie: <a
class="gblog-markdown__link"
href="https://github.com/kneitzel/blog-javafx-series"
>https://github.com/kneitzel/blog-javafx-series</a></li>
</ul>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="änderungsnachweis">
Änderungsnachweis
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/10/29/javafx-uebersicht/#änderungsnachweis" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Änderungsnachweis" href="#%c3%a4nderungsnachweis">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<ul>
<li>2020-11-16 Einfügen YouTube Video</li>
<li>2020-10-29 Komplette Überarbeitung</li>
<li>2020-07-03 Wechsel zu einem Repository für die ganze Serie.</li>
</ul>
JavaFX: Übersicht / Planunghttps://blog.kneitzel.de/2020/10/29/javafx-uebersicht-planung/2020-10-29T10:42:07+00:002023-01-16T20:14:20+01:00
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="teile-der-javafx-serie-aktualisiert">
Teile der JavaFX Serie (aktualisiert)
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/10/29/javafx-uebersicht-planung/#teile-der-javafx-serie-aktualisiert" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Teile der JavaFX Serie (aktualisiert)" href="#teile-der-javafx-serie-aktualisiert">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<ul>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/29/javafx-uebersicht-planung/"
>JavaFX 01: Übersicht / Planung</a> (<a
class="gblog-markdown__link"
href="https://youtu.be/emCUpGFpf_Q"
>YouTube</a>)</li>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/24/javafx-uebersicht/"
>JavaFX 02: Installation</a> (<a
class="gblog-markdown__link"
href="https://youtu.be/ZmDUr7fwABM"
>YouTube</a>)</li>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/11/02/javafx-maven-und-gradle/"
>JavaFX 03: Maven & Gradle</a> (<a
class="gblog-markdown__link"
href="https://youtu.be/daVCphI0qZ0"
>YouTube</a>)</li>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/11/02/javafx-intellij/"
>JavaFX 04: IntelliJ</a> (<a
class="gblog-markdown__link"
href="https://youtu.be/Lh8MqSrHIb4"
>YouTube</a>)</li>
</ul>
<div class="gblog-post__anchorwrap flex align-center">
<h3 id="teile-der-javafx-serie-alt--geplant">
Teile der JavaFX Serie (alt / geplant)
</h3>
<a data-clipboard-text="https://blog.kneitzel.de/2020/10/29/javafx-uebersicht-planung/#teile-der-javafx-serie-alt--geplant" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Teile der JavaFX Serie (alt / geplant)" href="#teile-der-javafx-serie-alt--geplant">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<ul>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/26/javafx-scene-builder/"
>JavaFX 05: Scene Builder</a></li>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/26/javafx-erlaeuterungen-der-applikation/"
>JavaFX –: Erläuterung der Applikation</a></li>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/26/javafx-model-view-controller/"
>JavaFX 06: Model / View / Controller</a></li>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/29/javafx-mvvm/"
>JavaFX 07: MVVM</a></li>
<li>JavaFX: Komplette MVVM Applikation (geplant)</li>
<li>JavaFX: Layouts (geplant)</li>
<li>JavaFX: Formulare einfach erstellen (geplant)</li>
<li>JavaFX: Multi Plattform (geplant)</li>
</ul>
<figure class="wp-block-embed-youtube wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper"><iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" height="371" loading="lazy" src="https://www.youtube.com/embed/emCUpGFpf_Q?feature=oembed" title="JavaFX Blog Serie - 01 Übersicht / Einführung" width="660"></iframe></div></figure>## Code der JavaFX Serie
<p>Der Source Code sowie alle Dokumente finden sich auf GitHub: <a
class="gblog-markdown__link"
href="https://github.com/kneitzel/blog-javafx-series"
>https://github.com/kneitzel/blog-javafx-series</a></p>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="überblick">
Überblick
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/10/29/javafx-uebersicht-planung/#überblick" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Überblick" href="#%c3%bcberblick">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>In dieser Serie zu JavaFX möchte ich einige Punkte der JavaFX Entwicklung aufgreifen und behandeln.</p>
<p>Nachdem ich einen ersten Ansatz gestartet hatte, war ich mit dem Ergebnis unzufrieden und ich habe mir Alternativen überlegt. Es gibt einige Veränderungen an der Serie, denn ich werde zukünftig dreigleisig fahren:</p>
<ol>
<li>Blog Beiträge. Diese sind sowohl im Web als auch als Word Dokument auf Github zu finden.</li>
<li>Word / PDF Dokument mit gesammeltem Wissen – gibt in etwa die Blog Inhalte wieder, aber ggf. umstrukturiert. Die Inhalte sind auch nicht identisch.</li>
<li>YouTube Videos – Ich erstelle zu einzelnen Blogs YouTube Videos, in denen ich versuche, die Punkte etwas zu zeigen und zu erläutern.</li>
</ol>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="vorhandene-inhalte">
Vorhandene Inhalte
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/10/29/javafx-uebersicht-planung/#vorhandene-inhalte" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Vorhandene Inhalte" href="#vorhandene-inhalte">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<div class="gblog-post__anchorwrap flex align-center">
<h4 id="übersicht--planung">
Übersicht / Planung
</h4>
<a data-clipboard-text="https://blog.kneitzel.de/2020/10/29/javafx-uebersicht-planung/#übersicht--planung" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Übersicht / Planung" href="#%c3%bcbersicht--planung">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>In diesem Abschnitt gebe ich einen Überblick über die Serie und das Format.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h4 id="installation">
Installation
</h4>
<a data-clipboard-text="https://blog.kneitzel.de/2020/10/29/javafx-uebersicht-planung/#installation" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Installation" href="#installation">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Hier wird nur ein kleiner Überblick gegeben und Hinweis zu einer Java Installation gegeben.</p>
<p>Die ursprünglich enthaltene Einführung in Gradle hat einen eigenständigen Eintrag erhalten.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h4 id="maven-amp-gradle">
Maven & Gradle
</h4>
<a data-clipboard-text="https://blog.kneitzel.de/2020/10/29/javafx-uebersicht-planung/#maven-amp-gradle" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Maven & Gradle" href="#maven-amp-gradle">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Übersicht über die Nutzung von JavaFX mit Maven und Gradle. Erläuterung des Beispiel-Projekts.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h4 id="scene-builder">
Scene Builder
</h4>
<a data-clipboard-text="https://blog.kneitzel.de/2020/10/29/javafx-uebersicht-planung/#scene-builder" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Scene Builder" href="#scene-builder">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Der Scene Builder ist ein GUI Editor, mit dem man auf einfache Art und Weise eine Oberfläche zusammen klicken kann. Diese ist ein separates Tool und ist damit das Mittel meiner Wahl, da es die Aufwände klein hält und eigentlich (fast) keine Stolpersteine bereithält.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h4 id="erläuterung-der-applikation">
Erläuterung der Applikation
</h4>
<a data-clipboard-text="https://blog.kneitzel.de/2020/10/29/javafx-uebersicht-planung/#erläuterung-der-applikation" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Erläuterung der Applikation" href="#erl%c3%a4uterung-der-applikation">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Ich habe in den ersten Teilen einfach Code präsentiert, ohne dies näher zu erläutern (um die Beiträge fokussiert auf das eigentliche Thema zu halten). Das hole ich hier nach.<br>
(Wird bei der Nachbearbeitung entfallen und in Scene Builder mit aufgehen!)</p>
<div class="gblog-post__anchorwrap flex align-center">
<h4 id="model--view--controller">
Model / View / Controller
</h4>
<a data-clipboard-text="https://blog.kneitzel.de/2020/10/29/javafx-uebersicht-planung/#model--view--controller" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Model / View / Controller" href="#model--view--controller">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>JavaFX verfolgt ein MVC Konzept. Dies findet sich leider in den meisten Applikationen nicht wieder. Dies soll ein einfacher kleiner Einstieg in die MVC Entwicklung darstellen und ich zeige auf, was für Probleme ich sehe und mit welchen Mitteln diese ggf. gelöst werden könnten. Leider mit dem Resümee, dass ich MVC mit JavaFX eher ablehne.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h4 id="mvvm">
MVVM
</h4>
<a data-clipboard-text="https://blog.kneitzel.de/2020/10/29/javafx-uebersicht-planung/#mvvm" class="gblog-post__anchor clip flex align-center" aria-label="Anchor MVVM" href="#mvvm">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Da ich das MVC Patten eher ablehne präsentiere ich hier eine Lösung, die ich für mich als gut empfinde und ich die weiterempfehlen würde.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h4 id="komplette-mvvm-applikation">
Komplette MVVM Applikation
</h4>
<a data-clipboard-text="https://blog.kneitzel.de/2020/10/29/javafx-uebersicht-planung/#komplette-mvvm-applikation" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Komplette MVVM Applikation" href="#komplette-mvvm-applikation">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Beschreibung eine kompletten MVVM Applikation, um einige Punkte zu demonstrieren. Die Applikation wird eine kleine Adressverwaltung sein, so dass man das Öffnen und Schließen eines Fensters sowie das saubere Binden an Properties sehen kann.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h4 id="layouts">
Layouts
</h4>
<a data-clipboard-text="https://blog.kneitzel.de/2020/10/29/javafx-uebersicht-planung/#layouts" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Layouts" href="#layouts">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>JavaFX bietet viele Möglichkeiten, Layouts zu gestalten. Diese möchte ich etwas erläutern, um zu verdeutlichen, dass man kein Scene Builder braucht, um Oberflächen zu gestallten. Dazu stelle ich die einzelnen Container vor (HBox, VBox und diverse Panes)</p>
<div class="gblog-post__anchorwrap flex align-center">
<h4 id="formulare-einfach-erstellen">
Formulare einfach erstellen
</h4>
<a data-clipboard-text="https://blog.kneitzel.de/2020/10/29/javafx-uebersicht-planung/#formulare-einfach-erstellen" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Formulare einfach erstellen" href="#formulare-einfach-erstellen">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Es gibt zu JavaFX interessante Erweiterungen. Eine Erweiterung dient der einfachen Erstellung von Formularen und diese Erweiterung möchte ich vorstellen.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h4 id="multi-platform">
Multi Platform
</h4>
<a data-clipboard-text="https://blog.kneitzel.de/2020/10/29/javafx-uebersicht-planung/#multi-platform" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Multi Platform" href="#multi-platform">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Es gibt die Möglichkeit, JavaFX Applikationen auf vielen Plattformen auszuführen. Diese Möglichkeiten werden in diesem Blog Beitrag erläutert und es wird eine Übersicht über die Möglichkeiten gegeben.</p>
<p>Es fehlt Dir ein Punkt, der Dich bezüglich JavaFX interessiert? Schreib mir einen Kommentar hier im Blog oder schreib mir im <a
class="gblog-markdown__link"
href="https./www.java-forum.org"
>Java-Forum</a>: Dort bin ich als kneitzel unterwegs. Natürlich kannst Du mich auch per Email erreichen unter: <a
class="gblog-markdown__link"
href="mailto:konrad@kneitzel.de"
>konrad@kneitzel.de</a></p>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="links">
Links
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/10/29/javafx-uebersicht-planung/#links" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Links" href="#links">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<ul>
<li>Java-Forum: <a
class="gblog-markdown__link"
href="https://www.java-forum.org/"
>https://www.java-forum.org/</a></li>
<li>Repository mit Code für diese JavaFX Blog Serie: <a
class="gblog-markdown__link"
href="https://github.com/kneitzel/blog-javafx-series"
>https://github.com/kneitzel/blog-javafx-series</a></li>
</ul>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="edit">
Edit
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/10/29/javafx-uebersicht-planung/#edit" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Edit" href="#edit">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<ul>
<li>2020-11-08 Einbettung des YouTube Videos</li>
<li>2020-11-02 Diverse Korrekturen und Verbesserungen</li>
<li>2020-10-29 Komplette Überarbeitung</li>
<li>2020-07-03 Wechsel zu einem Repository für die ganze Serie.</li>
<li>2020-06-29 MVVM veröffentlicht und komplette MVVM Applikation als weiteren Punkt eingeschoben.</li>
</ul>
JavaFX: MVVMhttps://blog.kneitzel.de/2020/06/29/javafx-mvvm/2020-06-29T15:03:47+00:002023-01-19T22:51:40+01:00
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="javafx-serie">
JavaFX Serie
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/06/29/javafx-mvvm/#javafx-serie" class="gblog-post__anchor clip flex align-center" aria-label="Anchor JavaFX Serie" href="#javafx-serie">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<ul>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/29/javafx-uebersicht-planung/"
>JavaFX: Übersicht / Planung</a></li>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/24/javafx-uebersicht/"
>JavaFX: Installation / erste Applikation</a></li>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/26/javafx-scene-builder/"
>JavaFX: Scene Builder</a></li>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/26/javafx-erlaeuterungen-der-applikation/"
>JavaFX: Erläuterung der Applikation</a></li>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/26/javafx-model-view-controller/"
>JavaFX: Model / View / Controller</a></li>
<li><strong>JavaFX: MVVM</strong></li>
<li>JavaFX: Komplette MVVM Applikation</li>
<li>JavaFX: Layouts (geplant)</li>
<li>JavaFX: Formulare einfach erstellen (geplant)</li>
<li>JavaFX: Multi Plattform (geplant)</li>
</ul>
<p>Wir haben uns im letzten Beitrag etwas mit der Aufteilung in Model / View / Controller beschäftigt und mussten in der View für das Binding teilweise auf Code ausweichen. Dies haben wir in Form von kleinen JavaScript Elementen eingefügt, was natürlich nicht unbedingt optimal ist.</p>
<p>Besonders schwerwiegend war, dass wir uns vom SceneBuilder verabschiedet haben, der hier mit gewissen Teilen Probleme bekommen hat.</p>
<p>Um diese Problematik aufzulösen, kommen wir automatisch zu einem neuen Pattern: Aus dem Model View Controller (MVC) Pattern wird ein Model – View – View Model (MVVM) Pattern.</p>
<p>Die erste wichtige Veränderung: Unsere View wird aus zwei Bestandteilen bestehen: Wie gewohnt das fxml aber es kommt auch eine Java Datei hinzu. Dies macht Sinn, denn wir haben bereits festgestellt, dass wir Code in der View benötigen und daher können wir dies in eine separate java Datei packen.</p>
<p>Desweiteren bekommen wir ein View Model. Für unser Binding brauchten wir in den vorhergehenden Beiträgen ein Model, welches mit JavaFX spezifischen Properties arbeitete. Wenn wir aber Software Entwickeln, dann hatten unsere Models (hoffentlich) statt z.B. (Simple)StringProperties immer Strings. Wir hatten hier also immer einen massiven Mehraufwand und den können wir jetzt gezielt abbilden: Wir haben ein dediziertes View Model. In diesem verwenden wir dann unser Model, das im Rahmen der „normalen Java Entwicklung“ entstanden ist.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="library-für-mvvm">
Library für MVVM
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/06/29/javafx-mvvm/#library-für-mvvm" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Library für MVVM" href="#library-f%c3%bcr-mvvm">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Rund um MVVM gibt es sehr viel Dokumentation. Microsoft hat sehr stark auf MVVM zugegriffen z.B. in seinem Windows Presentation Framework (WPF). Ein Projekt hat dies auf JavaFX adaptiert: <a
class="gblog-markdown__link"
href="https://github.com/sialcasa/mvvmFX"
>mvvmFX</a>. Im <a
class="gblog-markdown__link"
href="https://github.com/sialcasa/mvvmFX/wiki"
>Wiki</a> finden sich zu MVVM auch gute Links, die das Thema sehr ausführlich beschreiben und ich kann nur raten, dies im Detail zu lesen um ein tiefes Verständnis zu bekommen.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="anpassen-unseres-projekts">
Anpassen unseres Projekts
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/06/29/javafx-mvvm/#anpassen-unseres-projekts" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Anpassen unseres Projekts" href="#anpassen-unseres-projekts">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Solltest Du der Serie nicht gefolgt sein: Der Code der ganzen JavaFX Serie findet sich unter <a
class="gblog-markdown__link"
href="https://github.com/kneitzel/blog-javafx-series"
>https://github.com/kneitzel/blog-javafx-series</a>. Der MVC Code in „04 helloworld-mvc“ und die mvvm Version in „05 helloworld-mvvm“</p>
<div class="gblog-post__anchorwrap flex align-center">
<h4 id="abhängigkeit">
Abhängigkeit
</h4>
<a data-clipboard-text="https://blog.kneitzel.de/2020/06/29/javafx-mvvm/#abhängigkeit" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Abhängigkeit" href="#abh%c3%a4ngigkeit">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Wir wollen die mvvmFX Library nutzen, daher tragen wir diese als Abhängigkeit in unsere build.gradle Datei ein, indem wir in dem dependency Block einfügen:</p>
<pre tabindex="0"><code>compile group: 'de.saxsys', name: 'mvvmfx', version: '1.8.0'
</code></pre><div class="gblog-post__anchorwrap flex align-center">
<h4 id="neue-klasse-helloworldentitygreeting">
Neue Klasse: helloworld.entity.Greeting
</h4>
<a data-clipboard-text="https://blog.kneitzel.de/2020/06/29/javafx-mvvm/#neue-klasse-helloworldentitygreeting" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Neue Klasse: helloworld.entity.Greeting" href="#neue-klasse-helloworldentitygreeting">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Im Namespace helloworld legen wir eine neue Klasse an: entity.Greeting, in der wir unsere Business Logik / Daten für eine Begrüßung hinterlegen:</p>
<pre tabindex="0"><code>package helloworld.entity;<br></br><br></br>public class Greeting {<br></br> private String greeting;<br></br><br></br> public Greeting() {<br></br> greeting = "Hallo Welt!";<br></br> }<br></br><br></br> public Greeting(final String name) {<br></br> greetName(name);<br></br> }<br></br><br></br> public String getGreeting() { return greeting; }<br></br><br></br> public void greetName(final String name) {<br></br> if (name == null || name.isEmpty()) {<br></br> greeting = "Hallo Welt!";<br></br> } else {<br></br> greeting = "Hallo " + name + "!";<br></br> }<br></br> }<br></br>}
</code></pre><p>Dies ist eine einfache Klasse mit Daten und Business Logik, ganz ohne irgend welche JavaFX Spezialitäten wie StringProperties und Co. Die Klasse wirkt von Design etwas gekünstelt, aber wir nehmen dies an dieser Stelle einfach so hin.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h4 id="umbenennen-von-dateien">
Umbenennen von Dateien
</h4>
<a data-clipboard-text="https://blog.kneitzel.de/2020/06/29/javafx-mvvm/#umbenennen-von-dateien" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Umbenennen von Dateien" href="#umbenennen-von-dateien">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Nun wollen wir einige Dateien umbenennen:</p>
<p>a) View</p>
<p>Zu der View gehören ab jetzt das fxml File und das bisherige Controller File. Daher benennen wir diese um in HelloWorldView(.java|.fxml)</p>
<p>b) ViewModel</p>
<p>Das bisherige Model wird zum ViewModel, daher benennen wir die Datei um in HelloWorldViewModel.java</p>
<p>Das Umbenennen machen wir mit dem Refactoring der IDE, damit es immer gleich an allen Stellen geändert ist.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h4 id="anpassungen-der-view">
Anpassungen der View
</h4>
<a data-clipboard-text="https://blog.kneitzel.de/2020/06/29/javafx-mvvm/#anpassungen-der-view" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Anpassungen der View" href="#anpassungen-der-view">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Als erstes passen wir die HelloWorldView.fxml an:</p>
<ul>
<li>Wir löschen die Referenz auf JavaScript <?language javascript?></li>
<li>Das Label mit dem Greeting bekommt ein fx:id=“greetingLabel“ und das Binding für text wird gelöscht (text=“${controller.model.greeting}“)</li>
<li>Das fx:script wird komplett entfernt.</li>
</ul>
<p>Dann passen wir die HelloWorldView.java an:</p>
<pre tabindex="0"><code>package helloworld;<br></br><br></br>import de.saxsys.mvvmfx.FxmlView;<br></br>import de.saxsys.mvvmfx.InjectViewModel;<br></br>import javafx.event.ActionEvent;<br></br>import javafx.fxml.FXML;<br></br>import javafx.fxml.Initializable;<br></br>import javafx.scene.control.Label;<br></br>import javafx.scene.control.TextField;<br></br><br></br>import java.net.URL;<br></br>import java.util.ResourceBundle;<br></br><br></br>public class HelloWorldView implements FxmlView<HelloWorldViewModel>, Initializable {<br></br><br></br> /**<br></br> * Model with our data.<br></br> */<br></br> @InjectViewModel<br></br> private HelloWorldViewModel model;<br></br><br></br><br></br> /**<br></br> * TextField for name.<br></br> */<br></br> @FXML private TextField nameTextField;<br></br><br></br> /**<br></br> * Label for greeting<br></br> */<br></br> @FXML private Label greetingLabel;<br></br><br></br> /**<br></br> * Close application.<br></br> * @param e ActionEvent (unused).<br></br> */<br></br> public void closeApplicationAction(final ActionEvent e) {<br></br> model.closeApplication();<br></br> }<br></br><br></br> /**<br></br> * Updates Greeting in model.<br></br> * @param e ActionEvent (unused).<br></br> */<br></br> public void updateGreeting(final ActionEvent e) { model.updateGreeting();}<br></br><br></br> @Override<br></br> public void initialize(URL url, ResourceBundle resourceBundle) {<br></br> nameTextField.textProperty().bindBidirectional(model.nameProperty);<br></br> greetingLabel.textProperty().bind(model.greetingProperty);<br></br> }<br></br>}
</code></pre><p>Die folgenden wichtigen Änderungen sind sichtbar:</p>
<ul>
<li>Es wird nun FxmlView<HelloWorldViewModel>, Initializable implementiert.</li>
<li>Das Model wird nicht mehr selbst erzeugt sondern kommt per Injection.</li>
<li>Die Controls sind nun in der View bekannt (greetingLabel und nameTextField).</li>
<li>Die Business-Logik (Beenden der Applikation) ist in das ViewModel gewandert.</li>
<li>Das Binding ist nun in der initialize Methode.</li>
</ul>
<p>Die ViewModel Klasse wird auch angepasst:</p>
<pre tabindex="0"><code>package helloworld;<br></br><br></br>import de.saxsys.mvvmfx.ViewModel;<br></br>import helloworld.entity.Greeting;<br></br>import javafx.beans.property.SimpleStringProperty;<br></br>import javafx.beans.property.StringProperty;<br></br><br></br>/**<br></br> * Our Model for Hello World.<br></br> */<br></br>public class HelloWorldViewModel implements ViewModel {<br></br><br></br> /**<br></br> * Our Model to use.<br></br> */<br></br> private Greeting greeting;<br></br><br></br> /**<br></br> * Greeting to show.<br></br> */<br></br> public StringProperty greetingProperty = new SimpleStringProperty();<br></br> public StringProperty nameProperty = new SimpleStringProperty("Bitte Namen eingeben");<br></br><br></br> public HelloWorldViewModel() {<br></br> greeting = new Greeting("Welt");<br></br> updateViewModel();<br></br> }<br></br><br></br> /**<br></br> * Updates the greeting to use the name given.<br></br> */<br></br> public void updateGreeting() {<br></br> if (nameProperty.get().length() > 0) {<br></br> greeting.greetName(nameProperty.get());<br></br> nameProperty.setValue("Bitte Namen eingeben");<br></br> } else {<br></br> greeting.greetName("Welt");<br></br> }<br></br><br></br> updateViewModel();<br></br> }<br></br><br></br> /**<br></br> * Updates the ViewModel when Model was changed.<br></br> */<br></br> protected void updateViewModel() {<br></br> greetingProperty.setValue(greeting.getGreeting());<br></br> }<br></br><br></br> /**<br></br> * Close application.<br></br> */<br></br> public void closeApplication() {<br></br> System.exit(0);<br></br> }<br></br>}
</code></pre><p>Die wichtigen Änderungen sind nun:</p>
<ul>
<li>die Klasse implementiert ViewModel</li>
<li>closeApplication als Business Logik ist dazu gekommen.</li>
<li>Die Greeting Entity wird verwendet. Wir haben jedoch unseren eigenen Code geschrieben, um Änderungen an den Properties auszulesen / zu setzen.</li>
</ul>
<p>Unsere Applikation muss auch geändert werden:</p>
<pre tabindex="0"><code>package helloworld;<br></br><br></br>import de.saxsys.mvvmfx.FluentViewLoader;<br></br>import de.saxsys.mvvmfx.ViewTuple;<br></br>import javafx.application.Application;<br></br>import javafx.fxml.FXMLLoader;<br></br>import javafx.scene.Parent;<br></br>import javafx.scene.Scene;<br></br>import javafx.stage.Stage;<br></br><br></br>import java.io.IOException;<br></br><br></br>public class HelloWorld extends Application {<br></br><br></br> public static void main(final String[] args) {<br></br> launch(args);<br></br> }<br></br><br></br> @Override<br></br> public void start(final Stage primaryStage) throws IOException {<br></br> primaryStage.setTitle("Hello World Application");<br></br> ViewTuple<HelloWorldView, HelloWorldViewModel> viewTuple = FluentViewLoader.fxmlView(HelloWorldView.class).load();<br></br> Parent root = viewTuple.getView();<br></br> primaryStage.setScene(new Scene(root));<br></br> primaryStage.show();<br></br> }<br></br><br></br>}
</code></pre><p>Der Aufruf einer MVVM Applikation sieht nun leicht verändert aus. So müssen wir ein ViewTupel erzeugen und nutzen dazu einen neuen, speziellen FluentViewLoader.</p>
<p>Damit wäre die Applikation erst einmal umgestellt auf das MVVM Pattern mit Hilfe der mvvmFX Library.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="links">
Links
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/06/29/javafx-mvvm/#links" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Links" href="#links">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<ul>
<li>mvvmFX Projekt: <a
class="gblog-markdown__link"
href="https://github.com/sialcasa/mvvmFX"
>https://github.com/sialcasa/mvvmFX</a></li>
<li>mvvmFX Wiki: <a
class="gblog-markdown__link"
href="https://github.com/sialcasa/mvvmFX/wiki"
>https://github.com/sialcasa/mvvmFX/wiki</a></li>
<li>Repository mit Code für diese JavaFX Blog Serie: <a
class="gblog-markdown__link"
href="https://github.com/kneitzel/blog-javafx-series"
>https://github.com/kneitzel/blog-javafx-series</a></li>
</ul>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="edit">
Edit
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/06/29/javafx-mvvm/#edit" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Edit" href="#edit">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<ul>
<li>2020-07-03 Wechsel zu einem Repository für die ganze Serie.</li>
</ul>
JavaFX: Model / View / Controllerhttps://blog.kneitzel.de/2020/06/26/javafx-model-view-controller/2020-06-26T14:48:13+00:002023-01-16T20:14:20+01:00
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="javafx-serie">
JavaFX Serie
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/06/26/javafx-model-view-controller/#javafx-serie" class="gblog-post__anchor clip flex align-center" aria-label="Anchor JavaFX Serie" href="#javafx-serie">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<ul>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/29/javafx-uebersicht-planung/"
>JavaFX: Übersicht / Planung</a></li>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/24/javafx-uebersicht/"
>JavaFX: Installation / erste Applikation</a></li>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/26/javafx-scene-builder/"
>JavaFX: Scene Builder</a></li>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/26/javafx-erlaeuterungen-der-applikation/"
>JavaFX: Erläuterung der Applikation</a></li>
<li><strong>JavaFX: Model / View / Controller</strong></li>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/29/javafx-mvvm/"
>JavaFX: MVVM</a></li>
<li>JavaFX: Komplette MVVM Applikation (geplant)</li>
<li>JavaFX: Layouts (geplant)</li>
<li>JavaFX: Formulare einfach erstellen (geplant)</li>
<li>JavaFX: Multi Plattform (geplant)</li>
</ul>
<p>Wir haben bisher den Controller und die View gesehen, konnten Aktionen durchführen, aber wir haben bisher noch nicht mit Daten gearbeitet.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="helloworldmodel">
HelloWorldModel
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/06/26/javafx-model-view-controller/#helloworldmodel" class="gblog-post__anchor clip flex align-center" aria-label="Anchor HelloWorldModel" href="#helloworldmodel">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Die Daten liegen in einem Model vor. Dazu erstellen wir uns nun erst einmal eine eigene Klasse: HelloWorldModel</p>
<pre tabindex="0"><code>package helloworld;<br></br><br></br>/**<br></br> * Our Model for Hello World.<br></br> */<br></br>public class HelloWorldModel {<br></br><br></br>}
</code></pre><p>Nun können wir ein erstes Element hinzu fügen: Unser Greeting. Ein Binding setzt voraus, dass man informiert werden kann, wenn sich Werte ändern. Dazu existieren in JavaFX diverse Property Klassen.</p>
<p>Für String Werte gibt es StringProperty und SimpleStringProperty, welche wir nutzen können.</p>
<p>So erstellen wir uns eine Variable greeting:</p>
<pre tabindex="0"><code>private StringProperty greeting = new SimpleStringProperty();
</code></pre><p>Wenn der Controller Werte lesen können soll, dann wird ein Getter benötigt:</p>
<pre tabindex="0"><code>public String getGreeting() { return greeting.get(); }
</code></pre><p>Für Schreibzugriffe wird der Setter benötigt:</p>
<pre tabindex="0"><code>public void setGreeting(final String greeting) { this.greeting.setValue(greeting); }
</code></pre><p>Und falls die Oberfläche Änderungen mitbekommen soll, so muss das Property selbst bekannt gemacht werden:</p>
<pre tabindex="0"><code>public StringProperty greetingProperty() { return greeting; }
</code></pre><p>Nach dem gleichen Schema können wir nun auch noch den Namen hinzu fügen sowie eine Methode, die das Greeting ändert, wenn der Name geändert wurde:</p>
<pre tabindex="0"><code>package helloworld;<br></br><br></br>import javafx.beans.property.SimpleStringProperty;<br></br>import javafx.beans.property.StringProperty;<br></br><br></br>/**<br></br> * Our Model for Hello World.<br></br> */<br></br>public class HelloWorldModel {<br></br><br></br> private StringProperty name = new SimpleStringProperty();<br></br><br></br> public void setName(final String name) {<br></br> this.name.setValue(name);<br></br> }<br></br><br></br> public String getName() { return name.get(); }<br></br><br></br> public StringProperty nameProperty() { return name; }<br></br><br></br> private StringProperty greeting = new SimpleStringProperty();<br></br><br></br> public void setGreeting(final String greeting) {<br></br> this.greeting.setValue(greeting);<br></br> }<br></br><br></br> public String getGreeting() { return greeting.get(); }<br></br><br></br> public StringProperty greetingProperty() { return greeting; }<br></br><br></br> public HelloWorldModel() {<br></br> setGreeting("Hallo Welt!");<br></br> }<br></br><br></br> public void updateGreeting() {<br></br> if (name.get().length() > 0) {<br></br> greeting.setValue("Hallo " + name.get() + "!");<br></br> name.setValue("Bitte Namen eingeben");<br></br> } else {<br></br> greeting.setValue("Hallo Welt!");<br></br> }<br></br> }<br></br>}
</code></pre><p>Damit hätten wir ein fertiges Model, welches wir nutzen können.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="helloworldcontroller">
HelloWorldController
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/06/26/javafx-model-view-controller/#helloworldcontroller" class="gblog-post__anchor clip flex align-center" aria-label="Anchor HelloWorldController" href="#helloworldcontroller">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Den Controller können wir nun noch entsprechend aufbauen:</p>
<ul>
<li>Wir benötigen eine Instanz vom Model sowie ein Getter, damit das Model gelesen werden kann.</li>
<li>Wir benötigen die Behandlung von 2 Actions: Einmal zum Beenden der Applikation und zum Anderen um das Greeting anpassen zu können.</li>
</ul>
<pre tabindex="0"><code>package helloworld;<br></br><br></br>import javafx.event.ActionEvent;<br></br><br></br>public class HelloWorldController {<br></br><br></br> /**<br></br> * Model with our data.<br></br> */<br></br> private HelloWorldModel model = new HelloWorldModel();<br></br><br></br> /**<br></br> * Gets our model.<br></br> * @return Our model.<br></br> */<br></br> public HelloWorldModel getModel() { return model; }<br></br><br></br> /**<br></br> * Close application.<br></br> * @param e ActionEvent (unused).<br></br> */<br></br> public void closeApplicationAction(final ActionEvent e) {<br></br> System.exit(0);<br></br> }<br></br><br></br> /**<br></br> * Updates Greeting in model.<br></br> * @param e ActionEvent (unused).<br></br> */<br></br> public void updateGreeting(final ActionEvent e) { model.updateGreeting();}<br></br>}
</code></pre><div class="gblog-post__anchorwrap flex align-center">
<h2 id="helloworldfxml">
HelloWorld.fxml
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/06/26/javafx-model-view-controller/#helloworldfxml" class="gblog-post__anchor clip flex align-center" aria-label="Anchor HelloWorld.fxml" href="#helloworldfxml">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Nun fehlt zuletzt nur noch die View.</p>
<p>In der View benötigen wir ein Label für unser Greeting, ein Eingabefeld für den Namen und zwei Buttons: Einmal zum Aktualisieren und zum Anderen um die Applikation zu beenden.</p>
<p>Bei mir sieht dies auf die Schnelle so aus:</p>
<p><img
src="https://blog.kneitzel.de/wp-content/uploads/2020/06/HelloWorld-with-model.png"
alt=""
/></p>
<p><span style="color: #ff0000;"><strong>Achtung:</strong> Bezüglich Bindings unterstützt der SceneBuilder leider nicht, was wir hier benötigen. Daher ist es nach der rein optischen Erstellung dieser Maske leider Zeit, uns vom SceneBuilder wieder zu verabschieden (Für diesen Blog-Beitrag – wir benötigen diesen ab dem nächsten Beitrag wieder).</span> Wir werden später auch weitere Möglichkeiten lernen, wie wir Fenster schnell und sauber ohne GUI Editor erstellen können, die dann auch in der Größe veränderbar sind und gut aussehen. Oder wie wir schnell und einfach Formulare erstellen können.</p>
<p>Somit schließen wir den SceneBuilder und editieren nur noch das Textfile direkt z.B. in IntelliJ.</p>
<p>Als erstes binden wir das Label an unsere greeting Property in unserem Model:</p>
<pre tabindex="0"><code><Label ... text="${controller.model.greeting}" ... >
</code></pre><p>Über die ${} können wir ein Binding erstellen. Wichtig ist, dass der Controller gesetzt ist so dass wir auf das model zugreifen können (Getter muss da sein!) und dann auf die Property greeting zugreifen können (Getter und greetingProperty müssen da sein!).</p>
<p>Die Buttons binden wir an unsere Methoden im Controller:</p>
<pre tabindex="0"><code><Button ... onAction="#closeApplicationAction" text="Beenden" /><br></br><Button ... onAction="#updateGreeting" text="Aktualisiere" />
</code></pre><p>Nun fehlt nur noch das Binding des TextFields. Hier laufen wir in ein kleines Problem, wenn wir benötigen ein Bidirectionales Binding, denn wir wollen den Text ja verändern können. Das ist leider etwas, das derzeit nicht im fxml möglich ist. In Zukunft ist dies vorgesehen über die # statt dem $.</p>
<p>Nun haben wir Code, den wir nicht in den Controller packen wollen, also müssen wir etwas in die Trickkiste greifen:</p>
<p>Wir können Scripts mit in die fxml Datei packen. Dazu müssen wir als erstes im Kopf der Datei die Sprache angeben, die wir verwenden wollen:</p>
<pre tabindex="0"><code><?language javascript?>
</code></pre><p>Nun können wir das TextField definieren ohne jedes Binding aber mit einer fx🆔</p>
<pre tabindex="0"><code><TextField fx:id="nameTextField" ... text="Bitte Namen eingeben." />
</code></pre><p>Nun benötigen wir Code, der ein bidirectional Binding aufbaut. Dazu müssen wir in der Klasse Bindings die Methode bindBidirectional aufrufen und dabei die Property und das Control angeben:</p>
<pre tabindex="0"><code><fx:script><br></br> javafx.beans.binding.Bindings.bindBidirectional(<br></br> controller.model.nameProperty(),<br></br> nameTextField.textProperty()<br></br> );<br></br></fx:script>
</code></pre><p>Mit diesem Trick haben wir nun auch das Binding in beide Richtungen erstellt und es spricht nichts dagegen, die Applikation einmal zu starten und dann einen Namen anzugeben und zu staunen, wie das Greeting sich ändert, wenn man den Knopf drückt und erneut der Text erscheint: „Bitte Name eingeben“.</p>
<p>Der Code des ganzen Projekts findet sich unter <a
class="gblog-markdown__link"
href="https://github.com/kneitzel/blog-javafx-series"
>https://github.com/kneitzel/blog-javafx-series</a> im Verzeichnis „04 helloworld-mvc“</p>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="links">
Links
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/06/26/javafx-model-view-controller/#links" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Links" href="#links">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<ul>
<li>SimpleStringProperty class: <a
class="gblog-markdown__link"
href="https://openjfx.io/javadoc/12/javafx.base/javafx/beans/property/SimpleStringProperty.html"
>https://openjfx.io/javadoc/12/javafx.base/javafx/beans/property/SimpleStringProperty.html</a></li>
<li>StringProperty class: <a
class="gblog-markdown__link"
href="https://openjfx.io/javadoc/12/javafx.base/javafx/beans/property/StringProperty.html"
>https://openjfx.io/javadoc/12/javafx.base/javafx/beans/property/StringProperty.html</a></li>
<li>Repository mit Code für diese JavaFX Blog Serie: <a
class="gblog-markdown__link"
href="https://github.com/kneitzel/blog-javafx-series"
>https://github.com/kneitzel/blog-javafx-series</a></li>
</ul>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="edit">
Edit
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/06/26/javafx-model-view-controller/#edit" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Edit" href="#edit">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<ul>
<li>2020-07-03: Wechsel zu einem Repository für die ganze Serie.</li>
<li>2020-06-29: Den Part bezüglich SceneEditor etwas überarbeitet – wir werden diesen in späteren Blog Beiträgen wieder nutzen (können).</li>
</ul>
JavaFX: Erläuterungen der Applikationhttps://blog.kneitzel.de/2020/06/26/javafx-erlaeuterungen-der-applikation/2020-06-26T13:27:22+00:002023-01-16T20:14:20+01:00
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="javafx-serie">
JavaFX Serie
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/06/26/javafx-erlaeuterungen-der-applikation/#javafx-serie" class="gblog-post__anchor clip flex align-center" aria-label="Anchor JavaFX Serie" href="#javafx-serie">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<ul>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/29/javafx-uebersicht-planung/"
>JavaFX: Übersicht / Planung</a></li>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/24/javafx-uebersicht/"
>JavaFX: Installation / erste Applikation</a></li>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/26/javafx-scene-builder/"
>JavaFX: Scene Builder</a></li>
<li><strong>JavaFX: Erläuterung der Applikation</strong></li>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/26/javafx-model-view-controller/"
>JavaFX: Model / View / Controller</a></li>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/29/javafx-mvvm/"
>JavaFX: MVVM</a></li>
<li>JavaFX: Komplette MVVM Applikation (geplant)</li>
<li>JavaFX: Layouts (geplant)</li>
<li>JavaFX: Formulare einfach erstellen (geplant)</li>
<li>JavaFX: Multi Plattform (geplant)</li>
</ul>
<p>Die Applikation der letzten Blog-Einträge möchte ich jetzt hier einmal im Detail erläutern, da es mir in den ersten Teilen erst einmal um die Erstellung der Oberfläche in fxml gegangen ist.</p>
<p>Das ganze Projekt findet sich auf GitHub unter:<br>
<a
class="gblog-markdown__link"
href="https://github.com/kneitzel/blog-javafx-series"
>https://github.com/kneitzel/blog-javafx-serieshttps://github.com/kneitzel/blog-java-helloworld-fxml</a> im Verzeichnis „02 helloworld-fxml“.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="die-klasse-helloworld">
Die Klasse HelloWorld
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/06/26/javafx-erlaeuterungen-der-applikation/#die-klasse-helloworld" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Die Klasse HelloWorld" href="#die-klasse-helloworld">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Die Klasse HelloWorld enthält unsere JavaFX Applikation.</p>
<pre tabindex="0"><code>package helloworld;<br></br><br></br>import javafx.application.Application;<br></br>import javafx.fxml.FXMLLoader;<br></br>import javafx.scene.Parent;<br></br>import javafx.scene.Scene;<br></br>import javafx.stage.Stage;<br></br><br></br>import java.io.IOException;<br></br><br></br>public class HelloWorld extends Application {<br></br><br></br> public static void main(String[] args) {<br></br> launch(args);<br></br> }<br></br><br></br> @Override<br></br> public void start(Stage primaryStage) throws IOException {<br></br> Parent root = FXMLLoader.load(getClass().getResource("HelloWorld.fxml"));<br></br> Scene scene = new Scene(root);<br></br> primaryStage.setScene(scene);<br></br> primaryStage.show();<br></br> }<br></br><br></br>}
</code></pre><p>Unsere Klasse erbt von <a
class="gblog-markdown__link"
href="https://openjfx.io/javadoc/12/javafx.graphics/javafx/application/Application.html"
>Application</a>, welches die Funktionalität einer JavaFX Applikation bereit stellt und u.a. die Parameter, die mitgegeben werden, für uns auswertet.</p>
<pre tabindex="0"><code>public static void main(String[] args) {<br></br> launch(args);<br></br>}
</code></pre><p>In der Main Methode wird lediglich die in Application bereits vorhandene Methode launch aufgerufen, welche dann u.a. die Parameter auswertet und eine Instanz unserer Klasse erzeugt.</p>
<pre tabindex="0"><code>@Override<br></br>public void start(Stage primaryStage) throws IOException {
</code></pre><p>In unserer Klasse überschreiben wir die start Methode, welche uns als Parameter eine <a
class="gblog-markdown__link"
href="https://openjfx.io/javadoc/12/javafx.graphics/javafx/stage/Stage.html"
>Stage</a> mitgibt. Dies ist der oberste Container unserer JavaFX Struktur und entspricht dem Fenster.</p>
<pre tabindex="0"><code>Parent root = FXMLLoader.load(getClass().getResource("HelloWorld.fxml"));
</code></pre><p>In start lesen wir als erstes unser fxml File ein. Die Datei laden wir über die Methode getResource der Klasse, welche den ClassLoader nutzt um die Resource innerhalb des ClassPath zu finden. Dabei wird relativ zum Verzeichnis des Package gesucht. Da das Package unserer Klasse „helloworld“ ist, wird die Resource in einem Verzeichnis helloworld gesucht.</p>
<p>Der <a
class="gblog-markdown__link"
href="https://openjfx.io/javadoc/12/javafx.fxml/javafx/fxml/FXMLLoader.html"
>FXMLLoader</a> lädt nicht nur die Datei sondern erzeugt auch eine Instanz des Controllers und initialisiert auch alle durch das @FXML Attribut versehende Elemente.</p>
<pre tabindex="0"><code>Scene scene = new Scene(root);
</code></pre><p>Über den geladen Inhalt erzeugen wir eine <a
class="gblog-markdown__link"
href="https://openjfx.io/javadoc/12/javafx.graphics/javafx/scene/Scene.html"
>Scene</a>. Dies entspricht sozusagen dem Inhalt eines Fensters.</p>
<pre tabindex="0"><code>primaryStage.setScene(scene);
</code></pre><p>Wir setzen die erzeugte Scene zum Inhalt des Hauptfensters.</p>
<pre tabindex="0"><code>primaryStage.show();
</code></pre><p>Und zuletzt machen wir das Fenster sichtbar.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="die-klasse-helloworldcontroller">
Die Klasse HelloWorldController
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/06/26/javafx-erlaeuterungen-der-applikation/#die-klasse-helloworldcontroller" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Die Klasse HelloWorldController" href="#die-klasse-helloworldcontroller">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Der Controller ist für alle Aktionen in der View verantwortlich und wird von der View angesprochen. In dem Beispiel habe ich auch die Möglichkeit gezeigt, wie der Controller auf die View zugreifen kann, aber diese Abhängigkeit sollten wir nicht nutzen!<br>
<strong>Wichtig</strong>: Die Instanzen dieser Klasse werden vom FXMLLoader erzeugt. Wir erzeugen keine eigenen Instanzen!</p>
<pre tabindex="0"><code>package helloworld;<br></br><br></br>import javafx.event.ActionEvent;<br></br>import javafx.fxml.FXML;<br></br>import javafx.scene.control.Alert;<br></br>import javafx.scene.control.Button;<br></br>import javafx.scene.control.ButtonType;<br></br><br></br>public class HelloWorldController {<br></br><br></br> @FXML private Button greetMeButton;<br></br><br></br> public void closeApplicationAction(ActionEvent e) {<br></br> System.exit(0);<br></br> }<br></br><br></br> public void handleGreetMeButton(ActionEvent e) {<br></br> Alert alert = new Alert(Alert.AlertType.INFORMATION, "Hallo Anwender!", ButtonType.OK);<br></br> alert.showAndWait();<br></br> }<br></br><br></br> @FXML<br></br> public void initialize() {<br></br> greetMeButton.setOnAction(this::handleGreetMeButton);<br></br> }<br></br>}
</code></pre><p>Die Klasse unseres Controllers muss von keiner anderen Klasse abgeleitet werden.</p>
<pre tabindex="0"><code>@FXML private Button greetMeButton;
</code></pre><p>In dem Controller können wir uns die Elemente, welche im fxml definiert wurden, vom FXMLLoader geben lassen. Damit der FXMLLoader dies macht, muss die Annotation @FXML gesetzt sein.<br>
Desweiteren muss der Typ stimmen (hier Button) und der Name der Variablen muss mit der fx:id überein stimmen (hier fx:id=“greetMeButton“).</p>
<p><strong>Wichtig</strong>: Dies erzeugt eine Abhängigkeit vom Controller zu der View. Diese Abhängigkeit sollte vermieden werden so dass nur eine Abhängigkeit von der View zum Controller (und später auch zum Model) existiert. Dies findet sich nur in diesem Beispiel, da dies etwas ist, das sehr viele Entwickler so machen.</p>
<pre tabindex="0"><code>public void closeApplicationAction(ActionEvent e) {
</code></pre><pre tabindex="0"><code>public void handleGreetMeButton(ActionEvent e) {
</code></pre><p>Wir definieren Methoden, die ein ActionEvent als Parameter nehmen. Diese Methoden können Actions behandeln und werden in der fxml Datei referenziert.</p>
<p>Natürlich können wir diese Methoden auch aus unserem Code heraus nutzen.</p>
<pre tabindex="0"><code>@FXML<br></br>public void initialize() {
</code></pre><p>Es gibt für einen Controller gewisse Events, die wir nutzen können. Ein Event ist das initialize Event. Das @FXML Annotation sorgt dafür, dass der FXMLLoader diese Methode auch ansteuert.</p>
<p>Dies ist wichtig, denn die Variablen, die vom FXMLLoader gesetzt werden (mit @FXML Annotation) werden erst nach dem Konstruktor gesetzt. Somit stehen diese noch nicht im Konstruktor zur Verfügung. Initialisierungsarbeiten, die auch die Controls benötigen, müssen somit innerhalb der initialize() Methode gemacht werden.</p>
<pre tabindex="0"><code>greetMeButton.setOnAction(this::handleGreetMeButton);
</code></pre><p>Hier setzen wir im Code, was für eine Action bei dem Button ausgeführt werden soll. Dies hätte auch über das fxml gesetzt werden können (so wie beim anderen Button).</p>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="die-helloworldfxml-ressource">
Die HelloWorld.fxml Ressource
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/06/26/javafx-erlaeuterungen-der-applikation/#die-helloworldfxml-ressource" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Die HelloWorld.fxml Ressource" href="#die-helloworldfxml-ressource">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>In der fxml Datei haben wir unsere Oberfläche beschrieben.</p>
<pre tabindex="0"><code><?xml version="1.0" encoding="UTF-8"?><br></br><br></br><?import javafx.scene.control.Button?><br></br><?import javafx.scene.control.Label?><br></br><?import javafx.scene.layout.Pane?><br></br><?import javafx.scene.text.Font?><br></br><br></br><Pane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="145.0" prefWidth="237.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="helloworld.HelloWorldController"><br></br> <children><br></br> <Label alignment="CENTER" contentDisplay="CENTER" layoutX="-1.0" layoutY="14.0" prefHeight="53.0" prefWidth="237.0" text="Hallo Welt" textOverrun="CLIP" underline="true"><br></br> <font><br></br> <Font size="24.0" /><br></br> </font><br></br> </Label><br></br> <Button fx:id="greetMeButton" layoutX="30.0" layoutY="78.0" mnemonicParsing="false" text="Grüße Mich" /><br></br> <Button layoutX="137.0" layoutY="78.0" mnemonicParsing="false" onAction="#closeApplicationAction" text="Beenden" /><br></br> </children><br></br></Pane>
</code></pre><p>Wichtige Elemente sind dabei:</p>
<pre tabindex="0"><code><Pane ... fx:controller="helloworld.HelloWorldController">
</code></pre><p>Wir definieren in der Pane, welche Klasse als Controller dienen soll. Eine Instanz dieser Klasse wird vom FXMLLoader erzeugt.</p>
<pre tabindex="0"><code><Button fx:id="greetMeButton" ... />
</code></pre><p>Wir geben dem Button eine feste Id, um dann über den FXMLLoader eine Referenz zu dem Control bekommen zu können.</p>
<p><strong>Wichtig</strong>: Wie schon mehrfach gesagt: Dieses Vorgehen ist suboptimal und von mir nicht empfohlen.</p>
<pre tabindex="0"><code><Button ... onAction="#closeApplicationAction" ... />
</code></pre><p>Wir definieren in der fxml Datei, welche Methode im Controller bei der Action ausgeführt werden soll.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h1 id="links">
Links
</h1>
<a data-clipboard-text="https://blog.kneitzel.de/2020/06/26/javafx-erlaeuterungen-der-applikation/#links" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Links" href="#links">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<ul>
<li>Application class: <a
class="gblog-markdown__link"
href="https://openjfx.io/javadoc/12/javafx.graphics/javafx/application/Application.html"
>https://openjfx.io/javadoc/12/javafx.graphics/javafx/application/Application.html</a></li>
<li>FXMLLoader class: <a
class="gblog-markdown__link"
href="https://openjfx.io/javadoc/12/javafx.fxml/javafx/fxml/FXMLLoader.html"
>https://openjfx.io/javadoc/12/javafx.fxml/javafx/fxml/FXMLLoader.html</a></li>
<li>Stage class: <a
class="gblog-markdown__link"
href="https://openjfx.io/javadoc/12/javafx.graphics/javafx/stage/Stage.html"
>https://openjfx.io/javadoc/12/javafx.graphics/javafx/stage/Stage.html</a></li>
<li>Scene class: <a
class="gblog-markdown__link"
href="https://openjfx.io/javadoc/12/javafx.graphics/javafx/scene/Scene.html"
>https://openjfx.io/javadoc/12/javafx.graphics/javafx/scene/Scene.html</a></li>
<li>Repository mit Code für diese JavaFX Blog Serie: <a
class="gblog-markdown__link"
href="https://github.com/kneitzel/blog-javafx-series"
>https://github.com/kneitzel/blog-javafx-series</a></li>
</ul>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="edit">
Edit
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/06/26/javafx-erlaeuterungen-der-applikation/#edit" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Edit" href="#edit">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<ul>
<li>2020-07-03 Wechsel zu einem Repository für die ganze Serie.</li>
</ul>
JavaFX: Scene Builderhttps://blog.kneitzel.de/2020/06/26/javafx-scene-builder/2020-06-26T08:11:07+00:002023-01-16T20:14:20+01:00
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="javafx-serie">
JavaFX Serie
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/06/26/javafx-scene-builder/#javafx-serie" class="gblog-post__anchor clip flex align-center" aria-label="Anchor JavaFX Serie" href="#javafx-serie">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<ul>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/29/javafx-uebersicht-planung/"
>JavaFX: Übersicht / Planung</a></li>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/24/javafx-uebersicht/"
>JavaFX: Installation / erste Applikation</a></li>
<li><strong>JavaFX: Scene Builder</strong></li>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/26/javafx-erlaeuterungen-der-applikation/"
>JavaFX: Erläuterung der Applikation</a></li>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/26/javafx-model-view-controller/"
>JavaFX: Model / View / Controller</a></li>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/29/javafx-mvvm/"
>JavaFX: MVVM</a></li>
<li>JavaFX: Komplette MVVM Applikation (geplant)</li>
<li>JavaFX: Layouts (geplant)</li>
<li>JavaFX: Formulare einfach erstellen (geplant)</li>
<li>JavaFX: Multi Plattform (geplant)</li>
</ul>
<p>Als einen wichtigen Unterschied zu Swing habe ich angegeben, dass die Oberflächen deklarativ erstellt werden können. In dem HelloWorld fand sich aber dann davon aber nichts und das einfache Fenster habe ich im Programmcode erstellt.</p>
<p>Dies ändert sich nun und dazu besorgen wir uns noch ein zusätzliches Tool: Den <a
class="gblog-markdown__link"
href="https://gluonhq.com/products/scene-builder/"
>Scene Builder</a> von Gluon. Nach der Installation können wir den Scene Builder auch in IntelliJ integrieren, indem wir in den Settings unter Language & FRameworks -> JavaFX den Pfad zum Scene Builder eintragen.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="eine-erste-oberfläche-erstellen">
Eine erste Oberfläche erstellen
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/06/26/javafx-scene-builder/#eine-erste-oberfläche-erstellen" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Eine erste Oberfläche erstellen" href="#eine-erste-oberfl%c3%a4che-erstellen">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Wir erstellen unsere erste Oberfläche, in dem wir einfach in Screen Builder ein neues, leeres Dokument erstellen.</p>
<p>Als erstes ziehen wir aus den Containers ein Pane in unser Dokument. Dieses Element wird alle weiteren Elemente beherbergen.</p>
<p>Als nächstes Ziehen wir einen Label aus den Controls auf unser Pane. Damit können wir jetzt etwas spielen:</p>
<ul>
<li>Wir klicken abwechselnd auf Label oder das Pane: Das angeklickte Element wird markiert und es werden die Properties angezeigt.</li>
<li>Wir verschieben die Elemente, ändern am Rand die Größe….</li>
<li>Wir ändern Properties. Beim Label können wir den Text ändern und wie der Text dargestellt wird.</li>
</ul>
<p>Das Label platzieren wir oben im Pane, und verbreitern es, dass es über die ganze Breite geht. Der Text soll „Hallo Welt“ sein, mit 24px Größe und unterstrichen. Und der „Node“ des Label soll ein Alignment CENTER haben.</p>
<p>Unterhalb des Label können wir nun noch zwei Buttons hin ziehen. Diese bekommen den Text „Grüße Mich“ und „Beenden“.</p>
<p>Wir können die alles nun mit der Maus etwas verschieben und die Größe ändern, bis es uns gefällt.</p>
<p>Mein Ergebnis:</p>
<p><img
src="https://blog.kneitzel.de/wp-content/uploads/2020/06/HelloWorld-fxml-Aussehen.png"
alt=""
/></p>
<p>Unsere erstellte Oberfläche speichern wir nun als HelloWorld.fxml im Verzeichnis src/main/resources/helloworld/ unseres Testprojekts. Das helloworld Verzeichnis bitte so anlegen.</p>
<p><strong>Hinweis:</strong> Hier wird die Trennung deutlich: Unser Java-Code liegt unter src/main/java, aber alle Resourcen wie Bilder oder so eine Scene von JavaFX landen in src/main/resources.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="inhalt-der-datei">
Inhalt der Datei
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/06/26/javafx-scene-builder/#inhalt-der-datei" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Inhalt der Datei" href="#inhalt-der-datei">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Die erstellte Datei können wir uns mit einem Texteditor ansehen. Es handelt sich um eine XML Datei und wir können die Struktur, die wir aufgebaut haben sowie die Einstellungen wieder finden.</p>
<pre tabindex="0"><code><?xml version="1.0" encoding="UTF-8"?><br></br><br></br><?import javafx.scene.control.Button?><br></br><?import javafx.scene.control.Label?><br></br><?import javafx.scene.layout.Pane?><br></br><?import javafx.scene.text.Font?><br></br><br></br><br></br><Pane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="145.0" prefWidth="237.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1"><br></br> <children><br></br> <Label alignment="CENTER" contentDisplay="CENTER" layoutX="-1.0" layoutY="14.0" prefHeight="53.0" prefWidth="237.0" text="Hallo Welt" textOverrun="CLIP" underline="true"><br></br> <font><br></br> <Font size="24.0" /><br></br> </font><br></br> </Label><br></br> <Button layoutX="30.0" layoutY="78.0" mnemonicParsing="false" text="Grüße Mich" /><br></br> <Button layoutX="137.0" layoutY="78.0" mnemonicParsing="false" text="Beenden" /><br></br> </children><br></br></Pane>
</code></pre><p>Damit aber diese Scene von unserem Programm verwendet werden kann, müssen wir natürlich noch unser Programm anpassen:</p>
<pre tabindex="0"><code>package helloworld;<br></br><br></br>import javafx.application.Application;<br></br>import javafx.fxml.FXMLLoader;<br></br>import javafx.scene.Parent;<br></br>import javafx.scene.Scene;<br></br>import javafx.stage.Stage;<br></br><br></br>import java.io.IOException;<br></br><br></br>public class HelloWorld extends Application {<br></br><br></br> public static void main(String[] args) {<br></br> launch(args);<br></br> }<br></br><br></br> @Override<br></br> public void start(Stage primaryStage) throws IOException {<br></br> Parent root = FXMLLoader.load(getClass().getResource("HelloWorld.fxml"));<br></br> Scene scene = new Scene(root);<br></br> primaryStage.setScene(scene);<br></br> primaryStage.show();<br></br><br></br> }<br></br>}
</code></pre><p>Damit haben wir ein erstes kleines Programm. Die Befehle werde ich später im Detail erläutern. Jetzt nur als groben Überblick: Es wird die fxml Datei geladen und dann daraus ein Applikationsfenster angepasst. Wenn wir es starten, sollte ein Fenster mit dem erstellten Inhalt angezeigt werden, aber noch passiert da nichts, wenn wir einen Button drücken.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h4 id="aktionen-in-scenebuilder-definieren">
Aktionen in SceneBuilder definieren
</h4>
<a data-clipboard-text="https://blog.kneitzel.de/2020/06/26/javafx-scene-builder/#aktionen-in-scenebuilder-definieren" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Aktionen in SceneBuilder definieren" href="#aktionen-in-scenebuilder-definieren">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Eine Möglichkeit ist, dass wir Aktionen in der fxml Datei hinterlegen.</p>
<p>Dazu erstellen wir im ersten Schritt eine neue Klasse HelloWorldController mit einer Methode, die das Programm beenden soll, wenn eine „Action“ statt findet:</p>
<pre tabindex="0"><code>package helloworld;<br></br><br></br>import javafx.event.ActionEvent;<br></br><br></br>public class HelloWorldController {<br></br><br></br> public void closeApplicationAction(ActionEvent e) {<br></br> System.exit(0);<br></br> }<br></br>}
</code></pre><p>IntelliJ zeigt den Klassen- und Methodennamen grau an, um uns zu zeigen: Dies wird bisher nicht benutzt.</p>
<p>Als nächstes müssen wir im SceneBuilder die Aktion hinterlegen. Dazu sind zwei Schritte notwendig:</p>
<p>a) Wir hinterlegen in der Scene, welcher Controller zuständig ist. Dazu müssen wir im linken Bereich unten auf Controller klicken um dann die Controller class auszuwählen. Dort geben wir helloworld.HelloWorldController ein.</p>
<p>b) Im nächsten Schritt wählen wir den Knopf und klicken im rechten Bereich auf Code : Button. Dort finden wir unter Main ein Feld On Action. Dort geben wir closeApplicationAction ein.</p>
<p>Wir können die Scene nun speichern und zum IntelliJ zurück wechseln. IntelliJ sollte diese Änderung mitbekommen haben und nun die Klasse und Methode nicht mehr grau darstellen.</p>
<p>Nun einfach einmal die Applikation starten und prüfen, ob wir über unseren Beenden Knopf die Applikation beenden können.</p>
<p>Wir haben hier etwas aufgebaut, was eine sehr schöne Trennung aufzeigt:</p>
<ul>
<li>Under Controller bietet eine Action an. Ob und wie diese aufgerufen wird, ist erst einmal egal. Das kein Button sein aber auch irgend ein anderes Control, dass ein ActionEvent auslösen kann.</li>
<li>Die UI lässt sich jederzeit anpassen. Egal, was da benutzt wird: Die Methoden des Controllers stehen zur Verfügung</li>
</ul>
<p>Wir haben hier also eine sehr gute Trennung zwischen Controller und View.</p>
<p>Eine so strickte Trennung sollte wenn möglich immer eingehalten werden. Bei dem „Güße Mich“ Button möchte ich aber auch einmal kurz aufzeigen, was man oft bei anderen Entwicklern an Code sieht.</p>
<p>In dem SceneBuilder gehen wir auf den „Grüße Mich“ Knopf und tragen unter Code : Button eine fx:id ein: greetMeButton. Damit vergeben wir eine klare ID an diesen Button, so dass wir einfach auf diesen zugreifen können.</p>
<p>In unserem Controller fügen wir nun ein:</p>
<p>a) Die Methode, die uns grüßen soll:</p>
<pre tabindex="0"><code>public void handleGreetMeButton(ActionEvent e) {<br></br> Alert alert = new Alert(Alert.AlertType.INFORMATION, "Hallo Anwender!", ButtonType.OK);<br></br> alert.showAndWait();<br></br>}
</code></pre><p>b) Eine Instanzvariable hinzu mit Annotation @FXML:</p>
<pre tabindex="0"><code>@FXML private Button greetMeButton;
</code></pre><p>c) Eine Initialisierungs-Methode</p>
<pre tabindex="0"><code>@FXML<br></br>public void initialize() {<br></br> greetMeButton.setOnAction(this::handleGreetMeButton);<br></br>}
</code></pre><p>Wenn wir dies ausführen, dann sehen wir, dass alles funktioniert. Aber jetzt haben wir eine klare Abhängigkeit von dem Controller hin zur View. Es muss ein Button mit fx:id greetMeButton geben. Wenn jemand anderes es Oberfläche baut oder anpasst, dann hat er hier eine klare Einschränkung.</p>
<p>Und im Controller sind wir nicht mehr auf Funktionen konzentriert sondern auf konkrete Bedienelemente. Der Entwickler sollte sich aber in erster Linie um Funktionen auf Basis des Modells (Dazu kommen wir später in der Serie) kümmern.</p>
<p>Evtl. ein kleiner Vergleich: Ein Motor im Auto hat eine Steuerung „Gas“. Da kann man einen Wert setzen. Woher dieser Wert kommt (Gaspedal, Gashebel, Computer, Joystick, ….) ist egal.</p>
<p>Daher dieser Abschnitt nur als kurzer Hinweis. Wir lassen dies jetzt auch noch so, denn im nächsten Beitrag werde ich die Applikation im Detail erläutern.</p>
<p>Die Sourcen dieses Projektes finden sich unter <a
class="gblog-markdown__link"
href="https://github.com/kneitzel/blog-javafx-series"
>https://github.com/kneitzel/blog-javafx-series</a> in „02 helloworld-fxml“</p>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="links">
Links
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/06/26/javafx-scene-builder/#links" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Links" href="#links">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<ul>
<li>Scene Builder von Gluon: <a
class="gblog-markdown__link"
href="https://gluonhq.com/products/scene-builder/"
>https://gluonhq.com/products/scene-builder/</a></li>
<li>SceneBuilder in IntelliJ einbinden: <a
class="gblog-markdown__link"
href="https://www.jetbrains.com/help/idea/opening-fxml-files-in-javafx-scene-builder.html"
>https://www.jetbrains.com/help/idea/opening-fxml-files-in-javafx-scene-builder.html</a></li>
<li>Repository mit Code für diese JavaFX Blog Serie: <a
class="gblog-markdown__link"
href="https://github.com/kneitzel/blog-javafx-series"
>https://github.com/kneitzel/blog-javafx-series</a></li>
</ul>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="edit">
Edit
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/06/26/javafx-scene-builder/#edit" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Edit" href="#edit">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<ul>
<li>2020-07-03 Wechsel zu einem Repository für die ganze Serie.</li>
</ul>
WSL: Services automatisch startenhttps://blog.kneitzel.de/2020/06/19/wsl-services-automatisch-starten/2020-06-19T17:31:40+00:002023-01-16T20:14:20+01:00
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="beiträge-der-wsl-serie">
Beiträge der WSL Serie
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/06/19/wsl-services-automatisch-starten/#beiträge-der-wsl-serie" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Beiträge der WSL Serie" href="#beitr%c3%a4ge-der-wsl-serie">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<ul>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/16/windows-subsystem-fuer-linux-wsl/"
>Windows Subsystem für Linux (WSL)</a></li>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/16/wsl-interaktion-zwischen-den-systemen-i/"
>WSL: Interaktion zwischen den Systemen (I)</a></li>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/16/wsl-interaktion-zwischen-den-systemen-ii/"
>WSL: Interaktion zwischen den Systemen (II)</a></li>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/16/wsl-c-entwicklung-mit-clion/"
>WSL: C++ Entwicklung mit CLion</a></li>
<li><strong>WSL: Services automatisch starten</strong></li>
</ul>
<p>Wir haben im letzten Blog ssh installiert und den Service gestartet.</p>
<p>Wenn wir aber Windows neu gestartet oder WSL mit „wsl -t debian“ beendet haben, dann mussten wir feststellen, dass der ssh Service nicht mehr lief.</p>
<p>WSL startet kein Linux System, wie wir es von vollwertigen Installationen gewohnt sind. Dies kann man auch gut erkennen, wenn wir einmal systemctl aufrufen:</p>
<pre tabindex="0"><code>konrad@ZBook15G2:~$ systemctl<br></br>System has not been booted with systemd as init system (PID 1). Can't operate.<br></br>Failed to connect to bus: Host is down<br></br>konrad@ZBook15G2:~$
</code></pre><p>Dies ist sehr ärgerlich, denn davon sind alle Dienste betroffen. Aber wir wollen ggf. ja cron Einträge machen oder oder per ssh zugreifen. Daher müssen wir dafür sorgen, dass die Dienste, die wir brauchen, gestartet werden.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h3 id="schritt-1-sudo-ohne-passwort-aufrufen">
Schritt 1: sudo ohne Passwort aufrufen
</h3>
<a data-clipboard-text="https://blog.kneitzel.de/2020/06/19/wsl-services-automatisch-starten/#schritt-1-sudo-ohne-passwort-aufrufen" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Schritt 1: sudo ohne Passwort aufrufen" href="#schritt-1-sudo-ohne-passwort-aufrufen">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Damit wir generell services manipulieren können, ohne dass ein Passwort eingegeben werden muss, tragen wir dies bei sudoers ein:</p>
<pre tabindex="0"><code>echo "%sudo ALL=(ALL) NOPASSWD: /usr/sbin/service *" > /etc/sudoers.d/service
</code></pre><p>Danach können wir nun den service Befehl mittels sudo aufrufen ohne dass wir unser Passwort eingeben müssen.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h3 id="schritt-2-prüfen-ob-ein-service-läuft">
Schritt 2: Prüfen, ob ein Service läuft
</h3>
<a data-clipboard-text="https://blog.kneitzel.de/2020/06/19/wsl-services-automatisch-starten/#schritt-2-prüfen-ob-ein-service-läuft" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Schritt 2: Prüfen, ob ein Service läuft" href="#schritt-2-pr%c3%bcfen-ob-ein-service-l%c3%a4uft">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Nun können wir prüfen, ob ein Service läuft. Den Status von ssh können wir mittels</p>
<pre tabindex="0"><code>service ssh status
</code></pre><p>anzeigen lassen.</p>
<p>In einem Script können wir den Status auswerten und bei Bedarf den Service neu starten:</p>
<pre tabindex="0"><code>[ "`service ssh status | sed 's/.*not running.*/nok/'`" == "nok" ] && sudo service ssh start
</code></pre><p>Damit wird in der Ausgabe nach „not running“ gesucht um aus dem ganzen Text ein „nok“ zu machen. So das erfolgreich war, wird der Service neu gestartet.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h3 id="schritt-3-script-das-alle-services-startet-die-wir-brauchen">
Schritt 3: Script, das alle Services startet, die wir brauchen
</h3>
<a data-clipboard-text="https://blog.kneitzel.de/2020/06/19/wsl-services-automatisch-starten/#schritt-3-script-das-alle-services-startet-die-wir-brauchen" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Schritt 3: Script, das alle Services startet, die wir brauchen" href="#schritt-3-script-das-alle-services-startet-die-wir-brauchen">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>In dem Homelaufwerk von meinem User habe ich ein Script services.sh erstellt:</p>
<pre tabindex="0"><code>#!/bin/bash<br></br># Start Services if not running<br></br><br></br>[ "`service ssh status | sed 's/.*not running.*/nok/'`" == "nok" ] && sudo service ssh start<br></br>[ "`service dbus status | sed 's/.*not running.*/nok/'`" == "nok" ] && sudo service dbus start<br></br>[ "`service cron status | sed 's/.*not running.*/nok/'`" == "nok" ] && sudo service cron start
</code></pre><div class="gblog-post__anchorwrap flex align-center">
<h3 id="schritt-4-automatisches-starten-des-scripts">
Schritt 4: Automatisches Starten des Scripts
</h3>
<a data-clipboard-text="https://blog.kneitzel.de/2020/06/19/wsl-services-automatisch-starten/#schritt-4-automatisches-starten-des-scripts" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Schritt 4: Automatisches Starten des Scripts" href="#schritt-4-automatisches-starten-des-scripts">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Damit sicher gestellt ist, dass die Services laufen, wenn ich mit dem System arbeite, habe ich:</p>
<div class="gblog-post__anchorwrap flex align-center">
<h5 id="autostart">
Autostart
</h5>
<a data-clipboard-text="https://blog.kneitzel.de/2020/06/19/wsl-services-automatisch-starten/#autostart" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Autostart" href="#autostart">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Im Autostart ein Shortcut erstellt, welcher aufruf:</p>
<pre tabindex="0"><code>wsl.exe bash ~/services.sh
</code></pre><p>Dadurch werden alle Services in meinem Windows Subsystem für Linux gestartet, wenn ich mich anmelde.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h5 id="bashrc">
.bashrc
</h5>
<a data-clipboard-text="https://blog.kneitzel.de/2020/06/19/wsl-services-automatisch-starten/#bashrc" class="gblog-post__anchor clip flex align-center" aria-label="Anchor .bashrc" href="#bashrc">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>In meiner .bashrc habe ich den Aufruf ~/services.sh aufgenommen. Somit wird bei jedem Öffnen einer Shell noch einmal geprüft, ob die Services alle laufen.</p>
WSL: C++ Entwicklung mit CLionhttps://blog.kneitzel.de/2020/06/16/wsl-c-entwicklung-mit-clion/2020-06-16T19:23:12+00:002023-01-19T22:51:40+01:00
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="beiträge-der-wsl-serie">
Beiträge der WSL Serie
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/06/16/wsl-c-entwicklung-mit-clion/#beiträge-der-wsl-serie" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Beiträge der WSL Serie" href="#beitr%c3%a4ge-der-wsl-serie">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<ul>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/16/windows-subsystem-fuer-linux-wsl/"
>Windows Subsystem für Linux (WSL)</a></li>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/16/wsl-interaktion-zwischen-den-systemen-i/"
>WSL: Interaktion zwischen den Systemen (I)</a></li>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/16/wsl-interaktion-zwischen-den-systemen-ii/"
>WSL: Interaktion zwischen den Systemen (II)</a></li>
<li><strong>WSL: C++ Entwicklung mit CLion</strong></li>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/19/wsl-services-automatisch-starten/"
>WSL: Services automatisch starten</a></li>
</ul>
<p>Die Entwicklungsumgebung <a
class="gblog-markdown__link"
href="https://www.jetbrains.com/clion/"
>CLion</a> von <a
class="gblog-markdown__link"
href="https://www.jetbrains.com/"
>JetBrains</a> bringt keinen eigenen Compiler mit sondern kann mit diversen Compilern umgehen.</p>
<p>Eine Option ist dabei, ein Windows Subsystem für Linux zu nutzen. Dann kann der Windows Arbeitsplatz genutzt werden, um Software für Linux zu entwickeln.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="software-auf-debian-installieren">
Software auf Debian installieren
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/06/16/wsl-c-entwicklung-mit-clion/#software-auf-debian-installieren" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Software auf Debian installieren" href="#software-auf-debian-installieren">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Damit auf dem Debian WSL entwickelt werden kann, müssen erst die notwendigen Voraussetzungen geschaffen werden. Dazu werden die folgenden Pakete installiert:</p>
<table>
<thead>
<tr>
<th><strong>Paket</strong></th>
<th><strong>Beschreibung</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td>build-essential</td>
<td>Grundlegende Tools rund um den Compiler.</td>
</tr>
<tr>
<td>cmake</td>
<td>cmake als Standard Make-Tool von CLion</td>
</tr>
<tr>
<td>gdb</td>
<td>Debugger</td>
</tr>
<tr>
<td>ssh</td>
<td>Sammlung von SSH Paketen incl. openssh-server</td>
</tr>
</tbody>
</table>
<p>Die Installation kann mit folgendem Befehl durchgeführt werden:</p>
<pre tabindex="0"><code>sudo apt-get install build-essential cmake gdb ssh
</code></pre><p>Nach der Installation von ssh muss der Server noch gestartet werden:</p>
<pre tabindex="0"><code>sudo service ssh start
</code></pre><div class="gblog-post__anchorwrap flex align-center">
<h2 id="konfiguration-der-clion-toolchain">
Konfiguration der CLion Toolchain
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/06/16/wsl-c-entwicklung-mit-clion/#konfiguration-der-clion-toolchain" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Konfiguration der CLion Toolchain" href="#konfiguration-der-clion-toolchain">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Als nächstes können wir die Toolchain in CLion konfigurieren. Dazu öffnen wir in CLion die Settings (File -> Settings…)<br>
In den Settings finden sich die Toolchains unter Build, Execution, Deployment</p>
<p>Dort öffnet sich über das (+) ein kleines Menü, in dem WSL ausgewählt werden kann. Danach sind folgende Felder ausfüllbar:</p>
<table>
<thead>
<tr>
<th><strong>Feld</strong></th>
<th><strong>Beschreibung</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td>Name</td>
<td>Hier kann ein beliebiger Name für diese Toolchain eingegeben werden. Default ist WSL.</td>
</tr>
<tr>
<td>Environment</td>
<td>In dem Dropdown kann keine WSL Umgebung ausgewählt werden, so mehrere installiert wurden.</td>
</tr>
<tr>
<td>Credentials</td>
<td>Hier muss konfiguriert werden, wie CLion per ssh auf die WSL zugreifen soll. Eingabe von localhost als host und speichern von User/Passwort reicht schon aus. Wer kein Passwort speichern möchte, kann auch über einen SSH Key zugreifen.</td>
</tr>
</tbody>
</table>
<p>Die übrigen Felder sollten automatisch gefüllt werden. CLion kann auf das System zugreifen und selbständig feststellen, welche Tools in welcher Version installiert sind.</p>
<p><span style="color: #008000;"><strong>Gratulation, CLion ist bereit, um mit dem Linux Subsystem C++ Projekte zu übersetzen!</strong></span></p>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="links">
Links
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/06/16/wsl-c-entwicklung-mit-clion/#links" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Links" href="#links">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<ul>
<li>CLion von <a
class="gblog-markdown__link"
href="https://www.jetbrains.com/"
>JetBrains</a>: <a
class="gblog-markdown__link"
href="https://www.jetbrains.com/clion/"
>https://www.jetbrains.com/clion/</a></li>
</ul>
<div class="gblog-post__anchorwrap flex align-center">
<h1 id="edits">
Edits
</h1>
<a data-clipboard-text="https://blog.kneitzel.de/2020/06/16/wsl-c-entwicklung-mit-clion/#edits" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Edits" href="#edits">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<table>
<thead>
<tr>
<th>19.06.2020</th>
<th>Tippfehler beseitigt, Paket heißt build-essential und nicht build-essentials</th>
</tr>
</thead>
</table>
WSL: Interaktion zwischen den Systemen (II)https://blog.kneitzel.de/2020/06/16/wsl-interaktion-zwischen-den-systemen-ii/2020-06-16T16:13:17+00:002023-01-16T20:14:20+01:00
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="beiträge-der-wsl-serie">
Beiträge der WSL Serie
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/06/16/wsl-interaktion-zwischen-den-systemen-ii/#beiträge-der-wsl-serie" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Beiträge der WSL Serie" href="#beitr%c3%a4ge-der-wsl-serie">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<ul>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/16/windows-subsystem-fuer-linux-wsl/"
>Windows Subsystem für Linux (WSL)</a></li>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/16/wsl-interaktion-zwischen-den-systemen-i/"
>WSL: Interaktion zwischen den Systemen (I)</a></li>
<li><strong>WSL: Interaktion zwischen den Systemen (II)</strong></li>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/16/wsl-c-entwicklung-mit-clion/"
>WSL: C++ Entwicklung mit CLion</a></li>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/19/wsl-services-automatisch-starten/"
>WSL: Services automatisch starten</a></li>
</ul>
<p>In diesem Beitrag möchte ich etwas auf die Interaktion zwischen Linux und Windows Applikationen auf der jeweiligen Shell / Eingabeaufforderung eingehen.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="starten-von-linux-programmen-unter-windows">
Starten von Linux Programmen unter Windows
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/06/16/wsl-interaktion-zwischen-den-systemen-ii/#starten-von-linux-programmen-unter-windows" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Starten von Linux Programmen unter Windows" href="#starten-von-linux-programmen-unter-windows">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Wenn wir eine Windows Eingabeaufforderung geöffnet haben, dann können Linux Prozesse gestartet werden, in dem vor dem Aufruf ein wsl vorrangestellt wird. Wenn ich z.B. in der Windows Eingabeaufforderung das aktuelle Verzeichnis mittels „ls“ anzeigen lassen möchte, dann kann ich dieses mittels</p>
<pre tabindex="0"><code>wsl ls
</code></pre><p>ausführen.</p>
<p>Wenn sich die Befehlszeile aus mehreren Befehlen zusammen setzt (z.B. getrennt durch das Pipe Zeichen („|“), so kann dies bei jedem Befehl erfolgen. Z.B. über</p>
<p>dir | wsl grep file</p>
<p>Der Windows Befehl „dir“ gibt seine Ausgabe an den Linux Befehl „grep file“, d.h. es wird von grep nach Zeilen mit der Zeichenkette ‚file‘ gesucht.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="starten-von-windows-programmen-aus-linux">
Starten von Windows Programmen aus Linux
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/06/16/wsl-interaktion-zwischen-den-systemen-ii/#starten-von-windows-programmen-aus-linux" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Starten von Windows Programmen aus Linux" href="#starten-von-windows-programmen-aus-linux">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Umgekehrt ist es auch möglich, aus der Linux Shell ein Windows Programm zu starten. Dazu muss der Befehl mit der Endung (z.B. .exe) eingegeben werden:</p>
<pre tabindex="0"><code>notepad.exe
</code></pre><div class="gblog-post__anchorwrap flex align-center">
<h1 id="links">
Links
</h1>
<a data-clipboard-text="https://blog.kneitzel.de/2020/06/16/wsl-interaktion-zwischen-den-systemen-ii/#links" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Links" href="#links">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<ul>
<li>Windows Interoperabilität: <a
class="gblog-markdown__link"
href="https://docs.microsoft.com/de-de/windows/wsl/interop"
>https://docs.microsoft.com/de-de/windows/wsl/interop</a></li>
</ul>
WSL: Interaktion zwischen den Systemen (I)https://blog.kneitzel.de/2020/06/16/wsl-interaktion-zwischen-den-systemen-i/2020-06-16T16:03:09+00:002023-01-16T20:14:20+01:00
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="beiträge-der-wsl-serie">
Beiträge der WSL Serie
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/06/16/wsl-interaktion-zwischen-den-systemen-i/#beiträge-der-wsl-serie" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Beiträge der WSL Serie" href="#beitr%c3%a4ge-der-wsl-serie">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<ul>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/16/windows-subsystem-fuer-linux-wsl/"
>Windows Subsystem für Linux (WSL)</a></li>
<li><strong>WSL: Interaktion zwischen den Systemen (I)</strong></li>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/16/wsl-interaktion-zwischen-den-systemen-ii/"
>WSL: Interaktion zwischen den Systemen (II)</a></li>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/16/wsl-c-entwicklung-mit-clion/"
>WSL: C++ Entwicklung mit CLion</a></li>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/19/wsl-services-automatisch-starten/"
>WSL: Services automatisch starten</a></li>
</ul>
<p>Nach der Installation des Windows Subsystems für Linux und einer Linux Distribution haben wir nun zwei Systeme. Aber die zwei Systeme sind nicht komplett voneinander getrennt zu sehen, denn Microsoft hat viele Möglichkeiten eingebaut, damit die zwei Systeme miteinander agieren können und Anwender so das Beste aus beiden Welten kombinieren können.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="keine-getrennten-systeme">
Keine getrennten Systeme!
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/06/16/wsl-interaktion-zwischen-den-systemen-i/#keine-getrennten-systeme" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Keine getrennten Systeme!" href="#keine-getrennten-systeme">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Eine wichtige Tatsache ist, dass es sich hier nicht um zwei getrennte Systeme handelt, wie es z.B. bei den den üblichen VM wie VirtualBox oder Vmware Workstation der Fall wäre.</p>
<p>Um dies etwas aufzuzeigen, installieren wir einmal ssh unter Linux (Debian):</p>
<pre tabindex="0"><code>sudo apt-get install ssh
</code></pre><pre tabindex="0"><code>sudo service ssh start
</code></pre><p>Sobald der ssh Service unter Debian startet bekommen wir unter Windows das Popup der Firewall: Bei welchen „Netzwerkklassen“ darf auf den Port zugegriffen werden.</p>
<p>Wenn wir unter Windows einen ssh Client haben, dann können wir da auch drauf zugreifen über die ip 127.0.0.1.</p>
<p>Wir können aber auch die IPs vergleichen:</p>
<pre tabindex="0"><code>ip address
</code></pre><p>Wir bekommen die Devices angezeigt und die IPs von Windows (Welche wir uns z.B. mit</p>
<pre tabindex="0"><code>ipconfig -all
</code></pre><p>auf der Eingabeaufforderung anzeigen lassen können).</p>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="zugriff-auf-windows-dateien-aus-der-wsl">
Zugriff auf Windows Dateien aus der WSL
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/06/16/wsl-interaktion-zwischen-den-systemen-i/#zugriff-auf-windows-dateien-aus-der-wsl" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Zugriff auf Windows Dateien aus der WSL" href="#zugriff-auf-windows-dateien-aus-der-wsl">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Wenn wir nun in einer Shell von Debian sind, dann können wir auf die Dateien von unserem Windows System zugreifen. Dazu werden die Laufwerke unter /mnt gemounted.</p>
<p>Somit finden wir unter /mnt/c unser Laufwerk C:</p>
<p>Wir können dies unter Linux prüfen über den Befehl</p>
<pre tabindex="0"><code>mount
</code></pre><p>Dies gibt uns unter anderem aus, wie einzelne Filesysteme eingebunden wurden:</p>
<pre tabindex="0"><code>C:\ on /mnt/c type drvfs (rw,noatime,uid=1000,gid=1000,case=off)
</code></pre><p>Bei einem System von mir, war hier aber uid und gid 0 statt 1000. Daher hatte nur root Schreibzugriff. Dies kann man über die /etc/wsl.conf steuern:</p>
<pre tabindex="0"><code>[autoconf]<br></br>options = "metadata,uid=1000,gid=1000"
</code></pre><p>Hier können wir die Optionen, die der mount Befehl unterstützt, eintragen.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="gemeinsames-home">
Gemeinsames Home
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/06/16/wsl-interaktion-zwischen-den-systemen-i/#gemeinsames-home" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Gemeinsames Home" href="#gemeinsames-home">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Derzeit ist es so, dass wir zwei Home Laufwerke haben. Unter Linux finden wir unsere Dateien unter /home/<username>/ und unter Windows haben wir c:\Users\<username>.</p>
<p>Dies können wir aber auch noch anpassen und alle unsere Dateien unter c:\users\<username> legen. Der erste wichtige Schritt ist die Kontrolle, dass unser User die notwendigen Schreibrechte auf /mnt/c hat. Ist dies gegeben, dann können wir unser Unix-Homelaufwer verschieben und statt dessen einen Softlink auf das Windows Verzeichnis einrichten.</p>
<p>In dem folgenden Beispiel habe ich <username> durch konrad ersetzt – mein User unter Linux und Windows ist konrad:</p>
<pre tabindex="0"><code>cd /home<br></br>sudo mv konrad konrad.old<br></br>sudo ln -s /mnt/c/Users/konrad konrad<br></br>cp konrad.old/.??* konrad/
</code></pre><p>Der letzte Befehl kopiert die Dateien, die mit . anfangen, in das Windows Homeverzeichnis. Hier ist vor allem die .bashrc mit Einstellungen für die Linux Shell wichtig.</p>
<p>Sollten bereits weitere Dateien erzeugt worden sein, so sind diese ggf. auch noch zu kopieren.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="zugriff-auf-linux-dateien-von-windows-aus">
Zugriff auf Linux Dateien von Windows aus
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/06/16/wsl-interaktion-zwischen-den-systemen-i/#zugriff-auf-linux-dateien-von-windows-aus" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Zugriff auf Linux Dateien von Windows aus" href="#zugriff-auf-linux-dateien-von-windows-aus">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Nun haben wir unter Linux auf die Windows Dateien zugegriffen. Aber vielleicht wollen wir auch den umgekehrten Fall: Zugriff aus z.B. dem Windows Explorer auf die Dateien des Linux Subsystems.</p>
<p>Dafür hat Microsoft den Share \\wsl$ erzeugt. Wenn man im Windows Explorer in der Adresszeile</p>
<pre tabindex="0"><code>\\wsl$
</code></pre><p>eingibt, dann werden alle Linux Subsysteme angezeigt. (Bei mir gibt es nur das Debian System, somit wird Debian angezeigt)</p>
<p>Ein Doppelclick zeigt dann den Inhalt des Debian Dateisystems an. Ich kann aber auch immer die Adresse direkt angeben:</p>
<pre tabindex="0"><code>\\wsl$\Debian
</code></pre><p>Damit haben wir nun Zugriff auf alle Dateien sowohl unter Linux als auch unter Windows.</p>
<p>Im nächsten Beitrag „WSL: Interaktion zwischen den Systemen (II)“ werde ich auf die Interaktion zwischen Projekten eingehen.</p>
Windows Subsystem für Linux (WSL)https://blog.kneitzel.de/2020/06/16/windows-subsystem-fuer-linux-wsl/2020-06-16T13:59:07+00:002023-01-19T22:51:40+01:00
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="beiträge-der-wsl-serie">
Beiträge der WSL Serie
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/06/16/windows-subsystem-fuer-linux-wsl/#beiträge-der-wsl-serie" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Beiträge der WSL Serie" href="#beitr%c3%a4ge-der-wsl-serie">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<ul>
<li><strong>Windows Subsystem für Linux (WSL)</strong></li>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/16/wsl-interaktion-zwischen-den-systemen-i/"
>WSL: Interaktion zwischen den Systemen (I)</a></li>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/16/wsl-interaktion-zwischen-den-systemen-ii/"
>WSL: Interaktion zwischen den Systemen (II)</a></li>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/16/wsl-c-entwicklung-mit-clion/"
>WSL: C++ Entwicklung mit CLion</a></li>
<li><a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2020/06/19/wsl-services-automatisch-starten/"
>WSL: Services automatisch starten</a></li>
</ul>
<p>Microsoft hat schon eine ganze Zeit lang das Windows Subsystem für Linux (kurz: WSL) unter Windows 10 bereit gestellt so dass dies inzwischen aus dem „Versuchsstadium“ heraus sein sollte.</p>
<p>Unter Windows war ich bisher ein Fan von cygwin, denn ich wollte unter Windows auch die gewohnten Tools nicht missen.</p>
<p>Daher wird es nun für mich Zeit, diese Microsoft Lösung näher anzusehen und eine kleine Serie aufzusetzen, welche die wichtigsten Schritte kurz erläutert und auch mögliche Anwendungsgebiete aufzeigt.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="wsl-1-und-wsl-2">
WSL 1 und WSL 2
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/06/16/windows-subsystem-fuer-linux-wsl/#wsl-1-und-wsl-2" class="gblog-post__anchor clip flex align-center" aria-label="Anchor WSL 1 und WSL 2" href="#wsl-1-und-wsl-2">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Das Windows Subsystem für Linux existiert nun schon in der zweiten Version. Microsoft hat hier aus meiner Sicht kräftig nachgebessert, so dass ich auf jeden Fall empfehlen würde, immer gleich auf die WSL 2 gehen.</p>
<p>Voraussetzung für WSL 2 ist Windows 10 in Version (Build) 19041 oder neuer</p>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="installation">
Installation
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/06/16/windows-subsystem-fuer-linux-wsl/#installation" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Installation" href="#installation">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Die Installation erfolgt entweder über die GUI:<br>
– Einstellungen Öffnen<br>
– Apps auswählen<br>
– Ganz unten „Programme und Features“ anklicken<br>
– im neuen Fenster dann „Windows Features aktivieren oder deaktivieren“<br>
– Feature „Windows-Subsystem für Linux“ auswählen und Installation starten.</p>
<p>Oder man öffnet einfach eine Eingabeaufforderung oder PowerShell mit Administrator-Rechten und gibt ein:</p>
<pre tabindex="0"><code>dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
</code></pre><p>Nach der Installation des Windows Subsystems für Linux müssen wir den Rechner einmal neu starten.</p>
<p>Das blanke Subsystem nützt uns aber erst einmal nichts. Was wir nun noch benötigen ist eine Linux Distribution. Diese können wir einfach über den Microsoft Store installieren. Die gängigsten Distributionen sind verfügbar und als Debian Fan ist meine Wahl direkt auf <a
class="gblog-markdown__link"
href="https://www.microsoft.com/de-de/p/debian/9msvkqc78pk6"
>Debian </a>gefallen.</p>
<p>Nach der Installation können wir uns noch einen Eintrag in dem Startmenü anlegen lassen.</p>
<p>Der ersten Start dauert etwas, da jetzt die Debian Installation weiter konfiguriert wird. Im Rahmen dieser Installation wird der User erstellt, mit dem zukünftig gearbeitet werden kann.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h1 id="erster-überblick">
Erster Überblick
</h1>
<a data-clipboard-text="https://blog.kneitzel.de/2020/06/16/windows-subsystem-fuer-linux-wsl/#erster-überblick" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Erster Überblick" href="#erster-%c3%bcberblick">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Beim Start von Debian öffnet sich ein Fenster und man sieht eine Shell vom angelegten User.</p>
<p>Sudo ist eingerichtet und man kann sich z.B. per</p>
<pre tabindex="0"><code>sudo su -
</code></pre><p>eine root-Shell holen (nach Eingabe des vergebenen Passwortes).</p>
<p>Unter /mnt werden die Windows Laufwerke gemappt, jedoch hat hier nur root Schreibzugriff (Dies passen wir noch im nächsten Beitrag an).</p>
<div class="gblog-post__anchorwrap flex align-center">
<h1 id="software">
Software
</h1>
<a data-clipboard-text="https://blog.kneitzel.de/2020/06/16/windows-subsystem-fuer-linux-wsl/#software" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Software" href="#software">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Auf dem System ist noch nicht viel an Software installiert. Je nachdem, was man alles machen will, kann man aber Debian Pakete nachinstallieren. Ein X11 Server steht hier aber erst einmal nicht zur Verfügung, so dass X11 Programme erst einmal nicht zur Verfügung stehen. Wie diese Thematik gelöst werden kann, werde ich in Kürze ebenfalls beleuchten.</p>
<p>Der Zugriff auf die Repositories funktioniert aber ohne Probleme, wie man mit apt-get schnell sehen kann. Eine Aktualisierung des Systems erfolgt über die folgenden zwei Befehle:</p>
<pre tabindex="0"><code>sudo apt-get update
</code></pre><pre tabindex="0"><code>sudo apt-get upgrade
</code></pre><div class="gblog-post__anchorwrap flex align-center">
<h1 id="links">
Links
</h1>
<a data-clipboard-text="https://blog.kneitzel.de/2020/06/16/windows-subsystem-fuer-linux-wsl/#links" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Links" href="#links">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<ul>
<li>WSL Überblick: <a
class="gblog-markdown__link"
href="https://docs.microsoft.com/de-de/windows/wsl/about"
>https://docs.microsoft.com/de-de/windows/wsl/about</a></li>
<li>Debian im Microsoft Store: <a
class="gblog-markdown__link"
href="https://www.microsoft.com/de-de/p/debian/9msvkqc78pk6"
>https://www.microsoft.com/de-de/p/debian/9msvkqc78pk6</a></li>
</ul>
certbot mit Windowshttps://blog.kneitzel.de/2020/02/21/certbot-mit-windows/2020-02-21T13:34:56+00:002023-01-19T22:51:40+01:00
<p>Nachdem ich certbot unter cygwin nutzen konnte, stellte sich direkt die Frage: Ist dies überhaupt notwendig? Für mich war dies naheliegend, da ich auch Scripte im Einsatz hatte, die die neuen Zertifikate bei Bedarf direkt weiter verarbeitet haben.</p>
<p>Aber da Python auch unter Windows zur Verfügung steht, habe ich keinen Grund gesehen, dass dies nicht auch unter Windows funktionieren sollte. Und ein kurzer Test hat schnell erstaunlich gute Ergebnisse gezeigt:</p>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="installation-unter-windows">
Installation unter Windows
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/02/21/certbot-mit-windows/#installation-unter-windows" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Installation unter Windows" href="#installation-unter-windows">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Zuerst wird natürlich python benötigt. Die Downloads finden sich unter <a
class="gblog-markdown__link"
href="https://www.python.org/downloads/windows/"
>https://www.python.org/downloads/windows/</a> und die Installation erfolgt wie unter Windows gewohnt einfach und unkompliziert ab. (Aktuell war Python 3.8.1 aktuell, welches ich für alle Anwender auf meinem Windows Server 2016 Essentials System installiert habe.)</p>
<p>Als nächstes erfolgt, ebenso wie unter cygwin, die Installation von certbot:</p>
<pre tabindex="0"><code><pre class="wp-block-preformatted">pip install certbot
</code></pre><p>Die Installation lief zügig durch und nach kurzer Zeit stand mir certbot zur Verfügung. Schnell ein kleiner Test:</p>
<pre tabindex="0"><code><pre class="wp-block-preformatted">certbot certonly --manual -d test.kneitzel.de --preferred-challenge dns
</code></pre><p>Der erste Versuch in einem Terminal ohne Adminrechte erbrachte gleich einen Fehler: Die Applikation möchte mit Adminrechten aufgerufen werden!</p>
<p>Also das Ganze noch einmal mit Administrativen Rechten und es kamen die gewohnten Abfragen, so wie unter anderen Systemen auch. Und nach Aufspielen des TXT Eintrags für _acme-challenge.test im DNS lief alles problemlos durch und ich hatte die Zertifikate.</p>
<p>Die Dateien liegen jetzt natürlich nicht wie bei Unix gewohnt unter /etc/letsencrypt sondern es wurde c:\Certbot angelegt und verwendet.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="anmerkung">
Anmerkung
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/02/21/certbot-mit-windows/#anmerkung" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Anmerkung" href="#anmerkung">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Ich habe hier natürlich nur einen sehr kleinen Bereich von Certbot getestet – speziell die manuelle Erstellung/Aktualisierung von Letsencrypt Zertifikaten mit Certbot.<br>
Certbot bietet aber einiges mehr – so sorgt Certbot in der Regel selbst für die Autorisierung (z.B. über das Hinterlegen von Dateien in einem Webserver) und das Einspielen von Zertifikaten. Dies habe ich nicht angetestet und ich kann keine Aussage dazu treffen, ob und wie dies funktionieren würde.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="links">
Links
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/02/21/certbot-mit-windows/#links" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Links" href="#links">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<ul>
<li>Python für Windows: <a
class="gblog-markdown__link"
href="https://www.python.org/downloads/windows/"
>https://www.python.org/downloads/windows/</a></li>
</ul>
certbot mit Windows (cygwin)https://blog.kneitzel.de/2020/02/21/certbot-in-cygwin/2020-02-21T12:59:40+00:002023-01-19T22:51:40+01:00
<p>Wenn man selbst Zertifikate von <a
class="gblog-markdown__link"
href="https://letsencrypt.org/"
>https://letsencrypt.org/</a> beantragen möchte und ein Windows System sein eigenen nennt, der findet dann erst einmal keine sofortige Lösung:</p>
<p>Man wird auf die Seite vom Certbot geleitet und dort finden sich dann Anleitungen für diverse Distributionen aber leider nicht für Windows. Bei Non Unix findet man lediglich die Aussage: „Certbot is currently only available for UNIX-like operating systems.“, was einem nicht unbedingt direkt weiter hilft.</p>
<p>Aber Unix? Da fällt zumindest mir sofort Cygwin ein. (Microsoft bietet aber auch eine Lösung, um ein Linux System unter Windows laufen zu lassen, das Windows-Subsystem for Linux: <a
class="gblog-markdown__link"
href="https://docs.microsoft.com/de-de/windows/wsl/install-win10"
>https://docs.microsoft.com/de-de/windows/wsl/install-win10</a>)</p>
<p>Cygwin ist schnell von <a
class="gblog-markdown__link"
href="https://www.cygwin.com/"
>https://www.cygwin.com/</a> herunter geladen und bei der Installation darauf achten, dass das aktuelle Python mit installiert wird. (Ich habe die paar python38 Pakete installiert.)</p>
<p>Das certbot lässt sich dann über pythen pip installieren:</p>
<pre tabindex="0"><code><pre class="wp-block-preformatted">pip3.8 install certbot
</code></pre><p>(Den Befehl in einem Cygwin Terminal mit Administrationsrechten eingeben und in Ruhe abwarten, bis die Installation durch ist.)</p>
<p>Die Nutzung von certbot erfolgt dann wie in der Dokumentation beschrieben. Da ich keinen direkten Zugriff auf die Webhosting Server habe, nutze ich die manuelle Verifikation:</p>
<pre tabindex="0"><code><pre class="wp-block-preformatted">cerbot certonly --manual -d fqdn.of.my.server --preferred-challenge dns
</code></pre><p>certbot gibt dann klare Anweisung, was für ein TXT Eintrag man in der Domain setzen soll und nach setzen des Keys wird dann das Zertifikat ausgestellt / verlängert.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="links">
Links
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2020/02/21/certbot-in-cygwin/#links" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Links" href="#links">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<ul>
<li>Lets encrypt: <a
class="gblog-markdown__link"
href="https://letsencrypt.org/"
>https://letsencrypt.org</a></li>
<li>Windows-Subsystem für Linux: <a
class="gblog-markdown__link"
href="https://docs.microsoft.com/de-de/windows/wsl/install-win10"
>https://docs.microsoft.com/de-de/windows/wsl/install-win10</a></li>
<li>Cygwin: <a
class="gblog-markdown__link"
href="https://www.cygwin.com/"
>https://www.cygwin.com/</a></li>
</ul>
Nokia 800 Toughhttps://blog.kneitzel.de/2019/11/04/nokia-800-tough/2019-11-04T10:35:27+00:002023-01-16T20:14:20+01:00
<p>Ich habe schon lange diese ganze Entwicklung mit den Smartphones kritisch gesehen: ständig haben die Leute ihr Smartphone in der Hand und machen damit irgendwas. Egal, was um sie herum passiert.</p>
<p>Das mag lustig sein, wenn man z.B. ein Video von einem Überfall auf eine Bar sieht, bei dem ein Mann am Tresen so auf sein Smartphone fokusiert ist, dass er nichts vom Überfall mitbekommt und sich am Ende wundert, dass alle Anderen noch auf dem Boden liegen nachdem der Täter eben erst die Bar verlassen hat… Aber wenn Freunde oder Bekannte zusammen stehen und alle haben Ihr Smartphone in der Hand? Das finde ich kritisch.</p>
<p>Hinzu kommt, dass es ein Objekt ist, in das zu viel Zeit investiert wird. Es kommt eine Nachricht und man will nur kurz schauen, wer einem geschrieben hat. Aber wenn man das Gerät einmal in der Hand hat: Was für Neuigkeiten gibt es denn in aller Welt? Oder kurz in ein Spiel rein schauen …</p>
<p>Somit habe ich in den letzten Wochen massiv über Alternativen nachgedacht. Die Erreichbarkeit möchte ich nicht missen (Telefon, SMS), weil ich dies auch beruflich benötige. Aber darüber hinaus ist vieles unnötig…</p>
<p>Somit habe ich mich umgesehen und gleich viele Möglichkeiten gefunden: Nokia bietet eine ganze Reihe von Geräten: die reinen Mobiltelefone (Nokia 105, Nokia 130) über Geräte mit KaiOS (Nokia 2720 flip und Nokia 800 tough). Da ich das Gerät auch bei Feuerwehr Einsätzen mitnehmen möchte, habe ich mich für ein Nokia 800 tough entschieden. Dank KaiOS wird auch WhatsApp und Facebook unterstützt und die Kamera hat mit 2 MP wenigstens die Chance, Fotos zu machen, die etwas anzeigen.</p>
<p>Die Akku-Laufzeit wird bei dem Gerät auch mit bis zu 43 Tagen Standby angegeben, was mich fasziniert hat: Nur ein bis zwei Mal im Monat das Gerät laden! Somit wurde das Gerät gekauft um es im Detail zu testen.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h1 id="der-erste-eindruck">
Der erste Eindruck
</h1>
<a data-clipboard-text="https://blog.kneitzel.de/2019/11/04/nokia-800-tough/#der-erste-eindruck" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Der erste Eindruck" href="#der-erste-eindruck">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Der erste Eindruck beim Auspacken des Gerätes war sehr gut. Das Gerät ist handlich, etwas dicker als ein Smartphone aber dafür schmaler. Die Verarbeitung macht einen guten Eindruck.</p>
<p>Das einlegen der SIM Karten war aber relativ problematisch. Wie bei vielen Smartphones muss man mit so einem mitgelieferten Drahtstift an der Seite einen Träger für die SIM Karten heraus drücken. Dabei wird der Träger aber nur sehr wenig heraus gedrückt und man kann ihn noch nicht fassen. Eine kleine Zange hat mir aber geholfen und ich konnte meine beiden SIM Karten (privat und beruflich) einlegen.</p>
<p>Die Inbetriebnahme war bei mir problematisch. Ich war diesen Wipp-Schalter, mit dem man man im Menü hoch und runter gehen kann und auch die Auswahl bestätigt, nicht mehr gewohnt und so passierte, was passieren musste: Bei Auswahl der Sprache habe ich zugleich die Auswahl geändert und ich hatte ein Handy in einer fremden Sprache. So gab es dann noch ein nettes Spiel: Mach ein Reset des Gerätes ohne das Menü wirklich zu verstehen :). Das ist aber etwas, das ich dem Gerät nicht anlaste. Die Bedienung ist ok und nach kurzer Gewöhnung gab es da auch keine Probleme mit der Bedienung mehr.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h1 id="nutzung">
Nutzung
</h1>
<a data-clipboard-text="https://blog.kneitzel.de/2019/11/04/nokia-800-tough/#nutzung" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Nutzung" href="#nutzung">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p><strong>Synchronisierung</strong></p>
<p>Das Gerät bietet vielseitige Möglichkeiten an. So kann man Kontakte, Termine, Emails, … synchronisieren. Auch Google wird hier unterstützt und ich konnte schnell und einfach meinen GSuite Account hinterlegen. (Mit Unterstützung der aktuellen Sicherheitsvorgaben, also wirklich ganz problemlos). Da ich zwei SIM Karten nutze und so nur wenig freien Speicherplatz habe, wollte ich erst einmal mit den Kontakten anfangen:</p>
<p>Kontakte geöffnet und ihm gesagt, dass er synchronisieren soll. Dies ist aber leider mit einem wenig aussagenden Fehler fehlgeschlagen. Eine Synchronisierung ließ sich auch mit einigem rumprobieren nicht durchführen.</p>
<p>Es gibt auch eine Import Funktion. Auch wenn ich mir hier keinen Erfolg versprochen habe, habe ich den Import probiert. Das bereits eingerichtete Konto gewählt und schwups: alle meine Kontakte waren importiert. Das ist super! Natürlich nicht perfekt aber so oft ändern sich die Kontakte nicht, so dass dies für mich voll und ganz akzeptabel ist.</p>
<p>Die Synchronisation der anderen Elemente habe ich mir an dieser Stelle erspart und nicht weiter ausprobiert. Meine Kontakte und Co pflege ich in einem A5 Terminkalender in dem auch genug Platz für weitere Dinge sind, so dass ich dies nicht auf meinem Handy brauche.</p>
<p>Weitere Funktionalitäten, die ich eingesetzt habe:</p>
<ul>
<li>Wecker – der Wecker hat bei mir einwandfrei und sicher funktioniert mit der üblichen Funktionalität (z.B. Wecker, der an Werktagen einen wecken soll).</li>
<li>Taschenlampe – ich finde es gut, dass die Taschenlampe an der schmalen Seite zu finden ist. So ist es die übliche Haltung einer Taschenlampe und nicht so wie bei Smartphones ein aufrechtes Halten des Smartphones. Die Lichtstärke der Taschenlampe ist aber deutlich geringer als der „Blitz“, den ich von Smartphones her kenne (iPhone 7, Huawei P10 lite). Aber die Lichtstärke ist vollkommen ausreichend für das ausleuchten der näheren Umgebung um z.B. im Dunkeln mit dem Hund spazieren zu gehen.</li>
</ul>
<p><strong>Verbindungsmöglichkeiten</strong></p>
<p>Das Handy ist super, was die Verbindungsmöglichkeiten angeht. Da steht es den Smartphones in nichts nach. So wird auch LTE unterstützt. Tethering ist möglich – sowohl per USB als auch per aufgespanntem WLAN. Damit ist es ein guter Begleiter, wenn man unterwegs mit seinem Laptop Internet benötigt.</p>
<p>Sprache kann nicht nur über 2G sondern auch über aktuelle Protokolle geführt werden. Auch WLAN wird unterstützt, was ich immer gut fand, denn so kann man auch im Haus problemlos telefonieren, wo sonst der Empfang durch die Wände erschwert wurde.</p>
<p>WhatsApp ist vorhanden, aber mit stark eingeschränkter Funktionalität: Zum einen werden keine Sprachanrufe unterstützt (Aber wer viel Datenvolumen hat, so dass Sprachanrufe möglich sind, der hat doch in der Regel auch eine Sprach-Flat? Zumindest ich habe auch eine Sprach Flat, so dass dieser Punkt mich nicht stört) und auch das Web WhatsApp ist nicht möglich, d.h. man hat keine Möglichkeit, vom Computer einen QR Code zu scannen um dann am Computer WhatsApp zu nutzen.) Dadurch wurde die Kommunikation über WhatsApp sehr beschwerlich, denn Nachrichten mit der Telefon Tastatur zu schreiben ist doch recht mühsam. Damit beschränkte ich mich auf Sprachnachrichten, die unterstützt werden.</p>
<p><strong>Akkulaufzeit</strong></p>
<p>Eine Laufzeit von bis zu 43 Tagen Standby wurde versprochen. Aber nach etwas Nutzung war der Akku nach nur drei Tagen leer. Das war so nicht wirklich erwartet. Ich hatte hier schon so ein bis zwei Wochen erwartet. Somit wurde einiges optimiert:</p>
<ul>
<li>Sprache über LTE verbraucht mehr Strom -> abgeschaltet.</li>
<li>WLAN -> abgeschaltet (Also kein Telefonieren zuhause über WLAN)</li>
<li>Datenverbindung -> abgeschaltet (Also auch kein WhatsApp mehr)</li>
</ul>
<p>Somit wurde mein Gerät zu einem reinen Mobiltelefon, Wecker und Taschenlampe degradiert. Die Laufzeit wurde dadurch auch massiv erhöht, aber die Laufzeit beträgt nun immer noch nur ein bis zwei Wochen und damit immer noch deutlich weniger als die versprochenen „bis zu 43 Tage“. Das ist natürlich enttäuschend aber immer noch besser als als die maximal 2 Tage bei meinen Smartphones.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h1 id="fazit">
Fazit
</h1>
<a data-clipboard-text="https://blog.kneitzel.de/2019/11/04/nokia-800-tough/#fazit" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Fazit" href="#fazit">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Ich bin von dem Gerät etwas enttäuscht. Aber ein Teil der Enttäuschung sind nicht eingehaltene Versprechen (43 Tage versprochen, die fast 2 Wochen sind aber immer noch sehr gut und ausreichend finde ich!) und falsche Hoffnungen (Ich habe halt auf das WhatsApp Web gehofft). Das Handy bietet einige Funktionen, die ich sehr gut finde, so werde ich es als mein Haupt-Telefon behalten um damit erreichbar zu sein. Aber mein Smartphone wird auch weiter im Betrieb bleiben. Damit habe ich dann gewisse weitere Funktionen. Aber dank des Nokia 800 tough ist das bisherige Smartphone nun nicht mehr mein ständiger Begleiter und damit die Ablenkung deutlich kleiner.</p>
<p>Ob nun ein Nokia 105 oder 130 die bessere Wahl gewesen wäre? Es wäre auf jeden Fall deutlich günstiger aber dafür weniger robust. Und die Verbindungsmöglichkeiten wären deutlich geringer.</p>
<p>Ein vollwertigen Ersatz für ein Smartphone sehe ich aber nicht. Aber ich könnte mir gut vorstellen, dass es in Verbindung zu einem Tablet auch sehr gute Arbeit leisten würde! Als einziges Gerät wäre es für mich aber dann doch zu wenig.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h1 id="links">
Links
</h1>
<a data-clipboard-text="https://blog.kneitzel.de/2019/11/04/nokia-800-tough/#links" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Links" href="#links">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<ul>
<li><a
class="gblog-markdown__link"
href="https://www.nokia.com/phones/de_de/nokia-800-tough"
>Homepage des Nokia 800 Tough</a></li>
<li><a
class="gblog-markdown__link"
href="https://www.amazon.de/gp/product/B07X63JCWT"
>Nokia 800 Tough bei Amazon</a></li>
</ul>
HP ZBook 15 G2https://blog.kneitzel.de/2019/10/01/hp-zbook-15-g3/2019-10-01T08:06:58+00:002023-01-19T22:51:40+01:00
<p>Für die Arbeit Zuhause habe ich mir nun einen ’neuen‘ Laptop gekauft. Für mich war wichtig, dass ich zur Software Entwicklung einen großen Monitor mit mindestens Full HD Auflösung bekomme.</p>
<p>Und natürlich sollte der Rechner nicht gerade langsam sein. Da ich immer mehrere Applikationen parallel nutze die auch gleichzeitig Rechenpower benötigen, waren 4 Cores ein Wunsch. An Speicher soll es wenn möglich auch nicht scheitern und schnelles WLAN wäre toll…</p>
<p>Und da wird klar: Diese Wünsche deuten klar auf eine ‚Workstation‘ hin, aber dieses Preissegment (1.000€+, wenn nicht sogar schnell 2.000€+) wollte ich eigentlich nicht betreten, so dass ich mich nach Alternativen umgesehen habe.</p>
<p>Eine Workstation, welche schon ein paar Jahre Dienst geleistet hat, könnte eine Lösung sein, so dass ich mich bei <a
class="gblog-markdown__link"
href="http://www.itsco.de"
>ITSCO</a> etwas umgesehen habe. Hier fand ich ein HP ZBook 15 G3 für unter 600€, die vielversprechend aussah und dann auch näher analysiert wurde:</p>
<p>Ausstattung schien durchaus brauchbar:</p>
<ul>
<li>i7-4180 CPU</li>
<li>16GB Speicher, erweiterbar auf 32GB (DDR3L SDRAM)</li>
<li>512GB SSD</li>
<li>15,6″ FHD Display</li>
<li>NVIDIA Quadro K2100M Optimus mit 2 GB</li>
</ul>
<p>Die Performance der CPU habe ich mir noch etwas mehr im Detail angesehen und habe mir Tests angesehen bezüglich Geschwindigkeit. Die ältere i7 CPU hat hier bei Single Thread Performance gut mithalten können und bei Multi Thread Performance ging die quad-core CPU wie zu erwarten war, deutlich in Führung gegenüber der neuen dual-core i5 CPU.</p>
<p>Der Datendurchsatz ist aber bei der i5 CPU in der Regel höher. Das war aber auch zu erwarten, denn auch die Speichertechnologie hat sich weiter entwickelt. Die neuen, eher günstigen Notebooks mit i5 CPU nutzen hier aber die Möglichkeiten auch nicht voll aus, so dass der Unterschied auch nicht so groß ist.</p>
<p>Was fehlt, ist natürlich schnelles WLAN. Das verbaute Modul bietet die damals gute Leistung, aber kann natürlich die aktuellen Standards nicht einhalten. Hier kann es dann schon interessant sein, das Gerät noch zusätzlich mit einem WLAN USB Strick wie dem Maxesla WLAN Adapter 1200Mbps zu erweitern.</p>
<p>Als nette Beigabe hat das Gerät statt einem optischen Laufwerk eine UMTS Karte verbaut. Da ich das Gerät auch unterwegs nutzen möchte, ist dies für mich auch sehr interessant.</p>
<p><strong>Praktische Erfahrungen</strong></p>
<p>Im praktischen Einsatz verhält sich das Gerät wie erwartet. Linux ließ sich problemlos installieren. KDE Neon habe ich auf diesem System jetzt im Einsatz und das Gerät funktioniert einwandfrei (LAN, WLAN, UMTS Modem, Power Management, ….)</p>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="links">
Links
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2019/10/01/hp-zbook-15-g3/#links" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Links" href="#links">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<ul>
<li>ITSCO <a
class="gblog-markdown__link"
href="http://www.itsco.de"
>www.itsco.de</a></li>
<li>Maxesla WLAN Adapter 1200Mbps <a
class="gblog-markdown__link"
href="https://www.amazon.de/gp/product/B07RWX3LFS"
>https://www.amazon.de/gp/product/B07RWX3LFS</a></li>
</ul>
Helligkeit des Bildschirms steuernhttps://blog.kneitzel.de/2019/10/01/helligkeit-des-bildschirms-steuern/2019-10-01T06:57:28+00:002023-01-19T22:51:40+01:00
<p>Die Helligkeit des Bildschirms kann man über die Einstellungen manuell anpassen oder auch automatisch anpassen lassen.</p>
<p>Leider funktioniert dies mit Deepin bei meinem Apple MacBook Air nicht ganz so gut, so dass ich öfters die Helligkeit von Hand einstellen möchte.</p>
<p>Mit der Maus ist dies zwar problemlos möglich, aber von der Bedienung her nicht immer ganz handlich. Da ich aber immer auch ein Terminal offen habe, habe ich mich nach einer Lösung für die Kommandozeile umgesehen.</p>
<p>Das Tool xrandr kann die Helligkeit einstellen. Ein einfacher Aufruf von xrandr zeigt erst einmal alle vorhandenen Monitore an incl. der Information, ob diese angeschlossen sind oder nicht und welche Modi unterstützt werden. Für die Einstellung benötigen wir den Namen des aktiven Monitors, daher schauen wir nach der Zeile mit „connected primary“.</p>
<p>Die Helligkeit lässt sich nun mit einem Aufruf</p>
<p>xrandr –output <Name> –brightness <Level></p>
<p>einstellen. <Name> ersetzen wir durch den Namen des Monitors und <Level> mit der Helligkeit. 0 ist dabei komplett dunkel und 1 ganz hell.</p>
<p>Damit ist die Helligkeit mit einem einfachen Befehl anpassen kann, habe ich mir kleine Scripte geschrieben, die ich mit einem Befehl aufrufen kann, z.B.:</p>
<pre tabindex="0"><code>#!/bin/sh<br></br># Sets the bightness of active monitor to 1<br></br>#<br></br>monitor=`xrandr -q | grep "connected primary" | awk '{ print $1 }'`<br></br>xrandr --output $monitor --brightness 0.7
</code></pre><p>So habe ich mir kleine Scripte geschrieben für low, medium und high Einstellungen.</p>
Aktueller Kernel für Deepinhttps://blog.kneitzel.de/2019/08/12/aktueller-kernel-fuer-deepin/2019-08-12T13:09:37+00:002023-01-19T22:51:40+01:00
<p>Der Eine oder Andere, der Deepin nutzt, spielt evtl. mit dem Gedanken, einen neuen 5er Kernel für sein System zu besorgen. Deepin 15.11 nutzt derzeit noch den Kernel 4.15 und es den 5er Kernel gibt es schon eine gewisse Zeit und bringt evtl. das eine oder andere Feature mit, das für einen interessant ist.</p>
<p><span style="color: #000080;">Hinweis: Der 4er Kernel wird natürlich auch weiter gepflegt! Es ist also kein Zeichen für ein Sicherheitsrisiko, dass diverse Distributionen noch auf einen 4er Kernel setzen! Wenn alles funktioniert, dann gibt es in der Regel keinen Grund für irgendwelche Experimente oder Aktionen!</span></p>
<p>Es gibt mehrere Möglichkeiten, wie man an den neuen Kernel kommen kann.</p>
<ol>
<li>Es gibt ein neues Tool: Deepin Kernel Updater, mit dem auch etwas unbedarfte Nutzer schnell und einfach an einen neuen Linux Kernel kommen können (Achtung: Derzeit noch in der Beta Phase!) Dies ist ein einfacher und schneller Weg zum 5er Kernel.</li>
<li>In dem <a
class="gblog-markdown__link"
href="https://bbs.deepin.org/forum.php?mod=forumdisplay&fid=70"
>internationalen Deepin Forum</a> finden sich oft Threads zu neuen Kerneln, teilweise stellen Anwender den von Ihnen gebauten Kernel dort auch bereit. Wobei dies durch den neuen Deepin Kernel Updater wohl Vergangenheit sein müsste.</li>
<li>Es ist natürlich möglich, den aktuellen Linux Kernel von Debian sid zu verwenden. Wenn die sid Repositories eingebunden sind, dann lässt sich z.B. aktuell der Kernel 5.2.0 mit einem einfachen Aufruf installieren:<br>
sudo apt-get -t sid install linux-image-amd64</li>
<li>Eine letzte Variante ist die eigene Übersetzung des aktuellen Linux Kernels. Dies bedeutet aber einiges an Aufwand und Geduld. Falls aber bestimmte Dinge benötigt werden, die in den bereitgestellten Paketen nicht enthalten sind, dann ist dies oft die letzte Möglichkeit.</li>
</ol>
<p><strong>Im Folgenden beschäftige ich mich mit dem manuellen Übersetzen eines aktuellen Kernels auf einem Deepin System.</strong></p>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="vorarbeiten">
Vorarbeiten
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2019/08/12/aktueller-kernel-fuer-deepin/#vorarbeiten" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Vorarbeiten" href="#vorarbeiten">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Als erster müssen wir die notwendigen Pakete installieren:</p>
<p>apt-get install libncurses-dev wget bzip2 make build-essential bc chrpath gawk texinfo libsdl1.2-dev whiptail diffstat cpio libssl-dev flex bison libelf-dev libssl-dev libncurses5-dev qt4-default qt4-dev-tools</p>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="herunterladen-und-entpacken-der-linux-kernel-sources">
Herunterladen und Entpacken der Linux Kernel Sources
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2019/08/12/aktueller-kernel-fuer-deepin/#herunterladen-und-entpacken-der-linux-kernel-sources" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Herunterladen und Entpacken der Linux Kernel Sources" href="#herunterladen-und-entpacken-der-linux-kernel-sources">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Der Linux Kernel kann unter <a
class="gblog-markdown__link"
href="https://www.kernel.org/"
>https://www.kernel.org/</a> herunter geladen werden. Dazu einfach den tarball des gewünschten Kernels herunter laden.</p>
<p>Nun entpacken wir den Kernel an einem geeigneten Ort. Dies kann z.B. mit folgendem Befehl erfolgen</p>
<pre tabindex="0"><code><pre class="wp-block-verse">tar xf ~/Downloads/linux-5.2.8.tar.xz<br></br>cd linux-5.2.8
</code></pre><p>Nun kopieren wir die aktuelle Konfiguration des Kernels, den wir im Einsatz haben:</p>
<pre tabindex="0"><code><pre class="wp-block-verse">cp /boot/config-```
`uname -r
```` .config<br></br>
</code></pre><p>Anpassung der Konfiguration</p>
<p>Nun müssen wir die Konfiguration anpassen. Wir müssen mindestens einmal ein</p>
<pre tabindex="0"><code><pre class="wp-block-verse">make oldconfig
</code></pre><p>laufen lassen um die Einstellungen, welche neu zu der eingespielten Konfiguration sind, vornehmen zu können. Wer hier die ganzen Optionen nicht durchgehen möchte, kann einfach ein</p>
<pre tabindex="0"><code><pre class="wp-block-verse">yes "" | make oldconfig
</code></pre><p>laufen lassen.</p>
<p>Eine individuelle Einstellung diverser Einstellungen kann man mit einem der folgenden Befehle vornehmen:</p>
<pre tabindex="0"><code><pre class="wp-block-verse">make config<br></br>make menuconfig<br></br>make xconfig
</code></pre><p>Ich selbst rate zu make menuconfig oder make config, da diese am intuitivsten zu bedienen sind.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="übersetzen-des-kernels">
Übersetzen des Kernels
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2019/08/12/aktueller-kernel-fuer-deepin/#übersetzen-des-kernels" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Übersetzen des Kernels" href="#%c3%bcbersetzen-des-kernels">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Als nächstes übersetzen wir den Kernel. Da hier sehr viele einzelne Dateien zu übersetzen sind, macht es Sinn, make anzuweisen, mehrere Dateien parallel zu übersetzen. Dazu dient der Parameter -j<x> wobei x für die Anzahl der parallelen Übersetzungen steht, z.B. -j4 für 4 parallele Übersetzungen.</p>
<p><strong>Übersetzen des Kernels</strong></p>
<pre tabindex="0"><code><pre class="wp-block-verse">make -j4 bzImage modules<br></br>
</code></pre><p><strong>Bau von Debian Paketen</strong> (diese finden sich dann im Anschluss ein Verzeichnis höher)</p>
<pre tabindex="0"><code><pre class="wp-block-verse">make -j4 pkg-deb
</code></pre><div class="gblog-post__anchorwrap flex align-center">
<h2 id="installation-des-compilierten-kernels">
Installation des compilierten Kernels
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2019/08/12/aktueller-kernel-fuer-deepin/#installation-des-compilierten-kernels" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Installation des compilierten Kernels" href="#installation-des-compilierten-kernels">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Die Installation kann man nun direkt von den Sourcen aus anstoßen:</p>
<pre tabindex="0"><code><pre class="wp-block-verse">sudo make install install-modules
</code></pre><p>Alternativ lassen sich die erstellten Debian Pakete nutzen (Dies ist der von mir empfohlene Weg!):</p>
<pre tabindex="0"><code><pre class="wp-block-verse">cd ..<br></br>sudo dpkg -i ../
</code></pre><p>Nun noch den Bootloader grub aktualisieren und das System neu starten</p>
<pre tabindex="0"><code><pre class="wp-block-verse">sudo update-grub<br></br>sudo reboot
</code></pre><div class="gblog-post__anchorwrap flex align-center">
<h2 id="links">
Links
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2019/08/12/aktueller-kernel-fuer-deepin/#links" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Links" href="#links">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<ul>
<li>
<p>Deepin Kernel Updater<br>
Der Deepin Kernel Updater scheint nicht mehr so zur Verfügung zu stehen. Statt dessen hat der Autor nun ein repository, welches man einbinden kann:</p>
<ul>
<li><img
src="https://blog.kneitzel.de/wp-content/uploads/2019/07/Flagge-England-klein.png"
alt=""
/> <a
class="gblog-markdown__link"
href="https://lvtommy.tk/repo-easily-install-my-repository/"
>https://lvtommy.tk/repo-easily-install-my-repository/</a></li>
</ul>
</li>
<li>
<p><img
src="https://blog.kneitzel.de/wp-content/uploads/2019/07/Flagge-England-klein.png"
alt=""
/> Deepin Forum: <a
class="gblog-markdown__link"
href="https://bbs.deepin.org/forum.php?mod=forumdisplay&fid=70"
>https://bbs.deepin.org/forum.php?mod=forumdisplay&fid=70</a></p>
</li>
<li>
<p><img
src="https://blog.kneitzel.de/wp-content/uploads/2019/07/Flagge-Deutschland-klein.png"
alt=""
/> Debian Pakete unter Deepin nutzen: <a
class="gblog-markdown__link"
href="https://blog.kneitzel.de/2019/08/11/deepin-mit-debian-repositories-nutzen/"
>https://blog.kneitzel.de/2019/08/11/deepin-mit-debian-repositories-nutzen/</a></p>
</li>
<li>
<p><img
src="https://blog.kneitzel.de/wp-content/uploads/2019/07/Flagge-Deutschland-klein.png"
alt=""
/> Neuen Kernel für Debian bauen: <a
class="gblog-markdown__link"
href="https://phoenix-blog.de/2018/12/13/einen-neuen-kernel-fuer-debian-9-strech-kompilieren/"
>https://phoenix-blog.de/2018/12/13/einen-neuen-kernel-fuer-debian-9-strech-kompilieren/</a></p>
</li>
<li>
<p><img
src="https://blog.kneitzel.de/wp-content/uploads/2019/07/Flagge-England-klein.png"
alt=""
/> Linux Kernel: <a
class="gblog-markdown__link"
href="https://www.kernel.org/"
>https://www.kernel.org/</a></p>
</li>
</ul>
AnyDesk – Aktuelle Linux-Version bei angepasstem Clienthttps://blog.kneitzel.de/2019/08/11/anydesk-aktuelle-custom-linux-version/2019-08-11T13:00:21+00:002023-01-19T22:51:40+01:00
<p>Ich bin Nutzer der Software <a
class="gblog-markdown__link"
href="https://anydesk.com/de"
>AnyDesk</a> in der Professional Edition. Ein mir wichtiges Feature ist die Bereitstellung von angepassten Installern: Neben dem eigenen Logo lassen sich diverse Einstellungen fest vorgeben.</p>
<p>Leider hinkt <a
class="gblog-markdown__link"
href="https://anydesk.com/de"
>AnyDesk</a> hier bei der Linux Version etwas hinterher, was ich schade finde. So gibt es den angepassten Client für Linux nur in der Version 4.0.1 was dazu führt, dass der Client natürlich beim Start feststellt, dass er nicht aktuell ist. Aktuell ist die Version 5.1.1.</p>
<p>Um so erfreuter war ich, als meine Anfrage an den Support in sehr kurzer Zeit beantwortet wurde und mir einen Workaround mitgeteilt wurde:</p>
<p>In den erweiterten Einstellung kann man das Modul, welches in das Paket hinein soll, angeben:<br>
_module=anydesk-5.1.1</p>
<figure class="wp-block-image">![](https://blog.kneitzel.de/wp-content/uploads/2019/08/DeepinBildschirmfoto_Bereich-auswählen_20190811145225.png)<figcaption>Eintrag des zu verwendenden Moduls bei Erweitert</figcaption></figure>Und schon erhält man ein komprimiertes tar Archiv mit der angepassten AnyDesk Software.
<p>Dies ist natürlich noch nicht perfekt. Ein Vorteil war ja, dass man einen öffentlichen Link erzeugen konnte, über den Kunden immer die aktuelle Version herunter laden konnten. Aber diese Anforderung ist für mich nicht relevant, so dass ich mal wieder voll und ganz zufrieden bin.</p>
<p>Und AnyDesk arbeitet auch an dieser Thematik – So hoffe ich, dass ich in naher Zukunft dann auch individuelle Installer als deb oder rpm herunter laden kann (In meinen Augen auch positiv, dass hier Pakete gebaut werden und nicht irgendwelche Binary Installer erzeugt werden die man dann aufrufen muss!)</p>
<p><strong>Edit 1. Oktober 2019</strong>: Dieses Vorgehen scheint nicht mehr notwendig zu sein. Zumindest konnte ich nun auch die aktuelle Version 5.1.2 ohne diesen Workaround als angepasste Version herunter laden.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="links">
Links
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2019/08/11/anydesk-aktuelle-custom-linux-version/#links" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Links" href="#links">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<ul>
<li><img
src="https://blog.kneitzel.de/wp-content/uploads/2019/07/Flagge-Deutschland-klein.png"
alt=""
/> AnyDesk Homepage: <a
class="gblog-markdown__link"
href="https://anydesk.com/de"
>https://anydesk.com/de</a></li>
</ul>
Deepin mit Debian Repositories nutzenhttps://blog.kneitzel.de/2019/08/11/deepin-mit-debian-repositories-nutzen/2019-08-11T10:44:41+00:002023-01-19T22:51:40+01:00
<p>Die Deepin 15.x Distribution basiert auf Debian, auf Debian sid (unstable) um genau zu sein. Wenn einem nun irgendeine Software in Deepin fehlt, diese aber bei Debian sid vorhanden ist, dann liegt es nahe, diese von den Debian Repositories zu beziehen.</p>
<p>Ehe wir uns aber Software aus einer weiteren Quelle beziehen sollten wir uns genau überlegen, was für Probleme wir uns damit eventuell einhandeln könnten:</p>
<ul>
<li>Wenn Deepin Pakete von Debian erneuert werden, dann kann es passieren, dass Paketabhängigkeiten nicht mehr richtig funktionieren.</li>
<li>Pakete von Debian sid/unstable sind weniger getestet. Hier findet die Hauptarbeit an der Distribution statt und die Pakete wandern dann nach erfolgreichem Einsatz in die Testing Distribution ehe sie dann in einem stabilen Release landen.</li>
<li>Das Security Team von Debian kümmert sich in unstable nicht um Security Fixe. Daher kann es sein, dass notwendige Sicherheitspatche erst verzögert in sid/unstable landen.</li>
</ul>
<p>Aus diesen Gründen ist die klare Empfehlung, dass wir bei Software doch am Besten bei der Software der Deepin Distribution bleiben und nur fehlende Stücke von den Debian Repositories installieren. Dies lässt sich über ein „Apt Package Pininning“ (oder kurz Apt Pinning) erreichen.</p>
<p><strong>Konfiguration</strong><br>
Als erstes fügen wir das Repository von Debian hinzu:<br>
Dazu erstellen wir die Datei /etc/apt/sources.list.d/debian.list mit folgendem Inhalt:</p>
<pre tabindex="0"><code><pre class="wp-block-preformatted">deb http://ftp.debian.org/debian sid main contrib non-free<br></br>deb-src http://ftp.debian.org/debian sid main contrib non-free
</code></pre><p>Nun setzen wir die Prioritäten (Apt-Pinning). Dazu erstellen wir die Datei /etc/apt/preferences mit folgendem Inhalt:</p>
<pre tabindex="0"><code><pre class="wp-block-verse"># Deepin Package Pinning<br></br>Package: *<br></br>Pin: release o=Linux Deepin<br></br>Pin-Priority: 990
</code></pre><p>Die Prioritäten können wir nach einem „sudo apt-get update“ nun per „sudo apt policy“ prüfen. Der Befehl sollte uns nun die Policies aufzeigen:</p>
<ul>
<li>Prio 100 für /var/lib/dpkg/status</li>
<li>Prio 500 für debian repositories (mehrere)</li>
<li>Prio 990 für deepin repositories (mehrere)</li>
</ul>
<p>Nun steht einer Nutzung nichts mehr im Wege. wir synchronisieren erst einmal unsere apt datenbank mit den Repositories: apt update</p>
<p>Nun können wir ein Paket von den Debian Repositories installieren oder das installierte Paket von dort updaten:<br>
apt-get -t sid install libreoffice</p>
<p>(um z.B. libreoffice von Debian zu installieren oder auf die Debian Version upzugraden)</p>
<p><strong>Links</strong></p>
<ul>
<li><img
src="https://blog.kneitzel.de/wp-content/uploads/2019/07/Flagge-England-klein.png"
alt=""
/>Deepin Forum zur Nutzung von Debian Repositories: <a
class="gblog-markdown__link"
href="https://bbs.deepin.org/forum.php?mod=viewthread&tid=130778"
>https://bbs.deepin.org/forum.php?mod=viewthread&tid=130778</a></li>
<li><img
src="https://blog.kneitzel.de/wp-content/uploads/2019/07/Flagge-England-klein.png"
alt=""
/>Apt Pinning im Debian Wiki: <a
class="gblog-markdown__link"
href="https://wiki.debian.org/AptPreferences"
>https://wiki.debian.org/AptPreferences</a></li>
</ul>
O2 Surfstick 3 mit Deepinhttps://blog.kneitzel.de/2019/07/16/o2-surfstick-3-mit-deepin/2019-07-16T11:31:13+00:002023-01-19T22:51:40+01:00
<p><span style="color: #000080;">Editiert am 12. August 2019: Die Einrichtung der Breitband-Verbindung wurde noch im Detail beschrieben.</span></p>
<p>Ich habe noch zwei ältere USB HSDPA Datensticks (O2 Surfstick 3 und Huawei E1550), welche unter Linux immer problemlos funktioniert haben. Linux erkennt diese und der Netzwerk Manager übernimmt dann die weitere Benutzung (also PIN Abfrage und dann der Verbindungsaufbau).</p>
<p>Leider wird dies vom Deepin Netzwerkmanager (noch) nicht unterstützt. Als Workaround kann ein anderer Netzwerkmanager zusätzlich installiert werden.</p>
<p>Meine Wahl ist auf den Betzwerkmanager von Gnome gefallen, welcher über:</p>
<pre tabindex="0"><code><pre class="wp-block-verse">sudo apt-get install network-manager-gnome
</code></pre><p>installiert werden kann. Nach einer Neuanmeldung findet dieser sich dann in der Taskleiste neben Batterie, Lautstärke, u.s.w. und wir können das Netzwerk nun zusätzlich über diesen Netzwerkmanager steuern.</p>
<p>Auch ohne Neustart lässt sich die Applikation im Menü unter System -> Advanced Network Configuration finden und starten.</p>
<div class="gblog-post__anchorwrap flex align-center">
<h2 id="einrichtung-des-sticks">
Einrichtung des Sticks
</h2>
<a data-clipboard-text="https://blog.kneitzel.de/2019/07/16/o2-surfstick-3-mit-deepin/#einrichtung-des-sticks" class="gblog-post__anchor clip flex align-center" aria-label="Anchor Einrichtung des Sticks" href="#einrichtung-des-sticks">
<svg class="gblog-icon gblog_link"><use xlink:href="#gblog_link"></use></svg>
</a>
</div>
<p>Die Einrichtung hängt nun natürlich sowohl von der Hardware als auch vom Provider ab. Ablauf ist aber wie folgt:</p>
<p>a) Start der Applikation Advanced Network Configuration und das „+“ drücken:</p>
<figure class="wp-block-image">![](https://blog.kneitzel.de/wp-content/uploads/2019/08/DeepinBildschirmfoto_Bereich-auswählen_20190812152735.png)</figure>Nun wählen wir „Mobiles Breitband“ aus:
<figure class="wp-block-image">![](https://blog.kneitzel.de/wp-content/uploads/2019/08/DeepinBildschirmfoto_Bereich-auswählen_20190812153021.png)</figure>Und wählen im Anschluss die (vorher eingesteckte!) Hardware aus:
<figure class="wp-block-image">![](https://blog.kneitzel.de/wp-content/uploads/2019/08/DeepinBildschirmfoto_Bereich-auswählen_20190812153152.png)</figure>Im weiteren Verlauf werden wir nach einigen weiteren Informationen abgefragt, die von Provider zu Provider unterschiedlich sind. Bei mir war mein Provider zwar aufgelistet, aber der Abrechnungsmodus war nicht angegeben, so dass ich den APN von Hand eingegeben habe.
Am Ende wurde die Verbindung angelegt:
<figure class="wp-block-image">![](https://blog.kneitzel.de/wp-content/uploads/2019/08/DeepinBildschirmfoto_Bereich-auswählen_20190812153823.png)</figure>Hier habe ich lediglich den Verbindungsnamen angepasst. Es ließe sich aber noch sehr viel mehr einstellen, was aber für mich nicht notwendig war.
<p>So auf ein Neustart verzichtet wurde, so wird dieser vor der Nutzung des Sticks noch notwendig. Das Network Manager Applet lässt sich zwar per nm-applet starten, der Stick wird gesehen und es wird auch nach der Pin gefragt:</p>
<figure class="wp-block-image">![](https://blog.kneitzel.de/wp-content/uploads/2019/08/DeepinBildschirmfoto_Bereich-auswählen_20190812154146.png)</figure>Und in der Status-Leiste sieht man nun neben dem Deepin Network Manager auch den Gnome Network Manager:
<figure class="wp-block-image">![](https://blog.kneitzel.de/wp-content/uploads/2019/08/DeepinBildschirmfoto_Bereich-auswählen_20190812154948.png)</figure>Im roten Kreis ist der Gnome Network Manager zu sehen und im blauen Kreis der von Deepin. Somit hat man nun leider zwei Symbole in der Leiste. (Bei meinem Bild sieht man die Symbole mit einer verbundenen Ethernetverbindung.)
Deepinhttps://blog.kneitzel.de/2019/07/16/deepin/2019-07-16T09:35:13+00:002023-01-19T22:51:40+01:00
<p><strong>Was ist <a
class="gblog-markdown__link"
href="https://www.deepin.org/en/"
>Deepin</a>?</strong><br>
Deepin ist eine Linux Distribution aus China, welche auf Debian basiert und vor allem einige UI Komponenten mitbringt. Hinter der Distribution steckt die chinesische Firma Deepin Technology Co., Ltd.</p>
<p><strong>Was macht Deepin aus?</strong> Deepin bringt das Deepin Desktop Environment, welches aus meiner Sicht eine sehr gute Bedienung mit sich bringt – derzeit aus meiner Sicht die Beste Desktop-Lösung unter Linux.</p>
<p>Besonders interessant ist die Konfiguration, welche sich an der rechten Seite als Leiste öffnet.</p>
<p><strong>Wie komme ich zu Deepin?</strong><br>
In letzter Zeit sind einige, sehr kleine Geräte auf den Markt gekommen. One Mix 3S Yoga, Chuwi Minibook, GPD P2 Max, …) die ich als späteren Ersatz für mein älteres Apple MacBook Air 11″ ansehe. Und da kommen dann auch teilweise Touch Displays zum Einsatz, so dass ich schon nach einer Linux Distribution gesucht habe, die ich dann auch diesbezüglich nutzen kann. Und auch in dem Bereich scheint Deepin mit am weitesten zu sein…</p>
<p><strong>Mein bisheriges Fazit</strong> Deepin ist schon eine sehr gute und ausgereifte Distribution. Die Oberfläche lässt sich sehr gut bedienen und das Meiste war intuitiv nutzbar. Nur wenige Dinge musste ich kurz suchen (z.B. die Konfiguration von aktiven Ecken).</p>
<p>Somit wird das erst einmal meine bevorzugte Distribution, welche ich für meine Zwecke einsetzen werde und über die ich in Zukunft noch ein paar weitere Beiträge schreiben werde.</p>
<p><strong>Links</strong></p>
<ul>
<li><img
src="/wp-content/uploads/2019/07/Flagge-England-klein.png"
alt=""
/>Deepin Homepage (Englisch): <a
class="gblog-markdown__link"
href="https://www.deepin.org/en/"
>https://www.deepin.org/en/</a></li>
<li><img
src="/wp-content/uploads/2019/07/Flagge-Deutschland-klein.png"
alt=""
/>Deepin Homepage (Deutsch, wenig aktualisiert): <a
class="gblog-markdown__link"
href="https://www.deepin.org/de/"
>https://www.deepin.org/de/</a></li>
</ul>
Linux Installation in VM und nativehttps://blog.kneitzel.de/2019/07/16/linux-installation-in-vm-und-native/2019-07-16T08:37:55+00:002023-01-19T22:51:40+01:00
<p>Es kann interessant sein, wenn man auf einem System das Linux sowohl in einer VM (z.B. unter Windows mit VMware Workstation) als auch direkt booten kann. Zum direkten Starten der Linux VM verwende ich einen einfachen USB Stick, den ich in den Rechner stecken kann.</p>
<p><strong>Aufbau</strong><br>
Ein System mit zwei Festplatten, so nutze ich einen Lenovo Laptop mit einer zweiten Festplatte.</p>
<p>Auf der ersten Festplatte wird Windows in der Regel bereits installiert sein, so dass wir als nächsten Schritt VMware Workstation installieren und dann eine VM einrichten:</p>
<ul>
<li>Bei der VM ist wichtig, dass wir die zweite Festplatte als physikalische Festplatte übergeben.</li>
</ul>
<p>Die Installation der Linux Distribution (ich habe Debian genutzt) erfolgt dann ohne Besonderheiten. Bei der Installation kann die zweite Festplatte wie gewünscht partitioniert und genutzt werden.</p>
<p>Nach der Installation sollten wir noch die open-vm-tools installieren und schon haben wir unsere Linux VM fertig zur Benutzung.</p>
<p>Nun benötigen wir einen USB Stick, welchen wir anschließen und in VMware Workstation der laufenden Linux VM zuweisen. Diese sollte den USB Stick erkennen, so dass wir das Gerät nutzen können. (Falls wir den Device Namen nicht kennen, dann einfach per „sudo dmesg“ oder „lsblk“ nachschauen.)</p>
<p><strong>Formatieren des USB Sticks</strong><br>
Der USB Stick wird im MBR Format formatiert und eine erste Partition für ein FAT Filesystem erzeugt. Dieser Partition setzen wir noch das boot Flag. Im Anschluss formatieren wir die Partition mittels mkfs.msdos.</p>
<p><strong>Syslinux</strong><br>
Wir installieren das Paket syslinux und bereiten den Stick für das booten vor:</p>
<ul>
<li>Wir schreiben den bei syslinux mitgelieferten mbr auf den Stick<br>
dd conv=notrunc bs=440 count=1 if=mbr.bin of=/dev/sdX<br>
(Die datei mbr.bin findet sich bei Debian unter /usr/lib/syslinux/…)</li>
<li>Wir prüfen noch einmal das boot Flag der ersten Partition.</li>
<li>Wir schreiben notwendige Dateien auf die Partition:<br>
syslinux –install /dev/sdX1</li>
</ul>
<p>Nun kopieren wir aus /boot die Dateien<br>
– inird.img.*<br>
– vmlinuz-*<br>
auf die Partition des Sticks und legen dort die Datei syslinux.cfg mit folgendem Inhalt an:</p>
<p>DEFAULT linux<br>
TIMEOUT 1<br>
LABEL linux<br>
KERNEL vmlinuz-<rest of filename><br>
APPEND ro root=UUID=<UUID of root device><br>
initrd=initrd.img-<rest of filename></p>
<p>Dabei ist natürlich zu ersetzen:<br>
– <rest of filename> mit dem exakten Namen der initrd/vmlinuz files.<br>
– <UUID of root device> mit der UUID der root Partition. Diese sollte auch in der /etc/fstab stehen oder kann mit blkid ermittelt werden.</p>
<p>Hinweis: Wenn in der /etc/fstab Partitionen noch mit /dev/sdXY angegeben wurden, so empfehle ich, diese auch durch die UUID zu ersetzen!</p>
<p><strong>Links</strong></p>
<ul>
<li><img
src="https://blog.kneitzel.de/wp-content/uploads/2019/07/Flagge-England-klein.png"
alt=""
/> Syslinux Wiki – HowTos: <a
class="gblog-markdown__link"
href="https://wiki.syslinux.org/wiki/index.php?title=HowTos"
>https://wiki.syslinux.org/wiki/index.php?title=HowTos</a></li>
</ul>