JavaFX Freezes beim Zeichnen mit Canvas

Hauf3n

Mitglied
Hallo zusammen!

4 Mitstreiter und ich müssen einen Terraria Klon mithilfe von JavaFX programmieren.
Leider haben wir ein Problem beim Zeichnen mit dem Canvas/Graphicscontext.

Wir haben das Zeichnen(2D) durch eine verschachtelte Schleife realisiert, die ein Array ausließt
und dann anhand der Informationen gewisse 16x16 große Rechtecke an den richtigen
Positionen zeichnet. Also wird in unserer Gameloop das Canvas übermalt und dann werden die
Rechtecke gezeichnet und die Gameloop beginnt von vorne(Logik ist erstmal egal). Irgendwann kommt dann der Moment, an dem nichts mehr gezeichnet wird. Das Innere des Fenster wird nicht mehr aktualisiert, jedoch läuft der
Thread immer noch weiter und man erhält keine Fehlermeldung.

Ich konnte das Problem recht weit von unserem Projekt distanzieren, und hab dazu ein sehr kleines Programm geschrieben, bei dem genau der selbe Fehler auftritt.

Java:
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.stage.Stage;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Created by on 14.05.2015.
 */
public class Main extends Application {

    private Canvas canvas = new Canvas(800,600);
    private GraphicsContext gc = canvas.getGraphicsContext2D();
    private Group group = new Group();
    private Scene scene = new Scene(group);
    private ExecutorService ex = Executors.newSingleThreadExecutor();


    public static void main(String[] args){
        launch(args);
    }

    @Override
    public void start(Stage stage){
        group.getChildren().add(canvas);
        stage.setScene(scene);
        stage.sizeToScene();
        stage.show();

        //threadgameloop
        ex.execute(() -> {
            long before = System.currentTimeMillis(), now, sleep;
            while(true){
                //clear canvas
                gc.clearRect(0,0,800,600);

                //rendersimulation
                for(int i=0; i<50; i++){
                    for(int j=0; j<38; j++){
                        gc.fillRect(i*16,j*16,16,16);
                    }
                }
                //thread sleep
                now = System.currentTimeMillis();
                sleep = Math.max(0, 40 - (now - before));
                try {
                    System.out.println("Thread sleeps: "+sleep+"ms");
                    Thread.sleep(sleep);
                } catch (InterruptedException ignored) {}

                before = System.currentTimeMillis();
            }
        });

    }
}

Programm muss man leider mit dem Taskmanager beenden. :oops:
Das Programm zeichnet einfach den ganzen Bildschirm voll mit 16x16 großen, schwarzen Rechtecken(also wenns läuft dann ist das ganze Fenster schwarz) und übermalt sie dann wieder. Es ist immer unterschiedlich, wann das Programm freezt. Bei mir sieht es dann nach kurzer Zeit zB so aus. Ich benutze Java 8 45u, falls es benötigt wird.

javafx.png

Ich nehme auch gerne andere Zeichnungstechniken mit JavaFX entgegen! Man muss bloß jeden Pixel ansprechen können. :D
Ich freue mich auf Eure Antworten! :)
Mfg
 

top_chief

Mitglied
Hallo, schau mal wie das hier realisiert wurde:
Code:
/**
 * Copyright (c) 2008, 2012 Oracle and/or its affiliates.
 * All rights reserved. Use is subject to license terms.
 */
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.animation.Timeline;
import javafx.scene.Group;
import javafx.scene.effect.BlendMode;
import javafx.scene.effect.BoxBlur;
import javafx.scene.paint.Color;
import javafx.scene.paint.CycleMethod;
import javafx.scene.paint.LinearGradient;
import javafx.scene.paint.Stop;
import javafx.scene.shape.Circle;
import java.util.ArrayList;
import java.util.List;
import java.util.Iterator;
import javafx.animation.*;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.effect.Reflection;
import javafx.scene.image.ImageView;
import javafx.scene.layout.Pane;
import javafx.scene.paint.*;

