Auf eine Zeichnung im Canvas reagieren

TheJavaKid

Top Contributor
Hallo!

Ich habe vor einigen Jahren mal ein Spiel entwickelt und das ganze in Flash und HTML/JS realisiert und möchte das nun auch auf Java übertragen. Allerdings stehe ich vor folgender Hürde: Sowohl in Flash als auch in HTML lassen sich einfach einfache Objekte (MovieClips / DIV-Boxen) erzeugen, die auf ein Event reagieren können. Ich will aber kein Parkett aus JButtons in Java haben, deswegen will ich das mit Graphics und einem Canvas realisieren. Jetzt stellt sich mir eine Frage: Kann ein Objekt auf einem Canvas mit zB einem Mausklick interagieren?
Präzise geht es darum, dass ich mittels eines Mausklicks auf ein Canvas die Farbe des darin aufgemalten Rectangles eruieren will.
Wie wäre dafür der beste (und eleganteste!) Lösungsansatz?

LG
Matze
 

Robat

Top Contributor
Im Endeffekt würdest du auf dem Canvas wohl einen MouseListener registrieren und dann schauen ob der Mausklick in dem Rechteck liegt (Sprich Koordinaten anschauen/vergleichen)
 

mihe7

Top Contributor
Ja das schon aber da reagiert das Programm nict auf die Zeichnungen sondern auf das ganze Canvas, das in 3 Teile unterteilt ist und dann abhängig von der Mausposition die oberste Scheibe markiert.
Das ist doch auch nichts anderes. Die Frage ist doch nur, was die "Canvas-Klasse" mit dem Ereignis anstellt: reagiert es auf den Mausklick selbst oder gibt es das Ereignis an das angeklickte Objekt weiter. Je nachdem wie weit Du gehst, landest Du ggf. bei (J)Component. Die Grenzen sind da fließend.
 

TheJavaKid

Top Contributor
Das ist doch auch nichts anderes. Die Frage ist doch nur, was die "Canvas-Klasse" mit dem Ereignis anstellt: reagiert es auf den Mausklick selbst oder gibt es das Ereignis an das angeklickte Objekt weiter. Je nachdem wie weit Du gehst, landest Du ggf. bei (J)Component. Die Grenzen sind da fließend.

Es wird so sein, dass die jeweiligen Objekte damit interagieren werden, weswegen ich auch schon in betracht gezogen hab das ganze gar nicht zu zeichnen sondern mit JComponents umzusetzen, von denen ich weiß, dass sie spezifisch auf Ereignisse reagieren und sich wandeln können. Dabei hab ich allerdings die Sorge, um das nicht auf die Performance gehen könnte, wenn ich da 100 JComponents hab, die dann auch noch etwas machen sollen?
 

Thallius

Top Contributor
Ach. Du hast das Canvas doch irgendwann irgendwo gezeichnet. Warum merkst du dir das nicht einfach in einer Liste (wenn es mehrere sind) und schaust dann nach? Du must doch nicht das Canvas etwas fraagen das du ihm selber bestimmt hast....
 

mihe7

Top Contributor
Es wird so sein, dass die jeweiligen Objekte damit interagieren werden, weswegen ich auch schon in betracht gezogen hab das ganze gar nicht zu zeichnen sondern mit JComponents umzusetzen, von denen ich weiß, dass sie spezifisch auf Ereignisse reagieren und sich wandeln können. Dabei hab ich allerdings die Sorge, um das nicht auf die Performance gehen könnte, wenn ich da 100 JComponents hab, die dann auch noch etwas machen sollen?
Was sollten die denn "machen"?

Du kannst natürlich hergehen und selbst "Komponenten" entwerfen, die dann etwas leichtgewichtigter sind. Das hängt aber davon ab, was das Ding können soll. Wenn Du z. B. wirklich nur Shapes haben willst, könntest Du folgendes machen:
Java:
interface ClickableShape extends Shape {
    void processMouseEvent(MouseEvent e);
}

