Swing Noch ein Zeichenprogramm...

beastofchaos

Bekanntes Mitglied
Hallo Leute, ich hab in den letzten Wochen an einem etwas größeren Projekt gearbeitet und dabei auch schon viel hier rumgefragt und Threads erstellt. Anstatt bei jedem Problem einen Thread zu eröffnen, der dann nur 5 Beiträge lang ist. Werd ich hier alle möglichen Probleme zu dem Programm posten, um der Übersichtlichkeit beizutragen ;)

Also vorerst - wie der Threadname schon sagt - ist es ein Zeichenprogramm mit vielen Features und noch vielen kommenden Features :D Im Moment hab ich es geschafft, dass ich per Strg-X ein Bild nicht nur in die Zwischenablage lege, sondern auch ihre vorherige Position "unsichtbar" mache. Damit das so aussieht wie bei Paint oder Gimp, hab ich hinter mein Zeichen-JPanel ein weiteres JPanel gelegt, auf das ich ein grau-weiß kariertes Muster male. Dieses wird beim Ausschneiden per Strg+X sogar sichtbar und alles funktioneirt in der Hinsicht gut. Bloß hab ich dann weiter mit strg-X und Strg-V rumprobiert und mir fiel auf, dass ich es nicht schaffe, ein Bild mit einer "leeren" Stelle (durch Strg-X erzeugte Stellen) nicht in die Zwischenablage legen kann, ohne dass die Stelle beim Einfügen in Paint weiß wird. Andersrum hab ich bei Paint ein Bild gemacht mit "leeren" Stellen und es bei meinem Programm eingefügt. Auch da werden die "leeren" Stellen weiß.

Hier mal meine Klasse mit der Methode, die das Bild in die Zwischenablage legt (setClipboard());
Java:
public class ClipboardAdmin implements ClipboardOwner{
    public static void setClipboard(BufferedImage img){
        ClipboardAdmin admin = new ClipboardAdmin();
        TransferableImage transImg = admin.new TransferableImage(img);
        Clipboard clBo = Toolkit.getDefaultToolkit().getSystemClipboard();
        clBo.setContents(transImg, admin);
    }
    
    ...
    ...
    
    private class TransferableImage implements Transferable {
        
        Image img;
        
        public TransferableImage( Image i ) {
            img = i;
        }
        
        public Object getTransferData( DataFlavor flavor )
        throws UnsupportedFlavorException, IOException {
            if ( flavor.equals( DataFlavor.imageFlavor ) && img != null ) {
                return img;
            }
            else {
                throw new UnsupportedFlavorException( flavor );
            }
        }
        
        public DataFlavor[] getTransferDataFlavors() {
            DataFlavor[] flavors = new DataFlavor[ 1 ];
            flavors[ 0 ] = DataFlavor.imageFlavor;
            return flavors;
        }
        
        public boolean isDataFlavorSupported( DataFlavor flavor ) {   
            DataFlavor[] flavors = getTransferDataFlavors();   
            for ( int i = 0; i < flavors.length; i++ ) {
                if ( flavor.equals( flavors[ i ] ) ) {
                    return true;
                }
            }
            return false;
        }   
    }
}

Unf auf diese Weiße lösch ich dann die vorhandene Stelle. Nebenbei des.getLocation() gibt die Position der Auswahl in meinem ZeichenPanel und getSize() folglich deren Größe wieder (in Form von Points),
Java:
public void delete(){
    	SelectionDesign des = main.centerPanel.selection;
    	BufferedImage oldImg = main.centerPanel.paints.getImage();
    	BufferedImage newImg = new BufferedImage(oldImg.getWidth(), oldImg.getHeight(), BufferedImage.TYPE_INT_ARGB);
    	
    	Graphics2D g2d = newImg.createGraphics();
    	try{
	        if (des.getDrawType() == ShapeDesign.RECTANGLE){
	        	g2d.fillRect(des.getLocation().x, des.getLocation().y, des.getSize().x, des.getSize().y);
	        }
	        else if (des.getDrawType() == ShapeDesign.ELLIPSE){
	        	g2d.fillOval(des.getLocation().x, des.getLocation().y, 
	                    des.getSize().x, des.getSize().y);
	        }

	        g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OUT));
	    	main.centerPanel.paints.draw(g2d);
	    	main.centerPanel.paints.setImage(newImg);
    	} finally { 
    		g2d.dispose();
    	}
        main.centerPanel.repaint();
    }

