2D-Grafik Grafik in zwei verschiedenen Fenstern gleichzeitig zeichnen

  • Themenstarter Themenstarter Gelöschtes Mitglied 67058
  • Beginndatum Beginndatum
G

Gelöschtes Mitglied 67058

Gast
Hallo liebe Foren-Teilnehmer,
vielleicht hat jemand eine Idee wie man zwei Punkte in zwei verschiedenen Fenstern gleichzeitig zeichnen kann. Da ich selber hier nicht weiterkomme, habe ich zwei einfache Beispiele angefügt, mit denen ich teste. Leider hat der Versuch mit convertPoint, MouseListener, MouseMotionListener und auch damit ein Objekt, das schon erzeugt wurde an zwei verschiedene Frames zu übergeben nicht gelungen.
Erstes Beispiel: Linie zeichnen in zwei Fenstern gleichzeitig (zeichnet im zweiten Fenster nicht) / Zweites Beispiel ist nur evtl. eine Möglichkeit: Wie ein Objekt an einen nachfolgenden Frame übergeben werden kann. Vielen Dank im Voraus.


[CODE lang="java" title="Paint in zwei Fenstern gleichzeitig"]
public class P1 extends Component{

public static void main(String[] args)
{
JFrame f = new JFrame("Draw a Line");
f.setSize(300, 300);
f.setLocation(300, 300);
f.setResizable(false);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);



Component p = new Component() {
Point pointStart = new Point(200,200);
Point pointEnd = new Point(100,100);
// Point containerPoint1 = null;
// Point containerPoint2 = null;

Component p1 = new P1();
Component p2 = new P2();
// Component p4 = new P4(pointStart, pointEnd);



{
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
pointStart = e.getPoint();

Point containerPoint1 = SwingUtilities.convertPoint(
p1,
pointStart,
p4);
Component p4 = new P4(pointStart, pointEnd);
p4.repaint();
}

public void mouseReleased(MouseEvent e) {
pointStart = null;

Point containerPoint1 = null;
Component p4 = new P4(pointStart, pointEnd);
p4.repaint();
}
});
addMouseMotionListener(new MouseMotionAdapter() {
public void mouseMoved(MouseEvent e) {
pointEnd = e.getPoint();

Point containerPoint2 = SwingUtilities.convertPoint(
p1,
pointEnd,
p4);
Component p4 = new P4(pointStart, pointEnd);
p4.repaint();
}

public void mouseDragged(MouseEvent e) {
pointEnd = e.getPoint();

Point containerPoint2 = SwingUtilities.convertPoint(
p1,
pointEnd,
p4);

repaint();
Component p4 = new P4(pointStart, pointEnd);
p4.repaint();
}
});
Component p4 = new P4(pointStart, pointEnd);
p4.repaint();
}
public void paint(Graphics g) {
super.paint(g);
// pointStart = new Point(20,20);
// pointEnd = new Point(200,200);
if (pointStart != null) {

g.setColor(Color.red);
g.fillOval(pointStart.x - 10, pointStart.y - 10, 20, 20);

g.setColor(Color.BLUE);
g.fillOval(pointEnd.x - 10, pointEnd.y - 10, 20, 20);
g.drawLine(pointStart.x, pointStart.y, pointEnd.x, pointEnd.y);

Main m = new Main();
m.convertPoint(p1,pointStart, p4);
m.convertPoint(p1,pointEnd, p4);

Component p4 = new P4(pointStart, pointEnd);
p4.repaint();

}
}

};


// Point glassPanePoint = e.getPoint();
// Container container = contentPane;

f.add(p);
f.setVisible(true);
}
}

import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import javax.swing.JFrame;


public class P2 extends Component{


public P2() {
// TODO Auto-generated constructor stub
}

public static void main(String[] args)
{
JFrame f = new JFrame("Draw a Line");
f.setSize(300, 300);
f.setLocation(300, 300);
f.setResizable(false);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);


Component p2 = new Component() {

Point pointStart = null;
Point pointEnd = null;
{
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
pointStart = e.getPoint();

}

public void mouseReleased(MouseEvent e) {
pointStart = null;
}
});
addMouseMotionListener(new MouseMotionAdapter() {
public void mouseMoved(MouseEvent e) {
pointEnd = e.getPoint();

}

public void mouseDragged(MouseEvent e) {
pointEnd = e.getPoint();
repaint();
}
});
}