Dein Canvas muss dann bei einem Mouse-Ereignis einfach das betreffende Shape heraussuchen und processMouseEvent aufrufen. Aber dann geht es schon los: wie sollen die Shapes denn gezeichnet werden? Hm... da könnte man auf die Idee kommen und statt Shapes zu erweitern einfach das paint-Ereignis auch noch weitergeben:
Java:
interface Clickable {
    void processMouseEvent(MouseEvent e);
    void draw(Graphics g);
}
Und jetzt wollen wir noch dieses und jenes und schon sind wir bei JComponent angelangt.
 

TheJavaKid

Top Contributor
Dieser Lösungsansatz sieht gar nicht mal so schlecht aus, ich denke das könnte das sein, was ich brauche.
Im Prinzip nichts Aufregendes: Es wird ein Feld mit quadratischen Kacheln generiert. Bei einem Klick auf die Kachel soll die Farbe der Kachel herausgefunden und daraufhin sämtliche Farben der Kacheln zufällig geändert werden. Manko dabei: Es muss zwingend mit einer Farbverlauf-Animation geschehen.

Das Ganze wäre mit JComponents natürlich ganz easy umzusetzen allerdings suche ich eben nach der elegantesten und vor allem performantesten Lösung dafür. Deswegen war die Idee das Ganze zeichnen zu lassen.
 

dzim

Top Contributor
Von wie vielen Objekten auf dem Canvas reden wir eigentlich? Sind die frei verschiebbar und können sie sich überlappen? Warum nicht JavaFX nehmen und Shapes (Circle, Rectangle, SVGPath etc.) auf einem Pane platzieren und die vorhanden APIs verwenden - niemand redet davon, dass man da alles mit Buttons zupflastern muss, aber so musst du ständig das Cavas neu zeichnen, dir merken, welches Objekt in welchem Bereich liegt, diesen immer mit der Mausklick-Posittion abgleichen. Für mich klingt es einfach zu sehr nach Overkill im Moment - aber das ist nur meine Meinung...
 

mihe7

Top Contributor
Mal ein Beispiel. Achtung: die Datei ist ggf. etwas wirr und enthält aus Gründen der Faulheit Darstellung im Forum mehr als nur die Komponente :) Sprich: ab main gehört das nicht mehr zur Komponente selbst.

Java:
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.*;
import javax.swing.*;
import java.util.Random;
import java.util.function.Consumer;

public class TilesPanel extends JComponent {

    private Color[] colors;    
    private int tilesPerRow;
    private double balance;

    public TilesPanel(Color[] colors, int tilesPerRow) {
        this.colors = colors;
        this.tilesPerRow = tilesPerRow;
    }

    public int getTileCount() {
        return colors.length;
    }

    public Color[] getColors() { return colors; }    

    public Color getTileColor(int ix) {
        return colors[ix];
    }

    public void setColors(Color[] colors) {
        this.colors = colors;
        repaint();
    }        

    public int getTileIndex(Point p) {
        Point tile = viewToTile(p);
        return tilesPerRow * tile.y + tile.x;
    }

    public Point viewToTile(Point p) {
        Rectangle2D box = getDrawingBox();
        double x = p.getX() - box.getX();
        double y = p.getY() - box.getY();

        Rectangle2D size = getTileRect();
        int xTile = (int)(x / size.getWidth());
        int yTile = (int)(y / size.getHeight());

        return new Point(xTile, yTile);
    }

    public Rectangle2D getDrawingBox() {
        Insets insets = getInsets();
        int x = insets.left;
        int y = insets.top;
        double w = getWidth() - insets.left - insets.right;
        double h = getHeight() - insets.top - insets.bottom;

        return new Rectangle2D.Double(x, y, w, h);
    }