Wenn ihr noch etwas nicht in meinem Quellcode nicht versteht, sagt bitte bescheid. Wäre jetzt vll. zu aufwendig zu erläutern, wie mein ganzes Programm strukturiert ist :p

Gruß, Thomas
 
Zuletzt bearbeitet:

GUI-Programmer

Top Contributor
Ohne mir dein Programmcode durchgelesen zu haben, kann ich dir sagen, das ich die Erfahrung gemacht habe, dass wenn man ein
Bild öffnet, (z.B. jpg oder gif oder png) es kopiert und dann bei Paint einfügt, etwas daran verändert, immer die Stellen die vorher
durchsichtig, also transparent waren, nach dem Speichervorgang weiß waren. Ich glaube man wird von Paint sogar darauf hingewießen,
dass die Transparenz verloren geht. Bei Gimp ist das nicht so.
Vielleicht war ja das schon die Lösung, wenn nicht muss ich mir wohl doch mal deinen Code durchlesen und nicht nur überfliegen.
 

beastofchaos

Bekanntes Mitglied
So, hallo Leute. Ich hätte da mal ein kleines Problem, was dem vorherigem Problem ähnelt. Also man kann ja die Composite bei Graphics2D einstellen, so dass etwas nur halb gezeichnet wird, gar nicht, oder sich iwie mischt mit dem vorherigen.
Ein Beispiel für 50%iges Malen:
Code:
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));

Ein Beispiel für ein Löschen der vorherigen Zeichnung:
Code:
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_OUT));

Alle möglichen Kompositionen von AlphaComposite heißen meist etwas mit DST oder SRC und unterscheiden sich in der Zusammenrechnung (Die Funktionen stehen in der Dokumentation von den einzelnen Konstanten). Für mich ist jetzt die Frage, wenn ich ein Bild habe, was in der Mitte ein "Loch" hat (wo nichts gezeichnet worden ist), wie ich es schaffe, dass diese leere Stelle die vorherige Zeichnung mitwegnimmt. Also das Loch von dem "Source"(SRC) sich nicht vermischt mit der "Destination"(DST).

Ich hab mal ein Vorführvideo gemacht, in dem ihr seht, wie ich erst eine Stelle lösche (das funktioniert mit AlphaComposite.CLEAR) Dann ein Bild "nehme", wo ein Teil dieses leeren Bereiches ist und dann dieses Bild hin und her ziehe. Das Problem, dass die leere Stelle im Bild das andere nicht überschreibt. Hab, glaub ich alle Kompositionen ausprobiert, aber es kommt nie auf was besseres raus... :/
Im Moment abreitet das SRC_ATOP, funktioniert hier aber genauso wie SRC_OVER.

Das Video könnt ihr hier kurz runterladen: Megaupload - Selektierungs_Probleme
Gruß, Thomas

PS: Ich hab grad durch Zufall herausgefunden, dass das alte Problem mit der Transparenz im Clipboard innerhalb meines Programms behoben ist, aber halt in Paint.NET statt transparent wieder schwarz ist, aber es soll ja auch in meinem Programm funktionieren, nicht wahr? :D
 

Michael...

Top Contributor
Ich hab mal ein Vorführvideo gemacht
kann ich hier nicht runterladen
Dann ein Bild "nehme", wo ein Teil dieses leeren Bereiches ist und dann dieses Bild hin und her ziehe. Das Problem, dass die leere Stelle im Bild das andere nicht überschreibt.
Ich interpretiere dies wie folgt: Es existiert ein Bild mit einem transparenten (Kreis)Ausschnitt, welches über ein anderes Bild gelegt wird?
Dein Problem ist, dass das untere Bild durch den transparenten Ausschnitt sichtbar ist? Ist ja nicht verwunderlich, das ist die Eigenschaft von Transparenz ;-)

Vielleicht beschreibst Du mal, was Du erreichen willst und postest eventuell noch ein bisschen Code dazu.
 

beastofchaos

Bekanntes Mitglied
Also ich hab schon mal eine Möglichkeit gefunden, dass man die Transparenz die DST "überschreibt", indem man ein Objekt der Klasse ClearDesign auf das Bild legt.
Hier mal diese Klasse ClearDesign:
Java:
public class ClearDesign extends Design{
	private Area area;
	
	public ClearDesign(){
		this(null);
	}
	
	public ClearDesign(Area area){
		this.area = (area == null) ? new Area() : area;
	}
	
	//------------------------------------------------------------//
	public void setArea(Area area){
		this.area = area;
	}
	
	public void setArea(Shape shape){
		setArea(new Area(shape));
	}
	
	//------------------------------------------------------------//
	
