Изменение размера рисунка в соответствии с размером кадра

Я написал приложение, которое рисует все внутри paint() на основе фиксированных позиций пикселей. Затем я отключил изменение размера кадра, чтобы он всегда был виден.

Однако теперь я хотел бы изменить его размер, но я не хочу менять свой код рисования. Я надеялся, что смогу захватить квадрат 300x300 объекта Graphics g и изменить его размер до текущего размера JFrame после всего моего прорисовывающего кода, но я понятия не имею, что делаю.

Вот пример кода. В этом я хочу, чтобы квадрат 100x100 оставался посередине, пропорционально измененному размеру 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);
    }
}

Спасибо.


person Bryan Bueter    schedule 19.08.2011    source источник
comment
Вы никогда не должны переопределять метод paint() JFrame (если вы действительно не знаете, что делаете). Пользовательское рисование выполняется путем переопределения метода paintComponent() панели JPanel или JComponent.   -  person camickr    schedule 19.08.2011
comment
Настоящий код рисует все на холсте внутри JFrame, я для краткости просто рисовал сверху. Тем не менее, спасибо, поскольку я действительно не знаю, что я делаю.   -  person Bryan Bueter    schedule 19.08.2011


Ответы (4)


Предполагая, что вы переименовали свой метод, который рисует для 300x300, как paint300, определите буферизованное изображение:

@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
}

Выше показано, когда вы хотите рисовать в полном размере (300x300). Если размер вашего окна изменился:

@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);
}

Новые классы взяты из java.awt.image.*.

Я не тестировал этот код. Это просто, чтобы направить вас в правильном направлении.

person toto2    schedule 19.08.2011
comment
Да, это оно! Однако я использовал ReplicateScaleFilter(width, height) вместо CropImageFilter(), чтобы он масштабировался до нового размера окна. Именно то, что я искал. - person Bryan Bueter; 19.08.2011

если вы хотите рисовать пользовательскую краску, найдите JLabel или JPanel, включая Icon/ImageIcon внутри, простой пример об этом

введите здесь описание изображениявведите здесь описание изображения

введите здесь описание изображения

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);
        }
    }
}
person mKorbel    schedule 19.08.2011
comment
Это не отвечает на вопрос ОП. - person Jeffrey; 19.08.2011
comment
@Jeffrey huuuh Я говорю не об изменении размера пользовательской 2D-графики, а о том, как правильно рисовать в Swing, кстати, было бы неплохо знать, как предотвратить мерцание или зависание вашего кода, это было бы ответом на OP, не интересует меня, а не мое проблема вообще - person mKorbel; 19.08.2011
comment
Я позволил себе обновить ваш пример; такой компонент ценен для изучения этих проблем. Пожалуйста, верните, если неверно; извиняюсь, если перегнул палку. - person trashgod; 20.08.2011

Не эксперт, но вы можете просто масштабировать объект Graphics2D (переданный объект Graphics на самом деле является экземпляром Graphics2D), где отношения x и y представляют собой отношения фиксированного размера, который вы выбрали для рисования, и фактического размера кадра.

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

person JB Nizet    schedule 19.08.2011
comment
Я не мог заставить масштаб работать непосредственно на графическом объекте рисования. Кажется, мне нужно было нарисовать буферизованное изображение, а затем масштабировать его с помощью фильтров. Может быть, я что-то пропустил, но теперь у меня есть ответ. - person Bryan Bueter; 19.08.2011

Вы могли бы сделать это с некоторой математикой.

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);

}

Или, если вы хотите, чтобы ширина и высота блока оставались одинаковыми, используйте int width = this.getWidth() / 3; и int height = this.getHeight() / 3.

Другой вариант — использовать Graphics2D.scale(), как указал JB, переданный объект Graphics на самом деле является объектом Graphics2D.

person Jeffrey    schedule 19.08.2011
comment
Математика — причина, по которой я хотел масштабироваться, у меня много сотен строк кода, которые нужно было бы отредактировать. - person Bryan Bueter; 19.08.2011