Archief - Java Mouseinput + JPanel + controllers etc

Het archief is een bevroren moment uit een vorige versie van dit forum, met andere regels en andere bazen. Deze posts weerspiegelen op geen enkele manier onze huidige ideeën, waarden of wereldbeelden en zijn op sommige plaatsen gecensureerd wegens ontoelaatbaar. Veel zijn in een andere tijdsgeest gemaakt, al dan niet ironisch - zoals in het ironische subforum Off-Topic - en zouden op dit moment niet meer gepost (mogen) worden. Toch bieden we dit archief nog graag aan als informatiedatabank en naslagwerk. Lees er hier meer over of start een gesprek met anderen.

Xtralecherus

Legacy Member
Yo,

Heb hier nu zo 3 klassen.

Code:
package xtremedraw;

public enum DrawMode {
    MOVE,
    RECTANGLE
}

Code:
package xtremedraw;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JToolBar;

import xtremedraw.XtremeDrawPanel;


// hoofdvenster
public class XtremeDraw extends JFrame {
    
    private XtremeDrawPanel panel;
    
    public XtremeDraw() {
        super("Xtreme Draw");
        
        panel = new XtremeDrawPanel();
        
        JToolBar bar = new JToolBar();
        bar.setFloatable(false);
        
        JButton move = new JButton(new ImageIcon(getClass().getResource("/resources/move.png")));
        move.setToolTipText("Move");
        move.setSelected(true);
        move.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                panel.setMode(DrawMode.MOVE);
            }
        });
        
        JButton rectangle = new JButton(new ImageIcon(getClass().getResource("/resources/rectangle.png")));
        rectangle.setToolTipText("Rectangle");
        rectangle.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                panel.setMode(DrawMode.RECTANGLE);
            }
        });
        
        bar.add(move);
        bar.add(rectangle);
        
        add(bar, BorderLayout.NORTH);
        add(panel, BorderLayout.CENTER);
        
        pack();
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }
    
    public static void main(String[] args) {
        new XtremeDraw().setVisible(true);
    }
}

Code:
package xtremedraw;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.event.MouseEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JPanel;
import javax.swing.event.MouseInputListener;


// tekenpaneel
public class XtremeDrawPanel extends JPanel implements MouseInputListener {

    // geselecteerde functie
    private DrawMode mode;
    
    // huidige figuren
    private List<Shape> shapes;
    
    // tijdelijke variabelen
    private Point dragStart;
    private Shape selectedShape;
    private Shape tempShape;
    
    // tekeninstellingen
    private Stroke tempStroke = new BasicStroke(3, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 10, new float[] {10, 10}, 0);
    private Stroke stroke = new BasicStroke(3, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
    private Paint tempPaint = Color.RED;
    private Paint strokePaint = Color.BLACK;
    private Paint fillPaint = new Color(192, 192, 192);
    
    public XtremeDrawPanel() {
        mode = DrawMode.MOVE;
        shapes = new ArrayList<Shape>();
        
        setPreferredSize(new Dimension(640,480));
        addMouseListener(this);
        addMouseMotionListener(this);
    }

    public DrawMode getMode() {
        return mode;
    }

    public void setMode(DrawMode mode) {
        this.mode = mode;
        clearTemp();
        repaint();
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D)g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        
        // teken alle figuren
        g2.setStroke(stroke);
        for (Shape s : shapes) {
            g2.setPaint(fillPaint);
            g2.fill(s);
            g2.setPaint(strokePaint);
            g2.draw(s);
        }
        
        // teken de tijdelijke figuur (indien niet null)
        if (tempShape != null) {
            g2.setStroke(tempStroke);
            g2.setPaint(tempPaint);
            g2.draw(tempShape);
        }
    }

    private void clearTemp() {
        dragStart = null;
        selectedShape = null;
        tempShape = null;
    }
    
    @Override
    public void mouseClicked(MouseEvent e) {
        return;
    }

    @Override
    public void mousePressed(MouseEvent e) {
        if (mode == DrawMode.MOVE) {
            Point p = new Point(e.getX(), e.getY());
            // overloop de lijst en selecteer de laatste (bovenste) shape die dit punt bevat
            for (Shape s : shapes)
                if (s.contains(p))
                    selectedShape = s;
            // onthoud het beginpunt
            dragStart = p;
        } else if (mode == DrawMode.RECTANGLE) {
            // onthoud het beginpunt
            dragStart = new Point(e.getX(), e.getY());
        }  
    }

