0

I am trying to draw a portion of a circular game board. This board rotates, but I'd like to keep a constant viewport. My plan was to create a BufferedImage of the full board, rotate it, then draw a centered portion with a graphics paint method. However, Graphics does not have a rotate, and Graphics2D does not have a way to draw a portion of the image.

Any thoughts?

Adam Yost
  • 3,616
  • 23
  • 36

3 Answers3

3

"Graphics2D does not have a way to draw a portion of the image."

That's not true. Graphics2D inherits from Graphics this method. Which allows drawing portions of an image. see an example usage here

public abstract boolean drawImage(Image img,
                              int dx1,
                              int dy1,
                              int dx2,
                              int dy2,
                              int sx1,
                              int sy1,
                              int sx2,
                              int sy2,
                              ImageObserver observer)

Draws as much of the specified area of the specified image as is currently available, scaling it on the fly to fit inside the specified area of the destination drawable surface. Transparent pixels do not affect whatever pixels are already there.

Parameters:

  • img - the specified image to be drawn. This method does nothing if img is null.
  • dx1 - the x coordinate of the first corner of the destination rectangle.
  • dy1 - the y coordinate of the first corner of the destination rectangle.
  • dx2 - the x coordinate of the second corner of the destination rectangle.
  • dy2 - the y coordinate of the second corner of the destination rectangle.
  • sx1 - the x coordinate of the first corner of the source rectangle.
  • sy1 - the y coordinate of the first corner of the source rectangle.
  • sx2 - the x coordinate of the second corner of the source rectangle.
  • sy2 - the y coordinate of the second corner of the source rectangle.
  • observer - object to be notified as more of the image is scaled and converted.

Community
  • 1
  • 1
Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720
2

You can cast to Graphics 2D

How to rotate Graphics in Java

in order to get it rotatin'.

To draw a portion of it, I think you can use the clip method

http://docs.oracle.com/javase/7/docs/api/java/awt/Graphics2D.html#clip(java.awt.Shape)

and give it an appropriate shape.

Community
  • 1
  • 1
Carlos Bribiescas
  • 4,197
  • 9
  • 35
  • 66
  • Clip seems to draw relative to the original image, giving me the original selection rotated. I would like a non-rotated viewport over a rotated background. – Adam Yost Mar 20 '14 at 20:58
2

As mentioned by others:

  • Graphics2D extends Graphics and inherits all the methods of the parent class.
  • The Graphics object passed to Swing components should be a Graphics2D instance.

In this code, I side step the 2nd assumption by painting to a BufferedImage displayed in a JLabel. In the top of the GUI we can see the 'complete' image obtained from Example images for code and mark-up Q&As. In the bottom the code crops the image to just the 'black' king, rotates it and paints a clipped version (repeatedly).

enter image description here

import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
import java.net.URL;
import java.util.Random;
import javax.imageio.ImageIO;

class ClippedRotatedImage {

    public static void main(String[] args) throws Exception {
        URL url = new URL("https://i.stack.imgur.com/memI0.png");
        final BufferedImage bi = ImageIO.read(url);
        Runnable r = new Runnable() {
            @Override
            public void run() {
                JPanel gui = new JPanel(new BorderLayout());

                gui.add(new JLabel(
                        new ImageIcon(bi)), 
                        BorderLayout.PAGE_START);

                final BufferedImage bi2 = new BufferedImage(
                        400, 
                        150, 
                        BufferedImage.TYPE_INT_RGB);
                final JLabel l = new JLabel(
                        new ImageIcon(bi2), SwingConstants.CENTER);
                gui.add(l, BorderLayout.CENTER);
                ActionListener animatonListener = new ActionListener() {
                    Random rnd = new Random();

                    @Override
                    public void actionPerformed(ActionEvent e) {
                        Graphics2D g = bi2.createGraphics();
                        int x = rnd.nextInt(bi2.getWidth());
                        int y = rnd.nextInt(bi2.getHeight());
                        double theta = rnd.nextDouble()*2*Math.PI;
                        g.rotate(theta);
                        g.setClip(x,y,64,64);
                        g.drawImage(bi,x,y,null);
                        g.dispose();

                        l.repaint();
                    }
                };
                Timer timer = new Timer(50, animatonListener);
                timer.start();

                JOptionPane.showMessageDialog(null, gui);
                timer.stop();
            }
        };
        // Swing GUIs should be created and updated on the EDT
        // http://docs.oracle.com/javase/tutorial/uiswing/concurrency
        SwingUtilities.invokeLater(r);
    }
}
Community
  • 1
  • 1
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
  • Thats all well and good, but that is not what I need. I need a consistent clip section (viewPort) to display whatever would be behind it if the main image were rotated. – Adam Yost Mar 22 '14 at 15:18
  • I had no idea what you were talking about till I scrolled up and read your comment to Carlos. Easy done. Paint that before the clipping and transform are set. Give it a try. If you cannot get it to work, post a MCTaRE that hot-links to a 2nd image from the page linked above. There are several images suitable for a BG. *"..but that is not what I need"* – Andrew Thompson Mar 23 '14 at 00:08