Search code examples
javagraphicsrectangles

Change color of the rectangle which the mouse is in by using the mouse wheel


Sorry for posting my whole code but this way you can check my problem easier, no?

package task3;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import javax.swing.*;

class Model {
    
    int l; //line
    int c; //column
    int[] loc = {0,0}; //location
    JFrame frame;
    int m_width;
    int m_height;
    int R;
    int G;
    int B;
    int count;
    int mY;
    int x, y;
    Rectangle rect;
    
    
    int genR() {
    int R = (int)(Math.random()*256);
        return R;
    }
    int genG() {
        int G = (int)(Math.random()*256); 
        return G;
    }
    int genB() {
        int B = (int)(Math.random()*256);
        return B;
    }
    
    public int getRectWidth() {
        return frame.getContentPane().getWidth() / c;
    }
    public int getRectHeight() {
        return frame.getContentPane().getHeight() / l;
    }
    
    
    Model(int width, int height, int line, int column, JFrame w) {
        m_width = width;
        m_height = height;
        l = line;
        c = column;
        frame = w;
    }
}

class Mvl extends JComponent implements MouseWheelListener {
    
    private Model m_Mod;
    
    Mvl(Model mod) {
        m_Mod = mod;
    }
    public void mouseWheelMoved(MouseWheelEvent e) {
        //m_Mod.mY += e.getWheelRotation();
        //m_Mod.mY += e.getUnitsToScroll();
        System.out.print(m_Mod.rect.getSize());
        m_Mod.frame.repaint();
        //int x = e.getXOnScreen();
        //int y = e.getYOnScreen();
        //int x = e.getX();
        //int y = e.getY();

       
         //RectangleComponent rc = new RectangleComponent(x, y);
         //m_Mod.frame.add(rc);
         //m_Mod.frame.revalidate();
    }
}

class Reactmouse implements MouseListener { //Print size of rectangle //Implement all methods otherwise abstract class
    
    private Model m_Mod;
    
    Reactmouse(Model mod) {
        m_Mod = mod;
    }
    
    public void mouseClicked(MouseEvent e) { 
        //System.out.println(++m_Mod.count + "  " + "Width: " + m_Mod.getRectWidth() + "  " + "Height: " +
        //m_Mod.getRectWidth() + " Position X-Axis: " + m_Mod.loc[0] + "Position Y-Axis: " + m_Mod.loc[1]);
        System.out.println("Position on X-Axis:" + e.getX() + " " + "Position on Y-Axis: "+  e.getY()); 
        //Cords of the click, in the rectangle
    }
    
    @Override
    public void mousePressed(MouseEvent e) {
        
    }
    @Override
    public void mouseReleased(MouseEvent e) {
            
    }
    @Override
    public void mouseEntered(MouseEvent e) {
            
    }
    @Override
    public void mouseExited(MouseEvent e) { 
        
    }
}

class View extends JComponent {
    
    private Model m_Mod;

    View(Model mod) {
        m_Mod = mod;
    }
    public void draw(Graphics g) {
        Color c = new Color(m_Mod.genR(), m_Mod.genG(), m_Mod.genB());
        g.setColor(c);
        g.fillRect(m_Mod.loc[0], m_Mod.loc[1], m_Mod.getRectWidth(), m_Mod.getRectHeight());
        m_Mod.rect = g.getClipBounds(); 
    }

Here I ask for the size's Dimension but I need the rectangle's size

    @Override
    protected void paintComponent(Graphics g) {
        
        super.paintComponent(g);
    
        for(int i=0; i<m_Mod.l; ++i) {
            for(int j=0; j<m_Mod.c; ++j) {
                
              draw(g);  
              m_Mod.loc[0] = m_Mod.loc[0] + m_Mod.getRectWidth() + 2;
              
             }
            
            m_Mod.loc[0] = 0;
            m_Mod.loc[1] = m_Mod.loc[1] + m_Mod.getRectHeight() + 2;
        }
        m_Mod.loc[1] = 0;
    }
}
class Controller extends JFrame{
    
    private Model m_Mod;
    private View m_View;
    
    
        Controller(){
                
                JFrame window = new JFrame();
                m_Mod = new Model(500,500,8,8, window);
                m_View = new View(m_Mod);
                Image icon = window.getToolkit().getImage("C:\\Users\\49157\\eclipse-workspace\\Programmierung\\src\\task3\\download.png");
                window.setIconImage(icon);
                window.setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
                window.add(m_View);
                window.setSize(m_Mod.m_width,m_Mod.m_height);
                //window.add(new myButton());
                window.addMouseWheelListener(new Mvl(m_Mod));
                window.addMouseListener(new Reactmouse(m_Mod));
                window.setLocationRelativeTo(null);
                window.setVisible(true);
                window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                
        }
        void simulate(){
            m_View.repaint();
        }
        
}
public class task3 {