	public Area getArea(){
		return area;
	}
	
	//------------------------------------------------------------//
	@Override
	public void draw(Graphics g){
		Graphics2D g2d = (Graphics2D)g;
		Composite oldComposite = g2d.getComposite();
		g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR));
		g2d.fill(area);
		g2d.setComposite(oldComposite);
	}
	
	@Override
	public Design clone(){
		return new ClearDesign((Area)getArea().clone());
	}
}

In der draw-Methode seht ihr, dass ich mittels AlphaComposite.CLEAR das darunter lösche.
Mich wundert aber, dass das nur bem ClearDesign geht. Nebenbei könnt ihre eine Vorführung dessen auch im Video sehen. Da lösche ich erst eine Stelle und schneide dann ein Bild mit diesem Loch aus.

Aber leider funktioniert diese ClearDesign nur in diesem Fall. Wenn ich bei jedem ImageDesign(eine Klasse, die ein Bild trägt und dieses in der draw-Methode zeichnet) in der draw-Methode folgendes einfüge:
Java:
@Override
public void draw(Graphics g) {
	super.draw(g);

    	ClearDesign clear = new ClearDesign(new Area(getRectangle()));      // Eingefügt
    	clear.draw(g);

	((Graphics2D)g).setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
	g.drawImage(getImage(), getLocation().x, getLocation().y, null);
}

Dann zeigt es nicht den Hintergrund oder nur sich selber, sonder an jeder transparenten Stelle wird schwarz gemalt.

Das Video kann man im Link runterladen, den ich im letzten Post angegeben habe

Gruß, Thomas

Edit: Wer will kann sich auch mal das SelectionDesign anschaun, welches ein ImageDesign trägt und die blaue Markierung immer zeichnet:

Java:
private void draw(Graphics2D g){
        Composite oldComposite = g.getComposite();
        Stroke oldStroke = g.getStroke();
        
        if (imageDes != null){
                // Hatte es auch an der Stelle ausprobiert:
                //    	ClearDesign clear = new ClearDesign(new Area(getRectangle()));
                //    	clear.draw(g);
        	getImageDesign().draw(g);           // FEHLER: Leere Stellen in der SRC übschreiben nicht die Destination !!
        }
        
        drawSelecter(g);         // Zeichnet die blaue Markierung
        
        g.setStroke(oldStroke);
        g.setComposite(oldComposite);
    }
 
Zuletzt bearbeitet:

Michael...

Top Contributor
So ganz hab ich's nicht immer noch nicht verstanden. Du willst scheinbar einen Bereich eines Bildes löschen? Warum nimmst Du dann nicht CLEAR oder DST_OUT (SRC darf dabei nicht transparent sein)?
 

beastofchaos

Bekanntes Mitglied
Naja. Löschen kann ich ja auch (siehe Video). Das sieht dann so aus:

Java:
public void delete(){
    SelectionDesign des = Saves.properties.selection;     // Unwichtig
    Saves.properties.process.add(new ClearDesign(des.createArea(true)));         // Hinzufügen des ClearDesigns zu einer ArrayList von Designs, die alle auf ein Bild gemalt werden.
    Saves.properties.selection.setImageDesign(null);      // Unwichtig
}

Das funktioniert nämlich mit dem ClearDesign - Code hab ich ja schonmal gepostet.

Aber ich will ja ein Bild über ein andres legen, wobei das obere transparente Stelle haben soll, die sich aber nicht mit dem darunter liegendem "vermischen" sollen, sondern diese Stellen sollen auch bei der Zusammenmischung durch das Composite transparent bleiben. Ich glaube langsam auch zu verstehen, wie die ganzen AlphaComposites funktionieren.
Ein Beispiel an AlphaComposite_SRC_OVER - In der Dokumentation steht:
Java:
/**
     * The part of the destination lying outside of the source
     * replaces the destination
     * (Porter-Duff Destination Held Out By Source rule).
     *<p>
     * <em>F<sub>s</sub></em> = 0 and <em>F<sub>d</sub></em> = (1-<em>A<sub>s</sub></em>), thus:
     *<pre>
     * 	<em>A<sub>r</sub></em> = <em>A<sub>d</sub></em>*(1-<em>A<sub>s</sub></em>)
     * 	<em>C<sub>r</sub></em> = <em>C<sub>d</sub></em>*(1-<em>A<sub>s</sub></em>)
     *</pre>
     */

Wegen dem HTML-Code schwer lesbar, aber ich schreib euch die Formeln nochmal raus:
A.r = A.d * (1-A.s)
C.r = C.d * (1-C.s)