public void paint(Graphics g) {
super.paint(g);
// pointStart = new Point(140,40);
// pointEnd = new Point(100,20);

if (pointStart != null) {
g.setColor(Color.BLUE);

g.drawLine(pointStart.x, pointStart.y, pointEnd.x, pointEnd.y);
System.out.println("REPAINT wurde aufgerufen");
}
}
};


f.add(p2);
f.setVisible(true);
}
}
//Mit diesem Test, den ich im Netz gegoogelt habe,
//komme ich leider auch nicht weiter
public class OneFrame {
public GrossesBild so = null;
// create it in this class and do things with it

public OneFrame() {
so = new GrossesBild();
}

private void openNewFrame() {
NewFrame nf = new NewFrame(so);

}
}
public class NewFrame{
public static GrossesBild so = null;

public NewFrame(GrossesBild so) {
this.so = so;
}

public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {

new NewFrame(so);
}
});
}
}[/CODE]
 
Du zeigst einfach dasselbe Zeichnungsobjekt in zwei verschiedenen Frames an. Dabei verwendest Du das Observer-Pattern, um über Änderungen an der Zeichnung informiert zu werden. Fertig.
 
Bin damit nicht zurecht gekommen. Vielleicht hat ja noch mal jemand die Möglichkeit sich das anzusehen. Die Änderung an der Zeichnung geht bis zum Listener (ist im Konstruktor P5 vorhanden), allerdings ist sie nicht mehr in paint zu sehen, das über repaint() aufgerufen wird (poindEnd = null). Das Observer-Pattern habe ich aus einem Buch übernommen und dann habe ich versucht das Beispiels anzupassen. Deswegen gibt es sicher einiges, das man löschen könnte. P5 sollte konkreter Observer sein und Zeichner sollte konkretes Subjekt sein (und auch Observer, da einfach). Vielen Dank schon im Voraus.
[CODE lang="java" title="Start aufrufen"]import java.awt.Point;
class Subject {
Observer[] observers = new Observer[5];
int observerCnt = 0;

public void attach(Observer observer) {
observers[observerCnt++] = observer;
}

public void detach(Observer observer) {
for (int i = 0; i < observerCnt; i++) {
if (observers == observer) {
--observerCnt;
for(;i < observerCnt; ++i) {
observers = observers[i+1];
}
break;
}
}
}

public void fireUpdate(Point arg) {
for (int i = 0; i < observerCnt; ++i) {
System.out.println("Subject.fireUpdate()- arg = " + arg);
observers.update(this, arg);
}
}
}

import java.awt.Point;
interface Observer {
public void update(Subject subject, Point o);
}

import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
public class Zeichner extends Component{
int cnt = 0;
Point pointStart = null;
Point pointEnd = null;
Subject subject = new Subject();


public void attach(Observer observer) {
subject.attach(observer);
}

public void detach(Observer observer) {
subject.detach(observer);
}

public Zeichner() {

// this.pointStart = pointStart;
// this.pointEnd = pointEnd;
// {
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
pointStart = e.getPoint();
}

public void mouseReleased(MouseEvent e) {
pointStart = null;
}
});
addMouseMotionListener(new MouseMotionAdapter() {
public void mouseMoved(MouseEvent e) {
pointEnd = e.getPoint();
}

public void mouseDragged(MouseEvent e) {
pointEnd = e.getPoint();
// repaint();

subject.fireUpdate(e.getPoint());
}

});
}

public void paint(Graphics g) {
super.paint(g);
// pointStart = new Point(140,40);
// pointEnd = new Point(100,20);

if (pointStart != null) {
g.setColor(Color.BLUE);


g.drawLine(pointStart.x, pointStart.y, pointEnd.x, pointEnd.y);
System.out.println("in paint --- ***auch in zeichner*** --- Observer-update?");
}
}

public void update(Subject subject, Point o) {
this.repaint();
}
}

import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Point;