    public Rectangle2D getTileRect() {
        Rectangle2D box = getDrawingBox();

        double tileWidth = box.getWidth() / tilesPerRow;
        double tileHeight = box.getHeight() / getRows();
        return new Rectangle2D.Double(0, 0, tileWidth, tileHeight);
    }

    private int getRows() {
        return (colors.length + tilesPerRow - 1) / tilesPerRow;
    }

    @Override
    public void paintComponent(Graphics g) {
        Graphics2D g2 = (Graphics2D) g;
 
        Rectangle2D tile = getTileRect();
        double tileWidth = tile.getWidth();
        double tileHeight = tile.getHeight();

        g2.translate(getInsets().left, getInsets().top);

        for (int i = 0; i < colors.length; i++) {
            drawTile(g2, tile, i);
            g2.translate(tileWidth, 0);

            if ((i+1) % tilesPerRow == 0) {
                g2.translate(-tileWidth*tilesPerRow, tileHeight);
            }
        }
    }

    private void drawTile(Graphics2D g, Rectangle2D tile, int ix) {
        g.setColor(colors[ix]);
        g.fill(tile);
        g.setColor(Color.BLACK);
        g.draw(tile);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            Random rand = new Random(1L);
            Color[] colors = randomColors(400, rand);
            Animation animation = new Animation();

            TilesPanel panel = new TilesPanel(colors, 20);
            panel.addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    int ix = panel.getTileIndex(e.getPoint());

                    Color[] destColors = randomColors(colors.length, rand);
                    destColors[ix] = panel.getTileColor(ix);

                    ColorTransition colorTransition = new ColorTransition(
                            panel.getColors(), destColors);

                    animation.start(500, v -> panel.setColors(colorTransition.perform(v)));
                }
            });

            JFrame frame = new JFrame();
            frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
            frame.add(panel);
            frame.setSize(600, 400);
            frame.setVisible(true);

        });
    }

    public static Color[] randomColors(int num, Random rand) {
        Color[] colors = new Color[num];
        for (int i = 0; i < colors.length; i++) {
            colors[i] = new Color((int)(rand.nextInt()));
        }        
        return colors;
    }

    private static class ColorTransition {
        private Color[] source;
        private Color[] dest;

        public ColorTransition(Color[] source, Color[] dest) {
            this.source = source;
            this.dest = dest;
        }

        public Color[] perform(double value) {
            Color[] colors = new Color[source.length];
            for (int i = 0; i < colors.length; i++) {
                colors[i] = transformedColor(i, value);
            }
            return colors;
        }        

        private Color transformedColor(int ix, double value) {
            int red = dest[ix].getRed() - source[ix].getRed();
            int green = dest[ix].getGreen() - source[ix].getGreen();
            int blue = dest[ix].getBlue() - source[ix].getBlue();
            double factor = value * value;
            return new Color(
                (int)(source[ix].getRed() + red * factor),
                (int)(source[ix].getGreen() + green * factor),
                (int)(source[ix].getBlue() + blue * factor));
        }

    }

    private static class Animation {
        private Timer timer;

        public void start(long duration, Consumer<Double> consumer) {
            if (timer == null) {
                long start = System.currentTimeMillis();
                timer = new Timer(10, e -> processTimerEvent(start, duration, consumer));
                timer.setRepeats(true);
                timer.start();
            }
        }

        public void stop() {
            if (timer != null) {
                timer.stop();
                timer = null;
            }
        }    

        private void processTimerEvent(long start, long duration, Consumer<Double> consumer) {
            double value = (System.currentTimeMillis() - start) / (double) duration;
            if (value >= 1.0) {
                consumer.accept(1.0);
                stop();
            } else {
                consumer.accept(value);
            }
        }
    }
}
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
N eine Zeichnung scrollbar machen AWT, Swing, JavaFX & SWT 4
jojoge wie kann ich in eine Benennung eines JButtons eine Variable einbauen? AWT, Swing, JavaFX & SWT 6
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 Buttons und Shapes sehen ja nach Screengröße klein oder zu groß aus, jemand eine Idee, was man tun kann? AWT, Swing, JavaFX & SWT 1
ExceptionOfExpectation Mit einer laufenden GUI Applikation eine Datei in dem Rechner löschen AWT, Swing, JavaFX & SWT 2
Jose05 Aus einer normalen Java Klasse eine FXML-Klasse laden AWT, Swing, JavaFX & SWT 12
_user_q Gibt es eine Möglichkeit, in Java alle möglichen Zeichen automatisch tippen zu lassen? AWT, Swing, JavaFX & SWT 13
J Ich kriege eine Fehler Messesage bei meinem Media Player AWT, Swing, JavaFX & SWT 8
I Einbindung eines jpg/png/icons in eine GUI AWT, Swing, JavaFX & SWT 1
mrbody234 ArrayList<Message> in eine TableView visualisieren AWT, Swing, JavaFX & SWT 2
U Gibt es eine Möglichkeit statt concatenate einen anderen Befehl zu nutzen? AWT, Swing, JavaFX & SWT 9
D Tastaturabfragen CTRL+t, CTRL+E bei eine JTable, bestehend aus JTextAteas AWT, Swing, JavaFX & SWT 4
G JavaFX Wert aus DB lesen, wenn erfolgreich automatisch eine fxml laden, möglich? AWT, Swing, JavaFX & SWT 2
Lukas2904 Wie speicher ich eine Einstellung? AWT, Swing, JavaFX & SWT 1
T Getter und Setter für eine Stage AWT, Swing, JavaFX & SWT 6
P Zwei JTables auf eine A4-Seite mit einstellbaren Rändern AWT, Swing, JavaFX & SWT 9
Monokuma 2D-Grafik Imageimport durch eine gezeichnete Form ersetzen AWT, Swing, JavaFX & SWT 16
M Eine Datei auf den Apache Server hochladen - über das Menü im JavaProgramm AWT, Swing, JavaFX & SWT 7
B JavaFX Warum wird hier eine NullPointer-Exception geworfen? AWT, Swing, JavaFX & SWT 7
VPChief Gibt es eine möglichkeit Dateien aus der jar datei zu kopieren? AWT, Swing, JavaFX & SWT 46
B Swing Sudoku: Laden / Speichern von Zahlen aus/in mehrere JTextFields aus/in eine(r) Textdatei AWT, Swing, JavaFX & SWT 9
P Swing Icon einfügen wirft eine Fehlermeldung AWT, Swing, JavaFX & SWT 3
F Variablen an eine Form binden? AWT, Swing, JavaFX & SWT 2
V Swing für jedes Kästchen eine eigene Farbe AWT, Swing, JavaFX & SWT 2
F Wie bekomme ich den Wert der ComboBox in eine Variable gespeichert welche ich für meinen ActionListener nutzen kann? AWT, Swing, JavaFX & SWT 3
W JavaFX Warum kriege ich eine Exception? AWT, Swing, JavaFX & SWT 23
karlmasutra JavaFX Zugriff auf eine erzeugte Scene aus einer anderen Klasse AWT, Swing, JavaFX & SWT 1
Informatiknoob AWT Zahlenraten (eine Zahl zwischen 1 und 10) AWT, Swing, JavaFX & SWT 1
A eine Fehler AWT, Swing, JavaFX & SWT 9
A JavaFX Daten in eine HTML-Table mit JS schreiben AWT, Swing, JavaFX & SWT 3
B JavaFX TableView eine Zeile markieren AWT, Swing, JavaFX & SWT 5
J jButton soll nach klicken eine Variable um 1 erhöhen AWT, Swing, JavaFX & SWT 2
J Compiler in der JavaFX stop() Methode warten lassen bist eine Aktion in einer anderen Scene gemacht AWT, Swing, JavaFX & SWT 5
J Swing JavaProgramm für Verschlüssen für eine Datei AWT, Swing, JavaFX & SWT 19
xYurisha JLabel Text einer geöffneten Gui über eine andere Klasse ändern! AWT, Swing, JavaFX & SWT 3
J JavaFX Die Webview stellt eine Webseite nicht dar AWT, Swing, JavaFX & SWT 0
M JavaFX Ein Labeltext eine zeitlang anzeigen dann weiter machen AWT, Swing, JavaFX & SWT 3
F Event wenn Maus eine JList verlässt AWT, Swing, JavaFX & SWT 13
I JAVAFX - Übergabe der Inhalte an eine Scene - Wo ist der Vorteil gegenüber Swing? AWT, Swing, JavaFX & SWT 2
Joker4632 JFrame in eine Runnable auslagern? AWT, Swing, JavaFX & SWT 4
A JScrollPane soll JPanel mit JButtons enthalten und eine Scollbar anzeigen AWT, Swing, JavaFX & SWT 1
B Wie erstelle ich eine JavaFX Anwendung von diesem Code? AWT, Swing, JavaFX & SWT 3
Sanni94 JavaFX Kann man eine Grafik in einen Text einbinden? AWT, Swing, JavaFX & SWT 2
Java_RY AWT Frame in eine eigene klasse auslagern und aufrufen AWT, Swing, JavaFX & SWT 6
I 2D-Grafik Problem beim Ändern der Farbe eine 2d Objekts AWT, Swing, JavaFX & SWT 3
G Eine paint-Methode, 2 Welten? AWT, Swing, JavaFX & SWT 3
Thallius Swing JDatePicker oder Sucht jemand eine Aufgabe? AWT, Swing, JavaFX & SWT 0
K Wie kann ich eine Variable zwischen Tab Klassen weitergeben ? AWT, Swing, JavaFX & SWT 7
D JavaFX Erkennen wenn eine Anwendung geschlossen wird und etwas tun? AWT, Swing, JavaFX & SWT 4
R Swing Durch JComboBox-Item eine TextArea aktualisieren AWT, Swing, JavaFX & SWT 2
M Wie binde ich eine JavaFX ProgressBar an eine Datei Übertragung? AWT, Swing, JavaFX & SWT 2
D Objekte einer Oberfläche in eine Datei/Ordner speichern AWT, Swing, JavaFX & SWT 9
A Mit dem Scene Builder eine Collage erstellen (Bilder beziehen aus Flickr) AWT, Swing, JavaFX & SWT 1
A JFace Wizard: Ist es möglich eine Page zu löschen? AWT, Swing, JavaFX & SWT 2
L Swing Wie programmiere ich eine eigene GUI? AWT, Swing, JavaFX & SWT 12
M Combo Box auswahl in eine Datenbank speichern AWT, Swing, JavaFX & SWT 1
M Swing JTextField getText Mehtode übergeben in eine Klasse zu einer Rechnung AWT, Swing, JavaFX & SWT 1
D AWT Das ganze GUI in eine Klasse? AWT, Swing, JavaFX & SWT 1
J JavaFX eine Art Tabelle, jedoch mit mehreren Zeilen AWT, Swing, JavaFX & SWT 2
L Zwei String Array in eine Spalte einfügen AWT, Swing, JavaFX & SWT 1
U LookAndFeel für eine Komponente AWT, Swing, JavaFX & SWT 2
E Mit Netbeans von einer Form auf eine Komponente einer anderen Form zugreifen AWT, Swing, JavaFX & SWT 2
G Zeichnen auf eine schwergewichtige Komponente? AWT, Swing, JavaFX & SWT 0
S Swing Update eine JTabelle nach einer Drag&Drop Operation AWT, Swing, JavaFX & SWT 0
M Über eine JMenuBar überprüfen ob ein JCheckBoxMenuItem selectiert ist. AWT, Swing, JavaFX & SWT 4
M Wie kann ich eine an Apple Automator angelehnte GUI erstellen? AWT, Swing, JavaFX & SWT 1
A JavaFX Eine Task mit einer ProgressBar verbinden AWT, Swing, JavaFX & SWT 0
S JavaFX Canvas - nur eine Figur auf der Zeichenfläche färben? AWT, Swing, JavaFX & SWT 1
S Swing Mit einem Link eine Methode aufrufen AWT, Swing, JavaFX & SWT 2
C Swing Durch Inhaltsänderung eines JTextfields eine Funktion aufrufen AWT, Swing, JavaFX & SWT 5
G 2D-Slider bzw. eine graphische Auswahlkomponente die sich so verhält AWT, Swing, JavaFX & SWT 6
H Lust auf eine Open-Source Lösung für universelle Java Client-Technologie? AWT, Swing, JavaFX & SWT 11
T Aus JAVA.Jar GUI eine Flash-Datei machen AWT, Swing, JavaFX & SWT 3
S 5 Playlisten eine Skip() AWT, Swing, JavaFX & SWT 4
M SWT Browser nur eine Seite erlauben AWT, Swing, JavaFX & SWT 3
B Daten in eine JTable schreiben AWT, Swing, JavaFX & SWT 3
K GUI Elemente über eine separate Textdatei beschriften? AWT, Swing, JavaFX & SWT 4
G noch eine Frage zum EventDispachThread AWT, Swing, JavaFX & SWT 4
I Anhand ButtonGroup eine Auswahl treffen AWT, Swing, JavaFX & SWT 2
B Nach dem Öffnen des Dialogs eine Aktion ausführen. AWT, Swing, JavaFX & SWT 6
W Funktion aus einer Java Datei in eine andere einbauen AWT, Swing, JavaFX & SWT 25
A Swing Text auf eine Seite an beliebigen Orten schreiben AWT, Swing, JavaFX & SWT 6
G Swing Value von einer JScrollBar auf eine andere übertragen AWT, Swing, JavaFX & SWT 2
Rudolf Swing Wie testet man am besten eine GUI? AWT, Swing, JavaFX & SWT 3
P Swing Alle Zeilen einer Spalte (jTable) zusammen zählen und in eine eigene Zeile das Ergebnis schreiben. AWT, Swing, JavaFX & SWT 7
F GroupableTableHeader zeigt nur eine Zeile AWT, Swing, JavaFX & SWT 4
N Swing Optimale Höhe eine JTextPanes bei festgelegter Breite bestimmen AWT, Swing, JavaFX & SWT 23
R Swing Mit Swing eine throws Exception Methode öffnen AWT, Swing, JavaFX & SWT 3
M Eine Kugel nach rechts bewegen AWT, Swing, JavaFX & SWT 5
C Swing NullPointerException beim Hinzufügen von Checkboxes in eine ArrayList AWT, Swing, JavaFX & SWT 5
GUI-Programmer LayoutManager Kurze Layout Frage - eine komponente mittig? AWT, Swing, JavaFX & SWT 5
lumo SWT Zeichnen bescheunigen bzw eine allg. Frage AWT, Swing, JavaFX & SWT 8
M Auf einem Bild eine Markierung aufziehen AWT, Swing, JavaFX & SWT 3
R Eine Instanz von JPanel mehrfach hinzufügen AWT, Swing, JavaFX & SWT 2
B eine .jar erzeugen AWT, Swing, JavaFX & SWT 4
M In JField eine Kommazahl darstellen java.lang.NumberFormatException AWT, Swing, JavaFX & SWT 4
N Button on click eine andere Klasse aufrufen... AWT, Swing, JavaFX & SWT 2
M Eine nicht korrekte Darstellung bei repaint() warum? AWT, Swing, JavaFX & SWT 4
M Ein Tab eine JTabbedPane durch Button Druck öffen AWT, Swing, JavaFX & SWT 2
B Swing JButtons in eine Arraylist<JButton> einfügen AWT, Swing, JavaFX & SWT 2

Ähnliche Java Themen

Neue Themen


Oben