/**
 * A sample that demonstrates how to draw and paint shapes, apply visual
 * effects, blend colors in overlapping objects, and animate objects.
 *
 * @see javafx.scene.canvas.Canvas
 * @see javafx.scene.canvas.GraphicsContext
 * @see javafx.scene.effect.BlendMode
 * @see javafx.scene.effect.BoxBlur
 * @see javafx.scene.shape.Circle
 * @see javafx.scene.Group
 * @see javafx.scene.paint.LinearGradient
 * @see javafx.animation.Timeline
 */
public class FireworksSample extends Application {
    private final SanFranciscoFireworks sanFranciscoFireworks = new SanFranciscoFireworks();
    
    private void init(Stage primaryStage) {
        Group root = new Group();
        primaryStage.setScene(new Scene(root));
        root.getChildren().add(sanFranciscoFireworks);
    }

    @Override public void stop() {
        sanFranciscoFireworks.stop();
    }

    public void play() {
        sanFranciscoFireworks.start();
    }
    
    public static class SanFranciscoFireworks extends Pane {
        private final AnimationTimer timer;
        private final Canvas canvas;
        private final ImageView background;
        private final List<Particle> particles = new ArrayList<Particle>();
        private final Paint[] colors;
        private int countDownTillNextFirework = 40;
        
        public SanFranciscoFireworks() {
            // create a color palette of 180 colors
            colors = new Paint[181];
            colors[0] = new RadialGradient(0, 0, 0.5, 0.5, 0.5, true, CycleMethod.NO_CYCLE, 
                        new Stop(0, Color.WHITE),
                        new Stop(0.2, Color.hsb(59, 0.38, 1)),
                        new Stop(0.6, Color.hsb(59, 0.38, 1,0.1)),
                        new Stop(1, Color.hsb(59, 0.38, 1,0))
                        );
            for (int h=0;h<360;h+=2) {
                colors[1+(h/2)] = new RadialGradient(0, 0, 0.5, 0.5, 0.5, true, CycleMethod.NO_CYCLE, 
                        new Stop(0, Color.WHITE),
                        new Stop(0.2, Color.hsb(h, 1, 1)),
                        new Stop(0.6, Color.hsb(h, 1, 1,0.1)),
                        new Stop(1, Color.hsb(h, 1, 1,0))
                        );
            }
            // create canvas
            canvas = new Canvas(1024, 500);

            canvas.setBlendMode(BlendMode.ADD);
            canvas.setEffect(new Reflection(0,0.4,0.15,0));
            background = new ImageView(getClass().getResource("sf.jpg").toExternalForm());
            getChildren().addAll(background,canvas);
            // create animation timer that will be called every frame
            // final AnimationTimer timer = new AnimationTimer() {
            timer = new AnimationTimer() {

                @Override public void handle(long now) {
                    GraphicsContext gc = canvas.getGraphicsContext2D();
                    // clear area with transparent black
                    gc.setFill(Color.rgb(0, 0, 0, 0.2));
                    gc.fillRect(0, 0, 1024, 708);
                    // draw fireworks
                    drawFireworks(gc);
                    // countdown to launching the next firework
                    if (countDownTillNextFirework == 0) {
                        countDownTillNextFirework = 10 + (int)(Math.random()*30);
                        fireParticle();
                    }
                    countDownTillNextFirework --;
                }
            };
        }
        
        public void start() { timer.start(); }
        public void stop() { timer.stop(); }

        /**
         * Make resizable and keep background image proportions and center.
         */
        @Override protected void layoutChildren() {
            // final double w = 480.0;
            // final double h = 360.0;
            final double w = getWidth();
            final double h = getHeight();
            final double scale = Math.min(w/1024d, h/708d);
            final int width = (int)(1024*scale);
            final int height = (int)(708*scale);
            final int x = (int)((w-width)/2);
            final int y = (int)((h-height)/2);
            background.relocate(x, y);
            background.setFitWidth(width);
            background.setFitHeight(height);
            canvas.relocate(x, y);
            canvas.setWidth(width);
            canvas.setHeight(height * 0.706);
        }
    
