0

I have following code to display and draw JPanel with buffered image.

I am setting its size to size of buffered image, but it is not getting set actually.

It shows scroll bars when I resize, but when I resize JFrame greater than size of panel or BufferedImage, I am still getting mouse events when I click outside of panel's size.

I have omitted extra code.

    public class PaintFrame extends JFrame{    
        private JScrollPane paintScrollPane;
        private Painter painter;
        private JPanel paintPanel;
        private BufferedImage paintImage;
        private Color forgroundColor;

        public PaintFrame(){
            super("Paint");
            setDefaultCloseOperation(EXIT_ON_CLOSE);
            setPreferredSize(new Dimension(800, 600));
            setLocationByPlatform(true);
            getContentPane().setBackground(Color.black);

            paintImage = new BufferedImage(700, 500, BufferedImage.TYPE_3BYTE_BGR);

            paintPanel = new JPanel(){
                @Override
                public void paint(Graphics g){
                    if(paintImage != null){
                        g.drawImage(paintImage, 0, 0, paintImage.getWidth(), paintImage.getHeight(), null);
                    }
                }
            };
            paintPanel.setBackground(Color.white);
            paintPanel.addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent me){
                    mouseClickedOnPaint(me);
                }
            });
            paintPanel.setPreferredSize(new Dimension(paintImage.getWidth(), paintImage.getHeight()));
            paintScrollPane = new JScrollPane(paintPanel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);

            getContentPane().add(paintScrollPane);

            pack();
        }
}
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
nullptr
  • 3,320
  • 7
  • 35
  • 68
  • After adding imports and commenting out `Painter`, I still get an error on `mouseClickedOnPaint(me);`. For better help sooner, post an [SSCCE](http://sscce.org/). – Andrew Thompson Apr 21 '13 at 05:36
  • @AndrewThompson Do you just have that on Paste? :P – Sinkingpoint Apr 21 '13 at 05:37
  • @Quirliom The last part of it? Of course. What, do you think I'm thick? – Andrew Thompson Apr 21 '13 at 05:48
  • @AndrewThompson No Offence intended, just an amusing observation. – Sinkingpoint Apr 21 '13 at 05:49
  • @Quirliom *"just an amusing observation"* ..join the queue. ;) – Andrew Thompson Apr 21 '13 at 05:51
  • @Meraman Don't use `paint` - especially if you're not going to call `super.paint`. Take a look at [Performing Custom Painting](http://docs.oracle.com/javase/tutorial/uiswing/painting/). Also, avoid using `setPreferredSize`, instead, override the `getPreferredSize` method instead. Check out [this](http://stackoverflow.com/questions/7229226/should-i-avoid-the-use-of-setpreferredmaximumminimumsize-methods-in-java-swi) for more details – MadProgrammer Apr 21 '13 at 06:19
  • 1
    @Quirliom Andrew's actually a bot that automatically responds to all posts tagged with Swing. And grateful we are ;) – MadProgrammer Apr 21 '13 at 06:19

1 Answers1

2

As Quirlom has pointed out, LayoutManagers may choice to ignore the getPreferredSize value based on the needs of there implementations

If all you're worried about is the mouse events, you could filter them out by determining if the mouse event clicked within the image or not.

Otherwise you need to find a layout manager that better meets your needs...

The following example simply determines if the mouse events fall within the bounds of the image...

enter image description here

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class ClickImage {

    public static void main(String[] args) {
        new ClickImage();
    }

    public ClickImage() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Test");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new ImagePane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class ImagePane extends JPanel {

        private BufferedImage background;
        private List<Point> goodPoints;
        private List<Point> badPoints;

        public ImagePane() {
            try {
                background = ImageIO.read(new File("/Volumes/Disk02/Dropbox/MegaTokyo/url.jpg"));
            } catch (IOException ex) {
                ex.printStackTrace();
            }
            goodPoints = new ArrayList<>(5);
            badPoints = new ArrayList<>(5);
            addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    if (getImageBounds().contains(e.getPoint())) {
                        goodPoints.add(e.getPoint());
                    } else {
                        badPoints.add(e.getPoint());
                    }
                    repaint();
                }
            });
        }

        @Override
        public void invalidate() {
            goodPoints.clear();
            badPoints.clear();
            super.invalidate();
        }

        public Rectangle getImageBounds() {
            Rectangle bounds = new Rectangle();
            if (background != null) {
                bounds.x = (getWidth() - background.getWidth()) / 2;
                bounds.y = (getHeight() - background.getHeight()) / 2;
                bounds.width = background.getWidth();
                bounds.height = background.getHeight();
            }

            return bounds;            
        }

        @Override
        public Dimension getPreferredSize() {
            return background == null ? super.getPreferredSize() : getImageBounds().getSize();
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (background != null) {
                Graphics2D g2d = (Graphics2D) g.create();
                Rectangle bounds = getImageBounds();
                g2d.drawImage(background, bounds.x, bounds.y, this);

                g2d.setColor(Color.GREEN);
                drawPoints(g2d, goodPoints);
                g2d.setColor(Color.RED);
                drawPoints(g2d, badPoints);

                g2d.dispose();
            }
        }

        protected void drawPoints(Graphics2D g2d, List<Point> points) {
            for (Point p : points) {
                g2d.drawLine(p.x - 4, p.y - 4, p.x + 4, p.y + 4);
                g2d.drawLine(p.x + 4, p.y - 4, p.x - 4, p.y + 4);
            }
        }
    }
}

You may also want to take a look at A Visual Guide to Layout Managers

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366