public class P5 extends Component implements Observer {
Point pointStart = null;
Point pointEnd = null;
//Point pointStart = new Point(140,40);
// Point pointEnd = new Point(100,20);
Subject subject = new Subject();


/** public void attach(Observer observer) {
subject.attach(observer);
}

public void detach(Observer observer) {
subject.detach(observer);
}**/

public P5(Point pointStart, Point pointEnd) {
System.out.println(" P5 ---");
this.pointStart = pointStart;
this.pointEnd = pointEnd;

repaint();

// {
/** addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
pointStart = e.getPoint();

}

public void mouseReleased(MouseEvent e) {
pointStart = null;
}
});
addMouseMotionListener(new MouseMotionAdapter() {
public void mouseMoved(MouseEvent e) {
pointEnd = e.getPoint();

}

public void mouseDragged(MouseEvent e) {
pointEnd = e.getPoint();
repaint();
}
});**/
// }
}
public P5(Point pointEnd) {

// this.pointStart = pointStart;
this.pointEnd = pointEnd;
System.out.println(" P5 Konstruktor mit pointEnd: " + this.pointEnd);

}

public void paint(Graphics g) {
super.paint(g);
pointStart = new Point(140,40);
// pointEnd = new Point(100,20);

System.out.println("in paint --- ***auch in P5*** --- Observer-update? --- paint: pointStart: " + pointStart + " / paint: pointEnd: " + pointEnd);
if (pointStart != null) {
g.setColor(Color.BLUE);
g.fillOval(pointStart.x - 10, pointStart.y - 10, 20, 20);

// g.drawLine(pointStart.x, pointStart.y, pointEnd.x, pointEnd.y);

}
}

public void update(Subject subject, Point point) {
System.out.println("update von P5: " + point);
//new P5(pointStart, pointEnd);
new P5(point);
revalidate();
repaint();
}

/** @Override
public void update(Subject subject, Object o) {
System.out.println("update von P5 " + o);
//new P5(pointStart, pointEnd);
new P5((Point) o);
//this.repaint();

}**/
}

import java.awt.Point;
import javax.swing.JFrame;

class Starte {

/** public void paint(Graphics g) {
// super.paint(g);
Point pointStart = new Point(140,40);
Point pointEnd = new Point(100,20);

if (pointStart != null) {
g.setColor(Color.BLUE);

g.drawLine(pointStart.x,pointStart.y,pointEnd.x,pointEnd.y);
System.out.println("REPAINT wurde aufgerufen");
}
}**/
public static void main(String[] args) {
JFrame f1 = new JFrame("Draw a Line");
f1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f1.setSize(300, 300);
f1.setLocation(300, 300);
f1.setResizable(false);


JFrame f2 = new JFrame("Show the Line");
f2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f2.setSize(300, 300);
f2.setLocation(600, 300);
f2.setResizable(false);


Zeichner zeichner = new Zeichner();
Point pointStart = null;
Point pointEnd = null;

P5 p5 = new P5(pointStart, pointEnd); //soll ein listener sein

//lokale anonyme Klasse als Listener
zeichner.attach(
new Observer(){
public void update(Subject subject, Point o) {
System.out.print("Observers update: ");
zeichner.repaint();

}
}
);
//P5 als Listener
zeichner.attach(p5);


f1.add(zeichner);
f1.setVisible(true);

f2.add(p5);
f2.setVisible(true);

}
}[/CODE]
 
Beispiel:
Java:
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.awt.*;
import javax.swing.*;

import java.util.*;
import java.util.List;

public class Test {
    static interface DrawingListener {
        void modified();
    }

    static class Drawing {
        private List<Shape> shapes = new ArrayList<>();
        private List<DrawingListener> listeners = new ArrayList<>();

        public List<Shape> getShapes() {
            return shapes;
        }

        public void add(Shape shape) {
            shapes.add(shape);
            modified();
        }

        public void remove(Shape shape) {
            shapes.remove(shape);
            modified();
        }

        public void addListener(DrawingListener l) {
            listeners.add(l);
        }

        public void removeListener(DrawingListener l) {
            listeners.remove(l);
        }

        public void modified() {
            for (DrawingListener l : listeners) {
                l.modified();
            }
        }
    }

    

    static class DrawingPanel extends JComponent {
        private Drawing drawing;
        private DrawingListener listener = () -> repaint();

        public void setDrawing(Drawing newDrawing) {
            if (drawing != null) {
                drawing.removeListener(listener);
            }
            drawing = newDrawing;
            if (drawing != null) {
                drawing.addListener(listener);
            }
        }
  