        private void drawFireworks(GraphicsContext gc) {
            Iterator<Particle> iter = particles.iterator();
            List<Particle> newParticles = new ArrayList<Particle>();
            while(iter.hasNext()) {
                Particle firework = iter.next();
                // if the update returns true then particle has expired
                if(firework.update()) {
                    // remove particle from those drawn
                    iter.remove();
                    // check if it should be exploded
                    if(firework.shouldExplodeChildren) {
                        if(firework.size == 9) {
                            explodeCircle(firework, newParticles);
                        } else if(firework.size == 8) {
                            explodeSmallCircle(firework, newParticles);
                        }
                    }
                }
                firework.draw(gc);
            }
            particles.addAll(newParticles);
        }
        
        private void fireParticle() {
            particles.add(new Particle(
                canvas.getWidth()*0.5, canvas.getHeight()+10,
                Math.random() * 5 - 2.5, 0, 
                0, 150 + Math.random() * 100,
                colors[0], 9,
                false, true, true));
        }


        private void explodeCircle(Particle firework, List<Particle> newParticles) {
            final int count = 20 + (int)(60*Math.random());
            final boolean shouldExplodeChildren = Math.random() > 0.5;
            final double angle = (Math.PI * 2) / count;
            final int color = (int)(Math.random()*colors.length);
            for(int i=count; i>0; i--) {
                double randomVelocity = 4 + Math.random() * 4;
                double particleAngle = i * angle;
                newParticles.add(
                    new Particle(
                        firework.posX, firework.posY, 
                        Math.cos(particleAngle) * randomVelocity, Math.sin(particleAngle) * randomVelocity,
                        0, 0, 
                        colors[color], 
                        8,
                        true, shouldExplodeChildren, true));
            }
        }

        private void explodeSmallCircle(Particle firework, List<Particle> newParticles) {
            final double angle = (Math.PI * 2) / 12;
            for(int count=12; count>0; count--) {
                double randomVelocity = 2 + Math.random() * 2;
                double particleAngle = count * angle;
                newParticles.add(
                    new Particle(
                        firework.posX, firework.posY, 
                        Math.cos(particleAngle) * randomVelocity, Math.sin(particleAngle) * randomVelocity,
                        0, 0, 
                        firework.color, 
                        4,
                        true, false, false));
            }
        }
    }


    /**
     * A Simple Particle that draws its self as a circle.
     */
    public static class Particle {
        private static final double GRAVITY = 0.06;
        // properties for animation
        // and colouring
        double alpha;
        final double easing;
        double fade;
        double posX;
        double posY;
        double velX;
        double velY;
        final double targetX;
        final double targetY;
        final Paint color;
        final int size;
        final boolean usePhysics;
        final boolean shouldExplodeChildren;
        final boolean hasTail;
        double lastPosX;
        double lastPosY;
        
        public Particle(double posX, double posY, double velX, double velY, double targetX, double targetY, 
                Paint color,int size, boolean usePhysics, boolean shouldExplodeChildren, boolean hasTail) {
            this.posX = posX;
            this.posY = posY;
            this.velX = velX;
            this.velY = velY;
            this.targetX = targetX;
            this.targetY = targetY;
            this.color = color;
            this.size = size;
            this.usePhysics = usePhysics;
            this.shouldExplodeChildren = shouldExplodeChildren;
            this.hasTail = hasTail;
            this.alpha    = 1;
            this.easing   = Math.random() * 0.02;
            this.fade     = Math.random() * 0.1;
        }

        public boolean update() {
            lastPosX = posX;
            lastPosY = posY;
            if(this.usePhysics) { // on way down
                velY += GRAVITY;
                posY += velY;
                this.alpha -= this.fade; // fade out particle
            } else { // on way up
                double distance = (targetY - posY);
                // ease the position
                posY += distance * (0.03 + easing);
                // cap to 1
                alpha = Math.min(distance * distance * 0.00005, 1);
            }
            posX += velX;
            return alpha < 0.005;
        }

        public void draw(GraphicsContext context) {
            final double x = Math.round(posX);
            final double y = Math.round(posY);
            final double xVel = (x - lastPosX) * -5;
            final double yVel = (y - lastPosY) * -5;
            // set the opacity for all drawing of this particle
            context.setGlobalAlpha(Math.random() * this.alpha);
            // draw particle
            context.setFill(color);
            context.fillOval(x-size, y-size, size+size, size+size);
            // draw the arrow triangle from where we were to where we are now
            if (hasTail) {
                context.setFill(Color.rgb(255,255,255,0.3));
                context.fillPolygon(new double[]{posX + 1.5,posX + xVel,posX - 1.5}, 
                        new double[]{posY,posY + yVel,posY}, 3);
            }
        }
    }

