Отображение изображения JFrame при изменении размера кадра

У меня есть этот JFrame, содержащий дочерний элемент JPanel, в котором он отображает изображение, объявленное таким образом.

BufferedImage image = ImageIO.read(filename);

Программа правильно отображает изображение. Но единственное, для отображения изображения требуется изменить размер кадра.

Есть ли способ отобразить изображение после появления рамки?


person Cyril Horad    schedule 06.07.2011    source источник
comment
Возможно, это происходит из-за того, что вы добавляете изображение после показа кадра. В качестве решения вы должны сначала добавить изображение, а затем сделать рамку видимой, или вы также можете вызвать repaint() после добавления изображения.   -  person Harry Joy    schedule 06.07.2011
comment
@Cyril Horad, если бы вы предоставили больше примеров кода, это помогло бы.   -  person mre    schedule 06.07.2011
comment
Можете ли вы сделать комментарий ответом для очистки темы. Спасибо. Я приму ответ.   -  person Cyril Horad    schedule 06.07.2011
comment
Возможно, вы могли бы попробовать снова реализовать метод рисования в своем собственном классе, который расширяет JPanel следующим образом: pastebin.com/3ZwVvr2v и убедитесь, что super.paintComponent(g) вызывается при создании вашей JPanel, чтобы JFrame рисовался с изображением.   -  person Kevin Gurney    schedule 06.07.2011
comment
Не могли бы вы также опубликовать код, где вы рисуете изображение?   -  person Serhiy    schedule 06.07.2011
comment
@little, это может показаться странным. Но я попытался создать метод, возвращающий BufferedImage из той же строки кода выше. И в методе рисования (Graphics g) я использовал этот метод, и он сработал.   -  person Cyril Horad    schedule 06.07.2011
comment
@Cyril Horad, вы никогда не должны явно вызывать paint(...) или переопределять его.   -  person mre    schedule 06.07.2011
comment
@Cyril Horad paint(...) делегирован для Awt и BasicXxxUI, для рисования в Swing есть paintComponent(...) как предложено @Kevin Gurney и @little bunny foo foo тоже   -  person mKorbel    schedule 06.07.2011
comment
@Cyril Horad, пожалуйста, посмотрите мое редактирование.   -  person mre    schedule 06.07.2011


Ответы (2)


Вы должны переопределить paintComponent(Graphics g) и нарисуйте в нем изображение. В этом случае вы должны сделать это для компонента JPanel (я думаю? Если нет, сделайте это для JComponent (ов), о которых вы говорите). Кроме того, поскольку Swing не является потокобезопасным, убедитесь, что эти изменения выполняются в файле EDT.

ПРИМЕР

public class Demo{
    private static BufferedImage bi;
    
    public static void main(String[] args){
        try{
            loadImage();
            
            SwingUtilities.invokeLater(new Runnable(){
                @Override
                public void run(){
                    createAndShowGUI();
                }
            });
        }
        catch (IOException e){
            // handle exception
        }
    }
    
    private static void loadImage() throws IOException{
        bi = ImageIO.read(new File("src/resource/braveheart.PNG"));
    }
    