A ist der Alphawert (Sichtbarkeit) und C die Color(Farbe). A.r ist folglich das Ergebnis, A.d der bereits vorhandene Wert und A.s ist der Wert der draufgelegten Zeichnung.
Ist also in meinem Bild iwo Der Alphawert == 0 (Transparent), kommt die Transparenz des Ziels raus (A.d).
Das selbe gilt für die Farbe dann natürlich auch.

Ich dachte mir jetzt, dass also AlphaComposite_SRC das perfekte wäre, weil dort die Formel wie folgt lautet:
A.r = A.s
C.r = C.s

Das hieße doch, dass wen ich eine transparente Stelle im draufgelegten Bild habe, bleibt die auch so im Ergebnis !? Nein, stattdessen wird die Stelle schwarz... Das ist für mich unverständlich und genau da häng ich auch.
Hab jetzt alles ausprobiert und frag mich grad, ob man selbst iwie Composites erstellen kann, die dann eine eigene Formal enthalten würden. Damit käme ich sicher iwann zum richtigen Ergebnis , aber leider versteh ich die Struktur in den Klassen Composite, CompositeContext, ColorModel, Raster und weiteren nicht.
Meine Befürchtung ist, dass die Composite-Klassen selbst nicht diese Berechnung enthaltne, sondern dass iwo im Anwendungsbereich (iwo in Graphics2D oder so) die Rechnungen enthalten sind und er einfach per switch abfragt, welche Composite er da hat. So käme ich nie zu einer "Custom-Composite" Klasse. Wer echt super, wenn da jemand weiter weiß. Ich werd jetz nochmal in meinem Programm ein bisschen ausprobieren, glaub aber nicht, dass ich es gebacken bekomme.

Gruß, Thomas
 
Zuletzt bearbeitet:

Michael...

Top Contributor
Sorry, je mehr Du hier schreibst, desto weniger verstehe ich das Problem.
Naja. Ich will ja ein Bild über ein andres legen, wobei das obere transparente Stelle haben soll, die sich aber nicht mit dem darunter liegendem "vermischen" sollen, sondern diese Stellen sollen auch bei der Zusammenmischung durch das Composite transparent bleiben.
Was heisst "nicht ... vermischen" und "transparent" bleiben?
Wegen dem HTML-Code schwer lesbar, aber ich schreib euch die Formeln nochmal raus:
Das kann man ganz bequem in der API ohne HTML-Tags nachlesen. z.B.: AlphaComposite#CLEAR
Das hieße doch, dass wen ich eine transparente Stelle im draufgelegten Bild habe, bleibt die auch so im Ergebnis !? Nein, stattdessen wird die Stelle schwarz... Das ist für mich unverständlich und genau da häng ich auch.
Wie wird da was schwarz? Wie sieht der Code dazu aus? Bsp.Code ist immer hilfreich. Am besten kurz und direkt kompilier und ausführbar.
Man müsste halt echt genau wissen was Du machst und was rauskommen soll. Wenn Du die Bilder einfach übereinander legst schaut das anderere an den transparenten Stellen des oberen durch. Wenn Du die per Composite SRC übereinander auf ein transparentes Bild fügst "überträgt" sich die Transparenz nach unten.
 

Michael...

Top Contributor
So beim Schreiben und dem Stichwort "schwarz" ist mir was eingefallen:
Kann es sein das Du du die AlphaComposites auf das Graphics Objekt der Komponente (JPanel, JComponent...) anwendest? Das funktioniert so nicht und es kann durchaus sein, dass hier der schwarzer Fleck herrührt.

Deswegen habe ich ja auch in dem Bsp aus dem anderen Post zuerst auf ein BufferedImage (ARGB) gezeichnet und auf der Komponente einfach nur das Bild abmalen lassen.
 
Zuletzt bearbeitet:

beastofchaos

Bekanntes Mitglied
Genau da LAG mein Problem. Hab jetzt ewig gebastelt und ein Testprogramm gemacht, bis ich drauf kam, dass man nicht direkt auf das Panel etwas unsichtbares machen kann, da dann stattdessen schwarz entsteht.

Vll schreib ich ja wirklich zu viel, aber bei deinem vorherigen Kommentar(wo ich Danke gesagt habe) hast du in den letzten beiden Sätzen mein Problem gut ausgedrückt:
Wenn Du die Bilder einfach übereinander legst schaut das anderere an den transparenten Stellen des oberen durch. Wenn Du die per Composite SRC übereinander auf ein transparentes Bild fügst "überträgt" sich die Transparenz nach unten.