    @Override public void start(Stage primaryStage) throws Exception {
        init(primaryStage);
        primaryStage.show();
        play();
    }
    public static void main(String[] args) { launch(args); }
}

Aus dem Programm kann man mit Platform.exit() springen, zB wenn Escape gedrückt wurde:
Code:
scene.setOnKeyPressed(event -> {
            if (event.getCode() == KeyCode.ESCAPE) {
                mIsRunning = false;
                stage.close();
                Platform.exit();
            }
        });
 

Hauf3n

Mitglied
Hallo top_chief

Ich hab mir jetzt von deinem Codefragment ein kleines Programm geschrieben, und es läuft alles perfekt!
Werde dann wohl deine Zeichentechnik übernehmen. Danke!! LG
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
MartinNeuerlich Kann mir jemand, der einen Mac mit einem m1 oder m2-Chip hat, eine POM geben mit der Javafx-Fullscreen beim Mac mit m-Chip funktioniert? AWT, Swing, JavaFX & SWT 1
berserkerdq2 Wie greife ich auf ein Element zu, welches ich beim Scenebuilder erstellt habe AWT, Swing, JavaFX & SWT 10
H AWT Dialog Größe ändern - Schwarzer Inhalt beim groß ziehen AWT, Swing, JavaFX & SWT 1
L jComboBox Actionlistener wird beim erstmaligen Befüllen getriggert AWT, Swing, JavaFX & SWT 7
B Output GUI funktioniert nur beim ersten Mal richtig. AWT, Swing, JavaFX & SWT 4
A JavaFX exportierte Jar ohne beim starten die Libs hinzufügen? AWT, Swing, JavaFX & SWT 2
TheWhiteShadow JavaFX ListView Problem beim Entfernen von Elementen AWT, Swing, JavaFX & SWT 1
S Fehler beim Öffnen weiterer FXML AWT, Swing, JavaFX & SWT 11
I Probleme beim Drucken auf einen PDF-Drucker AWT, Swing, JavaFX & SWT 8
G Gui updated beim zweiten Aufruf nicht mehr AWT, Swing, JavaFX & SWT 15
K JavaFX Resizing-Problem beim BorderLayout (Center Component) beim Arbeiten mit mehreren FXMLs AWT, Swing, JavaFX & SWT 2
W Nullpointer Exception beim übertragen von Daten von Scene zu Scene AWT, Swing, JavaFX & SWT 6
missy72 JavaFX Wiederholen einer IF-Abfrage beim erneuten Öffnen einer Stage AWT, Swing, JavaFX & SWT 11
D JavaFX Probleme beim nachtäglichen hinzufügen der jfx dependency AWT, Swing, JavaFX & SWT 7
R NullPointerException beim Start des Fensters AWT, Swing, JavaFX & SWT 1
D JavaFX Label flackert beim aktualisieren AWT, Swing, JavaFX & SWT 12
J Kann mir jemand beim MediaPlayer helfen ? AWT, Swing, JavaFX & SWT 2
S JavaFx Zufallsfarbe beim Button-Klick AWT, Swing, JavaFX & SWT 22
L Swing JDialog ton beim klicken ausstellen AWT, Swing, JavaFX & SWT 1
sascha-sphw JavaFX ListCell höhe verändert sich beim ändern der Text-Farbe AWT, Swing, JavaFX & SWT 14
H Beim JFrame erstellen ein anderes schließen AWT, Swing, JavaFX & SWT 0
L Swing JLabel wird beim ändern der Schriftart immer neu gezeichnet. AWT, Swing, JavaFX & SWT 2
M AWT Kann meinen Fehler beim ActionListener nicht finden AWT, Swing, JavaFX & SWT 5
R 2D-Grafik Massive Frame Drops beim Benutzen von AffineTransformOp AWT, Swing, JavaFX & SWT 2
ruutaiokwu Swing windowStateChanged macht exakt das Gegenteil beim Verändern der Fenstergrösse AWT, Swing, JavaFX & SWT 3
J Exception beim JFrame erstellen AWT, Swing, JavaFX & SWT 6
B 2D-Grafik paintcomponent Probleme beim zeichnen AWT, Swing, JavaFX & SWT 10
D JInternalFrame wechselt Position beim ersten Click AWT, Swing, JavaFX & SWT 0
steven789hjk543 Swing Verstehe etwas beim GUI nicht AWT, Swing, JavaFX & SWT 3
L JavaFX Probleme beim Installieren JavaFX11 / JavaFX12 -- Eclipse 2019-03 AWT, Swing, JavaFX & SWT 3
H JavaFX Probleme Beim Wechseln der scene als .fxml AWT, Swing, JavaFX & SWT 7
A Fehler beim Hintergrund AWT, Swing, JavaFX & SWT 17
F JavaFX Probleme beim automatischen Konvertieren AWT, Swing, JavaFX & SWT 4
J Hilfe beim tablevies AWT, Swing, JavaFX & SWT 2
L JavaFX Fehler beim setzen von Farben AWT, Swing, JavaFX & SWT 16
T LookAndFeel LookAndFeel funktioniert nicht beim JFrame wechsel AWT, Swing, JavaFX & SWT 3
L Java FX Exception beim start AWT, Swing, JavaFX & SWT 2
L JSplitPane Divider Location beim Maximieren AWT, Swing, JavaFX & SWT 6
L JavaFX Problem beim Aufrufen einer Methode AWT, Swing, JavaFX & SWT 5
J ObservableList wirft exception beim zweiten füllen. AWT, Swing, JavaFX & SWT 4
emma_louisa JavaFX Werte beim Aufrufen des Fensters übernehmen (SceneBuilder) AWT, Swing, JavaFX & SWT 3
Tronert JavaFX Fehler beim Ändern der font-weight AWT, Swing, JavaFX & SWT 7
W Swing Hilfe beim Einbinden von Bildern in einem JFrame AWT, Swing, JavaFX & SWT 8
D Kein Icon beim JTabbedPane AWT, Swing, JavaFX & SWT 1
L JavaFX LoadException beim Laden von JavaFX Anwendung AWT, Swing, JavaFX & SWT 6
T Java FX Probleme beim befüllen eines Tableviews AWT, Swing, JavaFX & SWT 5
N Eclipse - GUI - MacBook - Buttonsichtbarkeit beim Anlegen/Erstellen AWT, Swing, JavaFX & SWT 14
S AWT Probleme beim Zeichnen AWT, Swing, JavaFX & SWT 3
T JButton wird beim vergrößern des Fensters erst sichtbar AWT, Swing, JavaFX & SWT 4
Tommy135 JavaFX JavaFX Fehler beim Scenewechsel AWT, Swing, JavaFX & SWT 23
E Swing Miserable Performance beim Ändern der Hintergrundfarbe von JLabels AWT, Swing, JavaFX & SWT 3
L Charset beim Drucken falsch AWT, Swing, JavaFX & SWT 2
MaxG. Swing Farbe von Button beim drücken ändern AWT, Swing, JavaFX & SWT 4
H JavaFX Kriege fehler beim Fenster wechseln AWT, Swing, JavaFX & SWT 7
D Swing Swing Objekte sehen im Entwurf anders aus als beim Ausführen AWT, Swing, JavaFX & SWT 3
R Swing Programm läuft nur beim Debuggen korrekt ab AWT, Swing, JavaFX & SWT 4
I 2D-Grafik Problem beim Ändern der Farbe eine 2d Objekts AWT, Swing, JavaFX & SWT 3
K Probleme beim JPasswordField AWT, Swing, JavaFX & SWT 11
W Kodierung (CharSet) beim Schreiben ändern AWT, Swing, JavaFX & SWT 1
D Swing JComboBox (DefaultComboBoxModel) überschreibt Eintrag beim erstellen AWT, Swing, JavaFX & SWT 0
T JButton überlagern sich und werden erst beim Mausscrollen sichtbar AWT, Swing, JavaFX & SWT 2
Thallius Swing "..." beim JLabel verhindern? AWT, Swing, JavaFX & SWT 3
P Scrollbalken verschwinden beim Zoomen AWT, Swing, JavaFX & SWT 4
A JavaFX DatePicker in Swing beim Start nicht sichtbar AWT, Swing, JavaFX & SWT 2
D JavaFX Probleme bei Service-Klasse beim ändern der GUI AWT, Swing, JavaFX & SWT 8
D JavaFX (WebStart) Graues Fenster beim Start AWT, Swing, JavaFX & SWT 4
K Probleme beim zeichnen mit paintComponent() AWT, Swing, JavaFX & SWT 1
O Swing JList beim Klicken in der GUI erstellen AWT, Swing, JavaFX & SWT 6
D Frame beim starten eines anderen Frames schließen AWT, Swing, JavaFX & SWT 2
R Hilfe beim ändern des Hintergrundes eines JFrames AWT, Swing, JavaFX & SWT 9
7 JavaFX Problem beim Zeichnen eines Dreiecks in einem GUI AWT, Swing, JavaFX & SWT 6
L JavaFX Verzögerung beim Laden von Daten AWT, Swing, JavaFX & SWT 6
S NullPointer Exception beim Laden von Bildern AWT, Swing, JavaFX & SWT 11
I JavaFX Speichern der eingefügten Einträge beim Neustart des Programms AWT, Swing, JavaFX & SWT 2
J JavaFx/SceneBuilder/Felder beim verlassen prüfen AWT, Swing, JavaFX & SWT 1
D JavaFX Beim Schließen (Rotes X) Code ausführen AWT, Swing, JavaFX & SWT 1
N Swing Problem beim Scrollen mit JScrollPane AWT, Swing, JavaFX & SWT 6
C Gesucht: Hilfe beim programmieren. AWT, Swing, JavaFX & SWT 1
S Action durchführen beim Programm beenden AWT, Swing, JavaFX & SWT 3
J JavaFX Tooltip Verzögerung beim ersten Anzeigen AWT, Swing, JavaFX & SWT 4
C Hilfe beim programmieren mit studiumgebundenes Projekt AWT, Swing, JavaFX & SWT 1
A JavaFX Hilfe beim Design eines Quiz AWT, Swing, JavaFX & SWT 2
D JavaFX build.fxbuild error beim Erstellen einer exe AWT, Swing, JavaFX & SWT 2
C Java FX Probleme beim Schließen einer Stage AWT, Swing, JavaFX & SWT 11
M Swing Vorgehen beim Aufruf der Klassen/Methoden AWT, Swing, JavaFX & SWT 7
T Swing NullPointerException beim auslesen von jTextField - Anfänger! AWT, Swing, JavaFX & SWT 3
R Swing Elemente verschieben sich im GBL beim Ein/Ausblenden AWT, Swing, JavaFX & SWT 0
N Swing JTree Problem beim erstellen der Knoten AWT, Swing, JavaFX & SWT 0
F Breite beim GridBagLayout festlegen AWT, Swing, JavaFX & SWT 2
N Swing CardLayout: Problem beim Wechsel zwischen den JPanels AWT, Swing, JavaFX & SWT 3
R TriangleMesh verschwindet teilweise beim resizen des Frames, sowie beim rotieren? AWT, Swing, JavaFX & SWT 1
S Swing Warum funktioniert der automatische Zeilenumbruch mit arabischen Zeichen beim JTextPane nicht AWT, Swing, JavaFX & SWT 3
T Problem beim Zeichnen von Rechteck AWT, Swing, JavaFX & SWT 3
H Swing Probleme beim erstellen eines neuen Objektes durch einen Button AWT, Swing, JavaFX & SWT 10
S Größe der Komponenten, beim ändern der größe des Frames, mit ändern! AWT, Swing, JavaFX & SWT 2
K Swing Automatisches "Packen" beim "Neu-Painten" AWT, Swing, JavaFX & SWT 2
U Swing Beim Bedienen eines Buttons JFrame schließen AWT, Swing, JavaFX & SWT 2
U Fenster beim Vergörßern immer quadratsich AWT, Swing, JavaFX & SWT 7
X JavaFX TableView Error beim clicken des außenbereiches AWT, Swing, JavaFX & SWT 5
S JScrollPane --> Programm hängt sich beim scrollen auf AWT, Swing, JavaFX & SWT 2

Ähnliche Java Themen

Neue Themen


Oben