    public static void main(String[] args) throws Exception {
            
            Controller c = new Controller();    
            c.simulate();
            
        }
    }

Okay so I can redraw the whole frame with my mousewheel but I can not redraw single rectangles drawed here. How do I do that?

The main problem is that I cannot ask for the x and y coords of my drawed rectangles. Any ideas?


Solution

  • Introduction

    Since your code is not runnable, I went ahead and created an example GUI. Here's the example GUI.

    Colored Rectangles 1

    Here's the example GUI after I changed a couple of colors.

    Colored Rectangles 2

    Explanation

    Oracle has a helpful tutorial, Creating a GUI With Swing. Skip the Learning Swing with the NetBeans IDE section.

    When I create a Swing GUI, I use the model-view-controller (MVC) pattern. This pattern allows me to separate my code into small logical methods and lets me focus on one small part of the problem at a time.

    The MVC pattern implies that you create the model first, then the view, then finally the controller. You iterate between the model, view, and controller. For this GUI, I created a basic model and added fields to the model as I went along.

    In Swing, the MVC pattern means:

    • The view reads information from the model.
    • The view does not update the model.
    • The controller(s) update the model and repaint/revalidate the view.

    Model classes are plain Java getter/setter classes. View classes use or extend Swing components.

    Generally, each Swing action or listener acts as its own controller, responsible for its portion of the model and view. There's not one controller class "to rule them all".

    For this application, I created two model classes, two view classes, and two mouse listener classes.

    Model

    The ColorRectangle class holds a background Color and a java.awt.Rectangle to hold the position and size of the rectangle.

    The ColoredRectanglesModel class holds a two-dimensional array of ColorRectangle instances and an array of possible background colors. This class creates the model that the view uses to create the GUI.

    View

    The ColoredRectangles class creates the JFrame. This is a pretty standard JFrame setup, and it forms the start of almost all of my Swing applications.

    All Swing applications must start with a call to the SwingUtilities invokeLater method. This method ensures that the Swing components are created and executed on the Event Dispatch Thread.

    The DrawingPanel class draws the rectangles. Period. Nothing else.

    I override the paintComponent method. The first call is to the super.paintComponent method, which draws the JPanel background and maintains the Swing paint chain.

    Controller

    The RectangleListener class lets the user select which rectangle will be modified.

    The ColorListener class scrolls through the possible background colors using the mouse wheel.

    Notice how simple both these classes are. The heavy lifting is done by the model classes.

    Code

    Here's the complete runnable code. I made all the additional classes inner classes so I could post the code as one block.

    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.Point;
    import java.awt.Rectangle;
    import java.awt.RenderingHints;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    import java.awt.event.MouseWheelEvent;
    import java.util.Random;
    
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;
    
    public class ColoredRectangles implements Runnable {
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new ColoredRectangles());
        }
        
        private final ColoredRectanglesModel model;
        
        private final DrawingPanel drawingPanel;
        
        public ColoredRectangles() {
            this.model = new ColoredRectanglesModel();
            this.drawingPanel = new DrawingPanel(this, model);
        }
    
        @Override
        public void run() {
            JFrame frame = new JFrame("Colored Rectangles");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            
            frame.add(drawingPanel, BorderLayout.CENTER);
            
            frame.pack();
            frame.setLocationByPlatform(true);
            frame.setVisible(true);
        }
        
        public void repaint() {
            drawingPanel.repaint();
        }
        
        public class DrawingPanel extends JPanel {
    
            private static final long serialVersionUID = 1L;
            
            private final ColoredRectanglesModel model;
            
            public DrawingPanel(ColoredRectangles view, ColoredRectanglesModel model) {
                this.model = model;
                this.setBackground(Color.BLACK);
                this.setPreferredSize(model.getDrawingDimension());
                this.addMouseListener(new RectangleListener(model));
                this.addMouseWheelListener(new ColorListener(view, model));
            }
            
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                
                Graphics2D g2d = (Graphics2D) g;
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                        RenderingHints.VALUE_ANTIALIAS_ON);
                g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
                        RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
                g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
                        RenderingHints.VALUE_FRACTIONALMETRICS_ON);
                
                ColorRectangle[][] coloredRectangles = model.getColoredRectangles();
                for (int i = 0; i < coloredRectangles.length; i++) {
                    for (int j = 0; j < coloredRectangles[i].length; j++) {
                        g2d.setColor(coloredRectangles[i][j].getBackgroundColor());
                        Rectangle r = coloredRectangles[i][j].getRectangle();
                        g2d.fillRect(r.x, r.y, r.width, r.height);
                    }
                }
            }
            
        }
        
        public class RectangleListener extends MouseAdapter {
            
            private final ColoredRectanglesModel model;
    
            public RectangleListener(ColoredRectanglesModel model) {
                this.model = model;
            }
            
            @Override
            public void mousePressed(MouseEvent event) {
                model.setSelectedRectangle(event.getPoint());
            }
            
        }
        
        public class ColorListener extends MouseAdapter {
    
            private final ColoredRectangles view;
    
            private final ColoredRectanglesModel model;
    
            public ColorListener(ColoredRectangles view,
                    ColoredRectanglesModel model) {
                this.view = view;
                this.model = model;
            }
    
            @Override
            public void mouseWheelMoved(MouseWheelEvent event) {
                if (model.getSelectedRectangle() != null) {
                    model.incrementColorIndex(event.getWheelRotation());
                    ColorRectangle r = model.getSelectedRectangle();
                    r.setBackgroundColor(model.getCurrentColor());
                    view.repaint();
                }
            }
    
        }
        
        public class ColoredRectanglesModel {
            
            private int colorIndex;
            
            private final ColorRectangle[][] coloredRectangles;
            private ColorRectangle selectedRectangle;
            
            private final Color[] colors;
            private Color currentColor;
            
            private Dimension drawingDimension;
            
            private final Random random;
            
            public ColoredRectanglesModel() {
                this.colorIndex = 0;
                this.random = new Random();
                this.colors = generateColors();
                this.coloredRectangles = generateColoredRectangles();
                this.currentColor = colors[colorIndex];
            }
            
            private Color[] generateColors() {
                return new Color[] { Color.BLUE, Color.CYAN, Color.LIGHT_GRAY,
                        Color.MAGENTA, Color.ORANGE, Color.PINK, Color.RED,
                        Color.WHITE, Color.YELLOW };
            }
            
            private ColorRectangle[][] generateColoredRectangles() {
                ColorRectangle[][] coloredRectangles = new ColorRectangle[4][3];
                
                int x = 20;
                int y = 20;
                int width = 128;
                int height = 128;
                int maxWidth = 0;
                
                for (int i = 0; i < coloredRectangles.length; i++) {
                    for (int j = 0; j < coloredRectangles[i].length; j++) {
                        int index = random.nextInt(colors.length);
                        Color color = colors[index];
                        coloredRectangles[i][j] = new ColorRectangle(color, x, y,
                                width, height);
                        x += width + 20;
                    }
                    maxWidth = x;
                    x = 20;
                    y += height + 20;
                }
                
                this.drawingDimension = new Dimension(maxWidth, y);
                
                return coloredRectangles;
            }
            
            public void setSelectedRectangle(Point point) {
                for (int i = 0; i < coloredRectangles.length; i++) {
                    for (int j = 0; j < coloredRectangles[i].length; j++) {
                        Rectangle r = coloredRectangles[i][j].getRectangle();
                        if (r.x <= point.x && r.x + r.width >= point.x
                                && r.y <= point.y && r.y + r.height >= point.y) {
                            this.selectedRectangle = coloredRectangles[i][j];
                            return;
                        }
                    }
                }
    
                this.selectedRectangle = null;
            }
            
            public void incrementColorIndex(int increment) {
                colorIndex += increment;
                if (colorIndex < 0) {
                    colorIndex = colors.length + colorIndex;
                } else {
                    colorIndex %= colors.length;
                }
                this.currentColor = colors[colorIndex];
            }
    
            public ColorRectangle[][] getColoredRectangles() {
                return coloredRectangles;
            }
    
            public Dimension getDrawingDimension() {
                return drawingDimension;
            }
    
            public ColorRectangle getSelectedRectangle() {
                return selectedRectangle;
            }
    
            public Color getCurrentColor() {
                return currentColor;
            }
    
        }
        
        public class ColorRectangle {
    
            private Color backgroundColor;
    
            private final Rectangle rectangle;
    
            public ColorRectangle(Color backgroundColor, int x, int y, int width,
                    int height) {
                this.backgroundColor = backgroundColor;
                this.rectangle = new Rectangle(x, y, width, height);
            }
    
            public void setBackgroundColor(Color backgroundColor) {
                this.backgroundColor = backgroundColor;
            }
    
            public Color getBackgroundColor() {
                return backgroundColor;
            }
    
            public Rectangle getRectangle() {
                return rectangle;
            }
    
        }
    
    }