Es funktioniert jetzt so, dass ich erst ein Bild mit den entsprechenden Größen mache und darauf dann alles zeichne.

Wer Lust hat, hier nochmal ein Vorführvideo, wie es jetzt ist und erstmal bleiben soll (bzw. später bau ich die Möglichkeit von beiden Composites ein) :
-> MEGAUPLOAD - The leading online storage and file delivery service


Kann sein, das ich noch heute Abend mit einer neuen Knobelaufgabe ankomme. Hab in letzter Zeit ein paar für mich nicht lösbare Aufgaben gesammelt und die einfach weg gelassen, das will ich jetzt mal nachholen. Werd mich dann aber deutlicher ausdrücken, damit es nicht wieder Probleme gibt ;)

Gruß, Thomas.


Edit:
- "vermischen" meint, wie sich SRC und DST verbinden durch die Composite.
- "transparent" ist selbsterklärend
 
Zuletzt bearbeitet:

beastofchaos

Bekanntes Mitglied
Problem gelöst, Post lassen sich wieder mal nicht löschen

Hallo, das nächste Problem ist gerade, dass ich ein Dialog erstellt hab, das als TextEditor fungiert -> in der Mitte eine JTextArea und ob ein JPanel mit FlowLayout, in dem sich Buchstabengröße, Schriftname und Einstellungen wie Fettgeschrieben, Kursiv, Unterstrichen und Durchgestrichen machen lassen. Das Problem, liegt leider in genau diesen Eigenschaften. Am besten zeig ich euch mal die Klasse, die diese Eigenschaften "trägt" und zeichnet. Müsst sie erstmal nicht anschaun, da ihr es noch nicht braucht zum Verstehen.
Java:
public class TextDesign extends Design {
	private String text;
	private Font font;
	
//------Konstruktoren------------------------------------------------------------------------------------------//

	public TextDesign(){
		this("", new Point(0, 0), new Point(0, 0), Color.black, 1);
	}
	
	public TextDesign(String text, Point newLoc, Point newSize, Color color, int newPenWidth) {
		this(text, newLoc, newSize, color, Color.white, newPenWidth, true);
	}
	
	public TextDesign(String text, Point newLoc, Point newSize, Color color, Color secColor, int newPenWidth, boolean leftClicked) {
		super(newLoc, newSize, Design.TEXT, newPenWidth, color, secColor, leftClicked);
		this.text = text;
		this.font = new Font("SansSerif", Font.PLAIN, 12);
}
	
//------Setter-------------------------------------------------------------------------------------------------//
	
	public void setText(String text) {
		this.text = text;
	}
	
	public void addLetter(char c){
		setText(getText() + c);
	}
	
	public void removeLetter(){
		setText(getText().substring(0, text.length() - 3));
	}
	
	public void setFont(Font font){
		this.font = font;
	}
	
	public void setFontSize(int size){
		setFont(new Font(getFont().getName(), getFont().getStyle(), size));
	}
	
	public void setFontName(String name){
		setFont(new Font(name, getFont().getStyle(), getFont().getSize()));
	}
	
	public void setFontStyle(int style){
		setFont(new Font(getFont().getName(), style, getFont().getSize()));
	}
	
//------Getter-------------------------------------------------------------------------------------------------//
	
	public String getText(){
		return text;
	}
	
	public Font getFont(){
		return this.font;
	}
	
//------Anderes------------------------------------------------------------------------------------------------//
	
	@Override
	public void draw(Graphics g){
		super.draw(g);
		g.setFont(getFont());
		g.drawString(getText(), getLocation().x, getLocation().y);
	}

    @Override
    public Design clone(){
        return new TextDesign(getText(), getLocation(), getSize(), getColor(), getSecColor(), getPenWidth(), isLeftClicked());
    }
}

Breite, kursiv und all das werden ja eig. im Font-Style übergeben. Ein Font mit Fett und Kursiv würde z.B. so aussehen:
Code:
new Font("FontName", Größe, Font.BOLD | Font.ITALIC);

