6

I've written an app that custom draws everything inside paint() based on fixed pixel positions. Then I disabled resize of the frame so its always visible.

However, now I would like to be able to resize it but I dont want to change my drawling code. I was hoping I could grab the 300x300 square of the Graphics g object and resize it to the JFrame current size after all of my drawling code, but I have no idea what I'm doing.

Here sample code. In this I want the 100x100 square to remain in the middle, proportionate to the resized JFrame:

package DrawAndScale;

import java.awt.Color;
import java.awt.Graphics;

public class DASFrame extends javax.swing.JFrame {
    public DASFrame() {
        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        this.setSize(300, 300);
    }

    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new DASFrame().setVisible(true);
            }
        });
    }

    @Override
    public void paint(Graphics g) {
        g.setColor(Color.BLACK);
        g.fill3DRect(100, 100, 100, 100, true);
    }
}

Thanks.

mKorbel
  • 109,525
  • 20
  • 134
  • 319
Bryan Bueter
  • 95
  • 1
  • 5
  • 1
    You should never override the paint() method of a JFrame (unless you really know what you are doing). Custom painting is done by overriding the paintComponent() method of a JPanel or JComponent. – camickr Aug 19 '11 at 16:18
  • The real code draws everything on a canvas within the JFrame, I just drew on top for brevity. However, thank you, as I really dont know what I'm doing. – Bryan Bueter Aug 19 '11 at 17:56

4 Answers4

3

Assuming you rename your method that paints for 300x300 as paint300, define a buffered image:

@Override public void paint(Graphics g) {
     Image bufferImage = createImage(300, 300);  // empty image
     paint300(bufferImage.getGraphics());  // fill the image
     g.drawImage(bufferImage, 0, 0, null);  // send the image to graphics device
}

Above is when you want to draw at full size (300x300). If your window is resized:

@Override public void paint(Graphics g) {
     Image bufferImage = createImage(300, 300);  
     paint300(bufferImage.getGraphics());
     int width = getWidth();
     int height = getHeight(); 
     CropImageFilter crop = 
         new CropImageFilter((300 - width)/2, (300 - height)/2 , width, height);
     FilteredImageSource fis = new FilteredImageSource(bufferImage, crop);
     Image croppedImage = createImage(fis);
     g.drawImage(croppedImage, 0, 0, null);
}

The new classes are from from java.awt.image.*.

I didn't test this code. It's just to send you in the right direction.

toto2
  • 5,306
  • 21
  • 24
  • 1
    Yes, this is it! However, I used ReplicateScaleFilter(width, height) instead of CropImageFilter(), that way it scales to the new window size. Exactly what I was looking for. – Bryan Bueter Aug 19 '11 at 17:40
2

if you want to painting Custom paint then look for JLabel or JPanel and including Icon/ImageIcon inside, simple example about that

enter image description here enter image description here

enter image description here

import java.awt.*;
import javax.swing.*;

public class MainComponentPaint extends JFrame {

    private static final long serialVersionUID = 1L;

    public MainComponentPaint() {
        setTitle("Customize Preffered Size Test");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    public void display() {
        add(new CustomComponent());
        pack();
        setMinimumSize(getSize());
        setPreferredSize(getSize());
    SwingUtilities.invokeLater(new Runnable() {

        @Override
        public void run() {
            setVisible(true);
        }
    });
    }

    public static void main(String[] args) {
        MainComponentPaint main = new MainComponentPaint();
        main.display();
    }
}

class CustomComponent extends JComponent {

    private static final long serialVersionUID = 1L;

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(50, 50);
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        int w = getWidth();
        int h = getHeight();
        for (int i = 0; i < Math.max(w, h); i += 20) {
            g.drawLine(i, 0, i, h);
            g.drawLine(0, i, w, i);
        }
    }
}
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
mKorbel
  • 109,525
  • 20
  • 134
  • 319
  • This doesn't answer the OP's question. – Jeffrey Aug 19 '11 at 15:53
  • @Jeffrey huuuh I not talking about resizing Custom 2D Graphics, but How to Paint in Swing correctly, btw nice would be to know how to prevents your code against flickering or freeze, that would be answer to OP, not interest me, and not my issue at all – mKorbel Aug 19 '11 at 17:39
  • I took the liberty of updating your example; such a component is valuable for studying these problems. Please revert if incorrect; pologies if I overstepped. – trashgod Aug 20 '11 at 02:35
1

Not an expert, but you could just scale the Graphics2D object (the passed Graphics is in fact a Graphics2D instance), where the x and y ratios are the ratios of the fixed size you chose to draw and the actual size of the frame.

See http://download.oracle.com/javase/6/docs/api/java/awt/Graphics2D.html#scale%28double,%20double%29

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • I couldnt get scale to work directly on the paint graphics object. It seems I needed to paint on a buffered image and then scale it using filters. Maybe I missed something, but I have the answer now. – Bryan Bueter Aug 19 '11 at 17:44
1

You could do this with some math.

public void paint(Graphics g){
    int height = 100;
    int width = 100;

    int x = (this.getWidth() / 2) - (width / 2);
    int y = (this.getHeight() / 2) - (height / 2);

    g.setColor(Color.BLACK);
    g.fill3DRect(x, y, width, height, true);

}

Or if you wanted to keep the width and height of the box with the same proportion, use int width = this.getWidth() / 3; and int height = this.getHeight() / 3.

The other option is to use Graphics2D.scale(), as JB pointed out, the passed Graphics object is actually a Graphics2D object.

Jeffrey
  • 44,417
  • 8
  • 90
  • 141