kl. Malprogramm-Problem



  • Hallo Leute ich bastel zur Zeit an einem kleinen Grafikprogramm.

    So einiges hat schon funktioniert nur jetzt stehe ich vor einem Problem.
    Man soll nicht mehr links oben und rechts unten klicken und dann wird zwischen den Koordinaten ein Kreis bzw. Rechteck gemalt sondern man soll das Rechteck malen indem man die MAus drückt und es dann auf die Größe zieht wie es werden soll.

    Ich habe es so versucht:
    Male Rechteck zwischen der MouseDown-Koordinate und der aktuellen MouseDrag Koordinate und wenn sich was verändere repaint mit neuen Koordinaten.

    Das klappt auch soweit nur 1. flackert das Rechteck und 2. kann ich nicht zwei Rechtecke in das Applett malen.

    Wie kann ich also den Bildinhalt speichern sobald man die Maus loslässt.
    Oder kann man auch nen unsichtbares LAyer einschieben sobald man die Maus los lässt und dann malt man das zweite Rechteck auf nem neuen Layer.

    Wie geht sowas ?

    Hier mal der Source für einen Teil des Programms:

    package malprogramm;
    
    import java.awt.*;
    import java.awt.event.*;
    import java.applet.*;
    
    public class Malen extends Applet implements ActionListener {
    
      private Image dbImage;
      private Graphics dbg;
      Image aktuell;
    
      int x1,y1,x2,y2,m,i=0;
      int start,ende;
      int hoch,breit;
      int x22,y22;
      String modus="";
    
      Button leeren= new Button("Lösche Bildschirminhalt");
      Button rund= new Button("Kreis");
      Button eckig= new Button("4-Eck");
    
    public int zz(int m){
    return(int)Math.round(Math.random()*m);
    }
    
    public void init()
      {
        setLayout(null);
        leeren.setBounds(220,10,160,30);
        leeren.addActionListener(this);
        this.add(leeren);
    
        rund.setBounds(55,10,160,30);
        rund.addActionListener(this);
        this.add(rund);
    
        eckig.setBounds(385,10,160,30);
        eckig.addActionListener(this);
        this.add(eckig);
      }
    
    public boolean mouseDown (Event e,int x1,int y1)
      {
        start=x1;
        ende=y1;
        x2=0;
        y2=0;
        return true;
      }
    
    public boolean mouseDrag (Event e, int x2, int y2)
    {
        Graphics g= getGraphics();
    
        if(x22!=x2&&y22!=y2)
        {
          repaint();
        }
    
        x22=x2;
        y22=y2;
    
        breit=-(start-x2);
        hoch=-(ende-y2);
    
        if(modus=="viereck")
        {
        g.drawRect(start,ende,breit,hoch);
        }
    
        if(modus=="kreis")
        {
        g.drawOval(start,ende,breit,hoch);
        }
    
        return true;
    }
    
    public void paint(Graphics g)
    {}
    
    public void update (Graphics g)
    {
    if (dbImage == null)
    {
    dbImage = createImage (this.getSize().width, this.getSize().height);
    dbg = dbImage.getGraphics ();
    }
    dbg.setColor (getBackground ());
    dbg.fillRect (0, 0, this.getSize().width, this.getSize().height);
    dbg.setColor (getForeground());
    paint (dbg);
    g.drawImage (dbImage, 0, 0, this);
    }
    
    public void actionPerformed(ActionEvent e)
      {
        String click = e.getActionCommand();
        Graphics g = getGraphics();
    
        if (click.equals("Lösche Bildschirminhalt"))
        {
        repaint(20);
        }
        if (click.equals("Kreis"))
        {
        modus="kreis";
        }
        if (click.equals("4-Eck"))
        {
        modus="viereck";
        }
    
      }
    }
    


  • Beim repaint flackert der Bildschirm weil das so oft aufgerufen wird.

    Am besten du läst nur den Teil neu zeichen der nötig ist -> weniger oder kein Flackern.



  • Ähm ja das hört sich interessant ... nur wie ?

    Michael



  • Ja doch habe es hinbekommen aber, das hat an meiner Situation so gar nichts geändert.
    Das Flackern ist nicht weniger geworden und ich kann auch immernoch nicht zwei Vierecke nacheinander malen.
    Weil das Bild ja ständig geleert wird.

    Also wie geht es weiter?

    Brauche dringend Hilfe, weil ich morgen wieder LK habe und es da funktionieren soll.

    Michael



  • Mein Ansatz dazu:

    Als erstes habe ich mal einen MouseListener implementiert, um die Mausereignisse abzufangen.

    Weiteres siehe Code:

    import java.awt.*; 
    import java.awt.event.*; 
    import java.applet.*; 
    
    public class Malen extends Applet implements ActionListener,MouseListener{ 	//MouseListener!
    	private int x1,y1,x2,y2;
    	private String modus=""; 
    
    	Button leeren= new Button("Lösche Bildschirminhalt"); 
    	Button rund= new Button("Kreis"); 
    	Button eckig= new Button("4-Eck"); 
    
    	public void init(){ 
    		setLayout(null); 
    		leeren.setBounds(220,10,160,30); 
    		leeren.addActionListener(this); 
    		this.add(leeren); 
    
    		rund.setBounds(55,10,160,30); 
    		rund.addActionListener(this); 
    		this.add(rund); 
    
    		eckig.setBounds(385,10,160,30); 
    		eckig.addActionListener(this); 
    		this.add(eckig);
    
    		this.addMouseListener(this);	//MouseListener!
    	} 
    
    	// Maustaste wird losgelassen:
    	public void mouseReleased(MouseEvent e){
    		x2 = e.getX();
    		y2 = e.getY();
    		System.out.println("x2="+x2+",y2="+y2);
    	}
    
    	// Maustaste wird gedrückt:
    	public void mousePressed(MouseEvent e){
    		x1 = e.getX();
    		y1 = e.getY();
    		System.out.println("x1="+x1+",y1="+y1);
    	}
    
    	public void mouseEntered(MouseEvent e){}
    	public void mouseExited(MouseEvent e){}
    	public void mouseClicked(MouseEvent e){}
    
    	public void paint(Graphics g){}
    
    	public void update (Graphics g){
    		if(modus=="viereck")
        		g.drawRect(x1,y1,x2-x1,y2-y1);
    
       		if(modus=="kreis")
        		g.drawOval(x1,y1,x2-x1,y2-y1);
    
        	/* wenn Bildschirm gelöscht werden soll, behelfe ich mir damit, dass ich in der Größe
        	   des Applets ein gefülltes weißes Rechteck zeichne ;-) */
        	if(modus.length()==0){
        		g.setColor(Color.WHITE);
        		g.fillRect(this.getBounds().x,this.getBounds().y,this.getBounds().width,this.getBounds().height);
        	}
    	}	
    
    	public void actionPerformed(ActionEvent e){ 
    		String click = e.getActionCommand(); 
    
    		if(click.equals("Lösche Bildschirminhalt")){
    			modus="";
    			repaint();
    		}
    
    		if (click.equals("Kreis")){
    			modus="kreis";
    			repaint();
    		}
    
    		if (click.equals("4-Eck")){
    			modus="viereck";
    			repaint();
    		}
    	} 
    }
    

    Damit wird von der Stelle, wo die Maus gedrückt wurde, bis zu der Stelle, wo die Maus wieder los gelassen wurde, ein Kreis oder ein Rechteck gezeichnet - je nachdem, welcher Button gedrückt wurde.

    Hoffe, ich habe dein Anliegen richtig verstanden, und kann dir mit diesem Ansatz behilflich sein.

    btw: Was ist LK???



  • IMHO ist das der falsche Ansatz, da die Figuren sofort wieder verschwinden, wenn das Fenster neu gezeichnet wird bzw. wenn es von anderen Fenstern überlagert wird und neu gezeichnet werden soll.
    Das Panel auf dem die Figuren zu sehen sein sollen muss etwas mehr leisten können als nur die Figuren zu zeichnen. Es muss nämlich alle gezeichneten Figuren speichern, damit es sie jederzeit neu malen kann. Die Methode, die du hier hast ist "fire and forget" ... sprich einmal gezeichnet weiss das Panel nicht mehr was es hatte. Stelle deinem Panel einen Vector zur Verfügung, der deine Figuren sichert. Für jede Art von Figur solltest du eine Klasse erzeugen und ihr auch sagen, wie sie sich selbst zu zeichnen hat. Anschließend genügt es in der paint-Methode des Panels einfach den Vector zu durchlaufen und für jedes Figur-Objekt die paint-Methode mit dem Graphics-Kontext des Panels aufzurufen. Damit sollte dann das Problem behoben sein.



  • @CengizS

    An Vector hatte ich auch gedacht, den Gedanken dann aber wieder verworfen, weil ich davon ausging, dass die gezeichneten Objekte ja nicht separat gespeichert werden müssen.

    Finde deinen Tipp jedenfalls super.


Anmelden zum Antworten