Wie kann ich das jetzt am besten umsetzen, dass ich die boolean-Werte von den JToggleButton (mit diesen soll die Effekte eingestellt werden) in so einen Integer-Mix umwandel. ich könnte jetzt halt so anfangen:
Java:
if (tbBold.isSelected() && !tbItalic.isSelected() && !tbUnderlined.isSelected() && !tbCrossedOut.isSelected()){
    textDesign.setFontStyle(Font.BOLD);
}
else if(...

Ihr seht vll., dass bei 4 verschiedenenButtons viele Kombination möglich sind (korrekt sind es 5 Kombinationen, aber das ist schon zu viel für einen übersichtlichen Code). Wie schaffe ich es nun diese Boolean-Werte am besten in so einen "Integer-Mix" bastle?

Gruß, Thomas
 
Zuletzt bearbeitet:

beastofchaos

Bekanntes Mitglied
So, ich hab wass ausprobiert und was rausgefunden. Und zwar wird der Wert Font.PLAIN (normal) wie null gewertet. Das heißt ich kann 4 Integer aufbauen und jedem per Abfrage entweder den jeweiligen Wert (z.B. Font.BOLD) oder sonst Font.PLAIN. Wenn ich "Font.PLAIN | Font.BOLD | Font.PLAIN" mache, wird es z.B. fett geschrieben und die PLAIN-Werter werden ignoriert. Ein guter Lösungsansatz schon mal.

Aber jetzt ist das Problem, wie ich aus dem Font-Style das wieder rausfilter. Ich kann ja per getFont().getStyle() ganz leicht das ermitteln. Jetzt frag ich mich grad, wie man die Methode "isBold()" konstruiert. Habs noch nicht ausprobiert, aber ginge es so?
Code:
return getFont().getStyle() == Font.BOLD;

Sprich gibt es true zurück, wenn in so einem Integer-Mix diese eine Integer-Zahl vorkommt?


Gruß, Thomas

Edit: Problem gelöst, ich werds mal nicht löschen, aber ich stell gleich mal die Lösung dafür vor: Also erstens kann man mit dem Style nur BOLD und ITALIC angeben. Unterstrichen und Durchgestrichen lässt sich so wie hier lösen
-> Was ist der konstante Wert der Unterstrichen Schriftart in Java?
-> TextAttribute: Underline and strike through
Zweitens sind in meinen Fragen die Antworten schon halb versteckt, weshalb ich jetzt alles selbst hinbekommen habe :D

Ich versuchs jetzt damit und ich denke, ich komme damit jetzt auch alleine klar, Tschuldigt, dass ich um Aufmerksamkeit gerungen habe ;)
 
Zuletzt bearbeitet:

beastofchaos

Bekanntes Mitglied
Hey, Leute.
Hier ist das nächste Problem. Ich versuche grad, bei einem Image die Transparenz beim Zeichnen zu halten. Es geht darum, dass, wenn ich ein Bild mit einem transparenten Loch auf was andres zeichne in Graphics, dass die Durchsichtige Stelle das darunter zeigt an der Stelle. Das Thema gabs weiter oben schonmal und wurde eigentlich mit der Composite AlphaComposite.SRC gelöst. Das doofe ist bloß daran, dass, wenn das Bild eine Ellipse sein soll, wird bei SRC das um die Ellipse herum mitgezeichnet. Hier mal ein Beispiel, wie ich eine Ellipse von einem Bild ausschneide:
Java:
    public static BufferedImage getOval(BufferedImage img){
    	int w = img.getWidth();
        int h = img.getHeight();
        BufferedImage newImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = newImage.createGraphics();
        try{
        	g2d.fillOval(0, 0, w, h);
        	g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_IN));
        	g2d.drawImage(img, 0, 0, null);
        } finally {
        	g2d.dispose();
        }
        return newImage;
    }

Das selbe versuch ich nun durch die Klasse Area. Mein Zeil dabei ist aber auch, dass ich das ganze so eng wie möglich gestalte, sprich das Bild soll den "Umfang" der Area habe. Das ist eigentlich leicht durch
Code:
image.getSubImage(area.getBounds())
zu lösen, aber wenn die Koordinaten außerhalb des Bildes liegen, muss ich das vorher korrigieren, damit keine Exception geworfen wird. Hier die Methode dafür:
Java:
    public static BufferedImage getAreaImage(BufferedImage img, Area area){
        BufferedImage newImage = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = newImage.createGraphics();
        try{
        	g2d.setStroke(new BasicStroke(0, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 0));
        	g2d.fill(area);
        	g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_IN));
        	g2d.drawImage(img, 0, 0, null);
        } finally {
        	g2d.dispose();
        }
        int maxW = newImage.getWidth();
        int maxH = newImage.getHeight();
        int x = area.getBounds().getLocation().x;
        int y = area.getBounds().getLocation().y;
        int w = area.getBounds().getSize().width;
        int h = area.getBounds().getSize().height;
        x = Math.max(Math.min(area.getBounds().getLocation().x, maxW), 0);
        y = Math.max(Math.min(area.getBounds().getLocation().y, maxH), 0);
        BufferedImage returner = null;
        try{
        	returner = newImage.getSubimage(
        		x, 
        		y,
        		(x+w > maxW) ? maxW - x : (x+w < 0) ? 0 : w, 
        		(y+h > maxH) ? maxH - y : (y+h < 0) ? 0 : h);
        } catch(RasterFormatException e){
        	// Weite oder Höhe des Subimages ist gleich 0
        	return newImage;
        }
        return returner;
    }