    @Override
    public void mouseReleased(MouseEvent e) {
        if (mode == DrawMode.MOVE) {
            // als de figuur verschoven is en we nog steeds binnen het paneel zijn
            if (tempShape != null && e.getX() >= 0 && e.getX() < getWidth() && e.getY() >= 0 && e.getY() < getHeight()) {
                // verwijder de orginele figuur
                shapes.remove(selectedShape);
                // voeg de verschoven figuur toe
                shapes.add(tempShape);
            }
            clearTemp();
            repaint();
        } else if (mode == DrawMode.RECTANGLE) {
            // als er een figuur getekend is en we nog steeds binnen het paneel zijn
            if (tempShape != null && e.getX() >= 0 && e.getX() < getWidth() && e.getY() >= 0 && e.getY() < getHeight()) {
                // voeg de tijdelijke figuur toe
                shapes.add(tempShape);
            }
            clearTemp();
            repaint();
        }
    }

    @Override
    public void mouseEntered(MouseEvent e) {
        return;
    }

    @Override
    public void mouseExited(MouseEvent e) {
        return;
    }

    @Override
    public void mouseDragged(MouseEvent e) {
        if (mode == DrawMode.MOVE) {
            // als we binnen het paneel zijn
            if (e.getX() >= 0 && e.getX() < getWidth() && e.getY() >= 0 && e.getY() < getHeight()) {
                // maak een translatie aan van het beginpunt naar het huidige punt
                AffineTransform transl = AffineTransform.getTranslateInstance(e.getX() - dragStart.x, e.getY() - dragStart.y);
                // verschuif de geselecteerde figuur volgens deze translatie
                tempShape = transl.createTransformedShape(selectedShape);
                // herteken
                repaint();
            }
        } else if (mode == DrawMode.RECTANGLE) {
            // als we binnen het paneel zijn
            if (e.getX() >= 0 && e.getX() < getWidth() && e.getY() >= 0 && e.getY() < getHeight()) {
                // bereken de kleinste x en y waarden als linkerbovenhoek
                int x = Math.min(dragStart.x, e.getX());
                int y = Math.min(dragStart.y, e.getY());
                // bereken het verschil tussen de x en y waarden als breedte en hoogte
                int w = Math.abs(e.getX() - dragStart.x);
                int h = Math.abs(e.getY() - dragStart.y);
                // maak een tijdelijke rechthoek aan
                tempShape = new Rectangle2D.Float(x, y, w, h);
                // herteken
                repaint();
            }
        }
    }

    @Override
    public void mouseMoved(MouseEvent e) {
        return;
    }
}

Nu ben ik dit aan het herwerken met een model, interface en controllers enzo die dan verschillende soorten figuren kunnen maken en andere functies dat lukt maar ik zit wat vast met die mouse stuff. Iemand die mij snel kan uitleggen hoe ik bv een RectangleController (gewoon bovenstaande insteken) dus gebruik maken van mousinput in die controller zodat ik op de JPanel figuren kan toevoegen door gebruik van methode via interface.

Xtralecherus

Legacy Member
Ik heb verschillende soorten klassen rectangleController, EllipsesController en nog andere die telkens een andere figuur tekenen(zonder muis input). Allemaal die klassen hebben "implements DrawingController", wat een interface is met voorlopig 2 methodes: Figuur toevoegen en verwijderen. Nu wil ik dus via die rectangleController een figuur zelf tekenen met behulp van de mousePressed, Released en Dragged dus. De JPanel heeft nu dus enkel de methodes paintComponent(Graphics g) en stateChanged(ChangeEvent e).

simpel gezegd wil ik vanuit die Controllers via mouse input figuren tekenen op een JPanel. Hierboven lukt dat in dezelfde klasse maar ben er nog niet helemaal uit hoe het precies moet vanuit een andere klasse.

momenteel heb ik een nieuwe klasse zitten maken

Code:
package drawingstyle.controllers;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Paint;
import java.awt.Point;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionAdapter;
import java.awt.event.MouseMotionListener;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;

import drawingstyle.DrawMode;
import drawingstyle.DrawingModel;
import drawingstyle.DrawingPanel;

public class TestController implements DrawingController{

    
    // huidige figuren
    //private List<Shape> shapes;
    
    // tijdelijke variabelen
    private Point dragStart;
    private Shape selectedShape;
    private Shape tempShape;
    
    
    private DrawingModel m;
    private DrawMode mode;
    private DrawingPanel p;
    