        public void paintComponent(Graphics g) {
            super.paintComponent(g);

            if (drawing == null) {
                return;
            }

            Graphics2D g2 = (Graphics2D) g;
            for (Shape shape : drawing.getShapes()) {
                g2.draw(shape);
            }
        }
    }

    public JFrame createDrawingFrame(DrawingPanel panel) {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.add(panel);
        frame.setSize(800, 600);
        return frame;
    }

    private DrawingPanel createDrawingPanel(Drawing drawing) {
        DrawingPanel panel = new DrawingPanel();
        panel.setDrawing(drawing);
        panel.addMouseListener(new MouseAdapter() {
            Point2D[] points = new Point2D[2];
            int count = 0;

            @Override
            public void mouseClicked(MouseEvent e) {
                points[count] = e.getPoint();
                count = (count + 1) % 2;
                if (count == 0) {
                    drawing.add(new Line2D.Double(points[0], points[1]));
                }
            }
        });
        return panel;
    }

    public void run() {
        Drawing drawing = new Drawing();
        drawing.add(new Line2D.Double(100, 100, 150, 150));

        createDrawingFrame(createDrawingPanel(drawing)).setVisible(true);
        createDrawingFrame(createDrawingPanel(drawing)).setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new Test().run());
    }
}
 
Die Kürze ist dem Forum geschuldet, das soll keine Lösung sondern lediglich ein Beispiel sein, um das Prinzip zu zeigen. In einer realen Anwendung wären die Klassen separat, außerdem würde man nicht nur Linien in einer Farbe und einer Strichstärke zeichnen wollen. Hierzu wäre wenigstens eine geeignete Klasse einzuführen, die entsprechende Zeichenobjekte modelliert. Eine Z-Achse wäre auch nicht verkehrt, um Objekte vor/hinter andere Objekte zu legen. Des weiteren kann das Ereignis (modified) durch zusätzliche Angaben konkretisiert werden, um beispielsweise nur Ausschnitte neu zu zeichnen. Kurz: es ist ein sehr rudimentärer, funktionaler Prototyp aber nicht mehr.
 
Ich habe diese Antwort heute erst gesehen.
Daß man die Klassen separat schreibt ist ein guter Tipp - obwohl ich diese nested Klassen sehr übersichtlich finde.
... Wie man das Ergebnis(modified) für Ausschnitte..... - kann ich mir gerade noch nicht vorstellen.
Eine x,y-Achse habe ich bereits, mit Mittelpunkt in der Mitte meines Bildes und eine z-Achse ist auch geplant, sobald die anderen Probleme gelöst sind. Über dieses Bild bewege ich meine Maus (bzw. die Maus bewegt ein transparentes JPanel darüber) und das JPanel zeigt genau dort den Ausschnitt und zusätzlich in einem seitlichen Frame an. Nun will ich das vergrößern - ohne scale (geht hier nicht, denn die Koordinatensysteme unterscheiden sich). Ursprünglich wollte ich dies über dem ersten Bild direkt tun, wegen Unübersichtlichkeit möchte ich den Ausschnitt ausschließlich in einem eigenen Frame seitlich davon anzeigen.
Wie man eine Klasse, die Zeichenobjekte modelliert, erstellt kann ich mir zur Zeit noch nicht vorstellen, wird später gemacht ... .
 
Wie man das Ergebnis(modified) für Ausschnitte..... - kann ich mir gerade noch nicht vorstellen.
Du kannst ja Ereignisse definieren, wie Du lustig bist und den Methoden kann man Objekte mitgeben, die das Ereignis näher beschreiben.

Wenn Du weißt: ok, der Zeichnung wurde eine Figur hinzugefügt, diese hat eine Bounding-Box x,y,w,h, dann kann statt einem kompletten repaint auch die zu zeichnende Region mitgegeben werden. Das Graphics-Objekt bekommt dann die clipping region gesetzt und Dein Zeichencode kann damit nur die relevanten Objekte zeichnen. Ob sich eine solche Optimierung lohnt, hängt natürlich vom Einzelfall ab.
 
Ich weiß das auch noch nicht.
Bisher ist meine Zeichnung nicht kompliziert und wird durch die Fenstermaße begrenzt (innerhalb getWidth(), getHeight()).
Muß ein wenig herum testen und Beispiele suchen. Irgendwie möchte ich, daß der Code auch gut ist. Vielleicht poste ich das am Ende, falls es klappt.
 

Zurück
Oben