Zurück zum Anfang: Ich hab jetzt statt SRC die Composite AlphaComposite.SRC_OVER genommen, wo die Transparenz wieder das darunter zeigt, was ich ja eig nicht will. Um das zu beheben zeichne ich die Area darunter "löschend". Also:
Java:
                g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR));
		if (area != null)
			g2d.fill(area);

Das Problem ist jetzt, dass diese gelöschte Fläche leicht verschoben ist. Im Anhang seht ihr ein Bild, wo ich einen ellipse-artigen Ausschnitt gemacht habe (ist aber eine Area) und ihn zu Seite geschoben wird, das, was auf die Seite geschoben wurde, ist nun so ein Image, dass "unter sich" erst alles löscht. Ihr seht, dass da ein kleines bisschen von dem Gelöschten links rausschaut. Ich vermute, da in Tests der Fehler nicht aufgetreten ist und auch im Debugger ich anschaun konnte, dass die beiden Areas (die eine Löschende und die andere, die das Bild ausschneidet) exakt gleich sind, dass mein Fehler iin der Methode "getAreaImage()" liegt, mit dem ich das area-artige Bild ausschneide. Könnt ihr euch das mal kurz durchschaun und sagen, ob meine Berechnungen richtig sind (s.o.)?

Gruß, Thomas

PS: Leider wird die Transparenz im Bild im Browser weiß angezeigt (bei mir in Iron, also Chrome zumindest so), aber ihr könnt es ja in Paint öffnen oder ein bisschen hin und her ziehen, dann sieht man ein bisschen was :D


EDIT: Das passiert übrigens nur bei einer runden Form. Bei Rechtecken fuktioniert es in jedem erdenklichen Winkel. Bei Ellipsen sieht es zwar so aus, als wäre es verschoben, aber anscheinend wird bei den Rändern einfach nur etwas mehr gezeichnet
 

Anhänge

  • DrobBox-Show2.png
    DrobBox-Show2.png
    9,2 KB · Aufrufe: 28
Zuletzt bearbeitet:

beastofchaos

Bekanntes Mitglied
->Kurzfassung:

Wie erhalte ich einen Area-Ausschnitt aus einem Bild bzw. funktioniert diese Methode richtig?

Java:
    public static BufferedImage getAreaImage(BufferedImage img, Area area){
        BufferedImage newImage = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = newImage.createGraphics();
        try{
            g2d.setStroke(new BasicStroke(0, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 0));
            g2d.fill(area);
            g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_IN));
            g2d.drawImage(img, 0, 0, null);
        } finally {
            g2d.dispose();
        }
        int maxW = newImage.getWidth();
        int maxH = newImage.getHeight();
        int x = area.getBounds().getLocation().x;
        int y = area.getBounds().getLocation().y;
        int w = area.getBounds().getSize().width;
        int h = area.getBounds().getSize().height;
        x = Math.max(Math.min(area.getBounds().getLocation().x, maxW), 0);
        y = Math.max(Math.min(area.getBounds().getLocation().y, maxH), 0);
        BufferedImage returner = null;
        try{
            returner = newImage.getSubimage(
                x, 
                y,
                (x+w > maxW) ? maxW - x : (x+w < 0) ? 0 : w, 
                (y+h > maxH) ? maxH - y : (y+h < 0) ? 0 : h);
        } catch(RasterFormatException e){
            // Weite oder Höhe des Subimages ist gleich 0
            return newImage;
        }
        return returner;
    }

PS: Was heißt KSKB? :D (meine Suche hat ergeben: "Kolej Sains Kesihatan Bersekutu")
 

Marco13

Top Contributor
Dass du nach >180 Beiträgen noch nicht weißt, dass KSKB für "Kleines Selbstständig Kompilierbares Beispiel" steht (und auch nicht auf die Idee gekommen bist, mit der Maus über die Abkürzung zu fahren, und das im Tooltip zu lesen) kann ich mir kaum vorstellen ;)