    private MouseListener mouseListener;
    private MouseMotionListener mouseMotionListener;
    
    public TestController(DrawingModel m) {
        this.m = m;

    }
  
    public String toString() {
        return "test";
    }
    
    private void clearTemp() {
        dragStart = null;
        selectedShape = null;
        tempShape = null;
    }
    @Override
    public void addRandomShape() {
        
        p.addMouseListener( 
                new MouseAdapter() 
                {
                    
                    public void mousePressed( MouseEvent e) 
                     {
                        dragStart = new Point(e.getX(), e.getY());
                     } 
                    
                     public void mouseReleased( MouseEvent e) 
                     {
                          // als er een figuur getekend is en we nog steeds binnen het paneel zijn
                          if (tempShape != null && e.getX() >= 0 && e.getX() < p.getWidth() && e.getY() >= 0 && e.getY() < p.getHeight()) {
                              // voeg de tijdelijke figuur toe
                              m.addShape(tempShape);
                          }
                          clearTemp();
                          p.repaint();
                     } 
                    
                }
                );
        
        p.addMouseMotionListener(
                new MouseMotionAdapter(){
                     public void mouseDragged( MouseEvent e) 
                     {
                         // als we binnen het paneel zijn
                         if (e.getX() >= 0 && e.getX() < p.getWidth() && e.getY() >= 0 && e.getY() < p.getHeight()) 
                         {
                             // bereken de kleinste x en y waarden als linkerbovenhoek
                             int x = Math.min(dragStart.x, e.getX());
                             int y = Math.min(dragStart.y, e.getY());
                             // bereken het verschil tussen de x en y waarden als breedte en hoogte
                             int w = Math.abs(e.getX() - dragStart.x);
                             int h = Math.abs(e.getY() - dragStart.y);
                             // maak een tijdelijke rechthoek aan
                             tempShape = new Rectangle2D.Float(x, y, w, h);
                             // herteken
                             p.repaint();
                         }
                     }
                }
                );
                
    }
        
    
    @Override
    public void clearDrawing() {
        // TODO Auto-generated method stub
        
    }
}

NeverwinterX

Legacy Member
Het verhaal is nogal warrig, maar ik neem aan dat je probeert model-view-controller toe te passen?

Voor dit soort programma zou het mvc model er ongeveer zo uitzien:
Controller vangt de mouse/keyboard events op.
Uw view toont uw jframe, jpanel en kan vormen tekenen.
Uw model heeft een model voor de verschillende vormen en bevat welke vormen waar in de ruimte staan.
Als uw controller dus iets opvangt beveelt die aan de view om de vormen uit het model te tekenen of andere acties die je wilt.

MVC

Xtralecherus

Legacy Member
MCV niet echt. Maar een andere pattern nl Factory pattern. Enige prob is momenteel hoe ik via een andere klasse die niet een JPanel is luisteren via de muis en tekenen. Nuja kheb factory pattern gekozen om het er in te verwerken. Desnoods kan ik mss nog veranderen naar MVC als dit gemakkelijker is maar lijkt mij bijna vrijwel hetzelfde ongeveer..

Xtralecherus

Legacy Member
Iemand die weet hoe ik via een klasse RectangleController een tekening tekent doormiddel van mousePressed/Released/Dragged op een andere klasse dat een jpanel is?

NeverwinterX

Legacy Member
Luisteren op muis/keyboard via een andere klasse is makkelijk. Die andere klasse moet gewoon die listener interfaces implementeren en dan kan je die toevoegen aan de buttons etc.
Tekenen op een andere JPanel zomaar vanuit een andere klasse is moeilijk en ook gewoon not done design-wise. Je kan wel een klasse maken die gegeven een Graphics en parameters over de shape die shape tekent in die graphics. En dan moet de JPanel die klasse maar gebruiken.
Het archief is een bevroren moment uit een vorige versie van dit forum, met andere regels en andere bazen. Deze posts weerspiegelen op geen enkele manier onze huidige ideeën, waarden of wereldbeelden en zijn op sommige plaatsen gecensureerd wegens ontoelaatbaar. Veel zijn in een andere tijdsgeest gemaakt, al dan niet ironisch - zoals in het ironische subforum Off-Topic - en zouden op dit moment niet meer gepost (mogen) worden. Toch bieden we dit archief nog graag aan als informatiedatabank en naslagwerk. Lees er hier meer over of start een gesprek met anderen.
Terug
Bovenaan