    private static void createAndShowGUI(){
        final JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        final JPanel panel = new JPanel(){
            @Override
            protected void paintComponent(Graphics g){
                Graphics g2 = g.create();
                g2.drawImage(bi, 0, 0, getWidth(), getHeight(), null);
                g2.dispose();
            }
            
            @Override
            public Dimension getPreferredSize(){
                return new Dimension(bi.getWidth(), bi.getHeight());
            }
        };
        
        frame.add(panel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}

ВЫВОД

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

Важно иметь в виду, что в этом примере игнорируются подсказки по рендерингу, поэтому, когда вы максимизируете JFrame, качество изображения будет очень плохим. :)

ИЗМЕНИТЬ

Отвечая на этот вопрос, я предполагал, что вы имеете базовое представление о Swing. Полагаю, я слишком много предполагал. Важно отметить, что все компоненты должны быть добавлены в контейнер верхнего уровня до того, как он будет реализован (т. е. сделан видимым). Это гарантирует, что все будет отображаться без необходимости изменять размер кадра. Как и предполагали другие, вы могли бы просто использовать JLabel для рендеринга изображения, а затем добавить его в свой JPanel. Вместо этого я продвигал нестандартную живопись, что вполне приемлемо и, на мой взгляд, чище.

person mre    schedule 06.07.2011
comment
В чем разница между paint(Graphics g) и paintComponent(Graphics g)? - person Cyril Horad; 06.07.2011
comment
@Cyril Horad, paint(...) обрабатывает отрисовку содержимого, границ и дочерних элементов любого компонента Swing, тогда как paintComponent(...) используется для рендеринга компонента Swing и переопределяется, когда требуется пользовательский рендеринг. - person mre; 06.07.2011
comment
@little bunny foo foo для немного сложного способа +1 - person mKorbel; 06.07.2011
comment
@camickr, я не уверен, как переопределение paintComponent(...) изобретает велосипед? Это определенно более низкий уровень, чем использование JLabel, но это определенно не изобретение велосипеда. Для меня, используя JLabel, все, что вы делаете, это делегируете рендеринг изображения другому компоненту. - person mre; 06.07.2011
comment
Почему вы продвигаете пользовательское рисование вместо использования JLabel? Я всегда думал, что одна из целей программирования — НЕ изобретать велосипед. - person camickr; 06.07.2011
comment
Каждый раз, когда вы расширяете класс, это пользовательский код. Добавление пользовательского кода, когда функциональность поддерживается напрямую, для меня заново изобретает велосипед. Также этот вопрос не о том, как рисовать, а о том, как показать изображение, когда отображается рамка. Нигде в вашем ответе вы не упоминаете, что настоящая проблема заключается в использовании setVisible(). Теперь постер считает, что решением является метод paintComponent(), а не вызов setVisible после того, как компоненты были добавлены в кадр. - person camickr; 06.07.2011
comment
@camickr, наверное, я предполагал, что у OP есть базовое понимание Swing. В подходе, который я продвигал, нет ничего плохого, на самом деле я думаю, что он более предпочтителен, но это всего лишь вопрос мнения. Мне жаль, что наши взгляды на это не совпадают. - person mre; 06.07.2011
comment
@camickr, ты закончил? если мой ответ покажется вам недостаточным, не стесняйтесь вмешаться и дать свой собственный ответ. в моем ответе нет абсолютно ничего плохого. хотя я не обращался к некоторым проблемам явно, я неявно отвечал на них. - person mre; 06.07.2011
comment
При отображении текста вы используете JLabel или создаете пользовательский компонент и используете метод Graphics.drawString()? Я предполагаю, что вы используете JLabel, так почему же вы предпочитаете пользовательское рисование изображения вместо того, чтобы позволить JLabel сделать всю работу за вас? Я не пытаюсь быть занозой в заднице. Я честно не понимаю разницы. - person camickr; 06.07.2011

для отображения изображения или ImageIcon лучше искать JLabel (базовые вещи)

person mKorbel    schedule 06.07.2011
comment
+1, согласен, используйте существующие компоненты вместо того, чтобы изобретать велосипед. - person camickr; 06.07.2011
comment
@camickr, забавно, как вы проголосовали за это (потому что этот ответ совпадает с вашим мнением), хотя @mKorbel не обратил внимания на исходную проблему. вот почему я воспринимаю вашу критику с долей скептицизма. :) - person mre; 06.07.2011
comment
@little bunny foo foo, это совсем не смешно. В этом смысл голосования за ответ. Вы голосуете за то, что считаете лучшим подходом. Я считаю, что использование JLabel для отображения изображения лучше, чем использование пользовательского кода. Независимо от того, решает ли это проблему или нет, это все еще верное утверждение. Всякий раз, когда я делаю комментарий, я приводил причину для комментария, чтобы люди могли принять обоснованное решение. Утверждение чего-то более предпочтительного без объяснения причин ничего не значит :) - person camickr; 06.07.2011
comment
@camickr, хахахаха, я нахожу это забавным. - person mre; 06.07.2011
comment
@camickr @little bunny foo foo, пожалуйста, в последний раз выключите свет, Роб ++ - person mKorbel; 06.07.2011
comment
@mKorbel, лмао... что угодно, чувак. вы оба смешны. - person mre; 06.07.2011