Insgesamt müßte ich wohl mehr vom Thread lesen, um rauszufinden, was du vorhast. Irgendwie sagt die Kristallkugel in meinem Bauch (nom, nom, nom...) dass das, was du vorhast, mit einer Area und einem passenden TexturePaint zu erreichen wäre... aber... da muss ich nochmal genauer schauen...
 

beastofchaos

Bekanntes Mitglied
Okay, ich lern mir kurz mal TexturePaint an und schau, ob das wirklich was hilft ;) Klar weiß ich, dass Tests und kleine Beispiele gut sind, aber ich kannte den Begriff noch nicht. Beim Herüberfahren kam bei mir vorher iwie nichts. Jetzt schon :D
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
M JavaFX Mandelbrot-bild noch nicht optimiert AWT, Swing, JavaFX & SWT 7
M JavaFX kann man da noch was am code vereinfachen design technisch sieht nicht richtig aus... AWT, Swing, JavaFX & SWT 15
K Wie kann ich noch den scale bekommen, außer mit getScaleX oder getScaleY? AWT, Swing, JavaFX & SWT 1
P Swing GUI noch nicht gezeichnet - Logik läuft - blockiert AWT, Swing, JavaFX & SWT 3
P Swing Nach removeAll() noch 1 Element vorhanden AWT, Swing, JavaFX & SWT 0
G noch eine Frage zum EventDispachThread AWT, Swing, JavaFX & SWT 4
D SWT TreeViewer: Daten aus Model gelöscht... trotzdem noch im Baum AWT, Swing, JavaFX & SWT 4
R Noch einmal x^2 bzw. parabel AWT, Swing, JavaFX & SWT 2
V Swing Neue Größe bei ComponentListener noch nicht verfügbar? AWT, Swing, JavaFX & SWT 3
S 3D-Grafik Java3D und was noch? AWT, Swing, JavaFX & SWT 3
T Event Dispatch Thread und noch ein Thread AWT, Swing, JavaFX & SWT 7
Nicer LookAndFeel Suche noch LaFs AWT, Swing, JavaFX & SWT 7
2 Werde Java GUIs immer noch mit dem in die Jahre gekommen Swing gemacht? AWT, Swing, JavaFX & SWT 12
M SWT Mutter-Shell blocken während Tochter-Shell noch offen ist AWT, Swing, JavaFX & SWT 6
R noch ein DoubleBuffering Noob AWT, Swing, JavaFX & SWT 10
S Swing noch nicht übergebenen Wert aus JComboBox auslesen AWT, Swing, JavaFX & SWT 4
S Swing Fenster schliessen, javaw noch im Speicher AWT, Swing, JavaFX & SWT 5
U JList mit Hintergrundbild hinterlegen und noch ne Frage AWT, Swing, JavaFX & SWT 4
S Weder ActionListener noch Graphics wollen so recht AWT, Swing, JavaFX & SWT 3
G JTree mouseClicked -> kontrolle ob noch ein unterknoten e AWT, Swing, JavaFX & SWT 2
A Noch mal Zusammenarbeit Java und HTML AWT, Swing, JavaFX & SWT 4
A Noch mals Probleme mit Login AWT, Swing, JavaFX & SWT 3
G Text eines noch aktiv editierten Textfeldes lesen AWT, Swing, JavaFX & SWT 2
H Noch einmal JList (nichts auswählen) AWT, Swing, JavaFX & SWT 2
C AWT, Swing & was sonst noch. AWT, Swing, JavaFX & SWT 11
E Toturial weg! Hat noch wer ne Kopie! AWT, Swing, JavaFX & SWT 3
U sporadisches Deadlock und noch ein Schmankerl ;) AWT, Swing, JavaFX & SWT 9
M Es bleibt immer noch eine Javaw instanz zurück AWT, Swing, JavaFX & SWT 3
H Swing nach schließen noch sichtbar AWT, Swing, JavaFX & SWT 4
J JavaFX JavaFX Canvas einfaches Zeichenprogramm AWT, Swing, JavaFX & SWT 7
U JavaFX Zeichenprogramm mit JavaFX FXML AWT, Swing, JavaFX & SWT 7
T 2D-Grafik Tutorial für ein einfaches Zeichenprogramm! AWT, Swing, JavaFX & SWT 2
Q Swing Zeichenprogramm, grundlegende Fragen AWT, Swing, JavaFX & SWT 8
J kleines Zeichenprogramm AWT, Swing, JavaFX & SWT 12
K Probleme mit Zeichenprogramm AWT, Swing, JavaFX & SWT 14

Ähnliche Java Themen

Neue Themen


Oben