【问题标题】:image to show up when I press the button in java swing (error in frame.add( ) )当我按下 java swing 中的按钮时显示的图像(frame.add() 中的错误)
【发布时间】:2021-12-08 21:22:54
【问题描述】:

你好,首先当我运行程序时会出现一个按钮,当我按下按钮时,图像会从上到下。 当图像从上到下时,我尝试了代码,效果很好 但是当我将所有代码放在一起时,( frame.add(new AnimationPane() ); )中出现错误

问题:如何将 AnimationPane() 添加到框架中? 因为这是我的问题。

我想制作两个场景的想法,第一个有一个按钮可以转到第二个场景,它将有一个图像(它必须从顶部推到向下)。

    /*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package maincontentpaneswitching;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

public class MainContentPaneSwitching {
    
    private static class ChangeContentPaneListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            // I want to put the image here
            JPanel newFrameContents = new JPanel(); //Uses FlowLayout by default.
            newFrameContents.add(new JLabel("You have successfully changed the content pane of the frame!", JLabel.CENTER));
            
            /*We assume that the source is a JButton and that the Window is of type JFrame, hence
            the following utility method call is possible without letting any errors appear:*/
            JFrame frame = (JFrame) SwingUtilities.getWindowAncestor((JButton) e.getSource());
            frame.setSize(600, 300);  

                
            
            
            frame.setContentPane(newFrameContents); //Change the content pane of the frame.
            frame.revalidate(); //Notify the frame that the component hierarchy has changed.
             frame.add(new AnimationPane()  );
            frame.pack(); //Resize the frame as necessary in order to fit as many contents as possible in the screen.
           
            frame.setLocationRelativeTo(null); //Place the frame in the center of the screen. As you can tell, this needs its size to calculate the location, so we made sure in the previous line of code that it is set.
            frame.repaint(); //Repaint frame with all its contents.
        }
    }
     public class AnimationPane extends JPanel {
 
        private BufferedImage boat;
        private int yPos = 0;
        private int direction = 1;

        public AnimationPane() {
            try {
                 boat = ImageIO.read(new URL("https://i.stack.imgur.com/memI0.png"));
                Timer timer = new Timer(50, new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        yPos += direction;
                        if (yPos + boat.getHeight() > getHeight()) {
                            yPos = getHeight() - boat.getHeight();
                            direction *= +1;
                        } else if (yPos < 0) {
                            yPos = 0;
                            direction *= +1;
                        }
                        repaint();
                    }

                });
                timer.setRepeats(true);
                timer.setCoalesce(true);
                timer.start();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }

        @Override
        public Dimension getPreferredSize() {
            return boat == null ? super.getPreferredSize() : new Dimension(boat.getHeight()*2 , boat.getWidth() *2);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);

            int x = getWidth() - boat.getWidth();
            g.drawImage(boat, x,  yPos, this);

        }

    }
    
    private static class MainRunnable implements Runnable {
        @Override
        public void run() {
            JButton changeContentPaneButton = new JButton("Click to go to the next image!");
            changeContentPaneButton.addActionListener(new ChangeContentPaneListener());
            
            JPanel frameContents = new JPanel(); //Uses FlowLayout by default.
            frameContents.add(changeContentPaneButton);
            
            JFrame frame = new JFrame("My application");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //Tells the frame that when the user closes it, it must terminate the application.
            frame.setContentPane(frameContents); //Add contents to the frame.
            frame.pack(); //Resize the frame as necessary in order to fit as many contents as possible in the screen.
            frame.setLocationRelativeTo(null); //Place the frame in the center of the screen. As you can tell, this needs its size to calculate the location, so we made sure in the previous line of code that it is set.
            frame.setVisible(true);
        }
    }
    
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new MainRunnable()); //Swing code must always be used in the Event Dispatch Thread.
    }
}

【问题讨论】:

  • 我放了图片的链接,现在你可以运行了。
  • 将animationPane添加到frame时出现错误
  • 我尝试修复您的代码,但无法让图像动画正常工作。您过于依赖静态字段和方法。你的 getPreferredSize 是落后的。应该是宽度,高度。在显示任何内容之前创建完整的 GUI。使用 CardLayout 显示按钮 JPanel,然后显示图像 JPanel。分开你的顾虑。您的绘图 JPanel 应该绘制图像。时期。您可以在与绘图类分开的控制器类中修改 yPos。在开始构建 GUI 之前阅读所有图像。
  • 感谢您的努力和建议。

标签: java image swing


【解决方案1】:

简介

正如我在评论中所说,我无法让图像动画正常工作。至少这段代码会给你一个坚实的开始。

这是我想出的 GUI。

这是左键单击按钮后的 GUI。

如果您要将 cmets 添加到代码中,请将 cmets 放在与代码不同的行中。不是每个人都有大显示器,可以阅读 200 多行代码。

说明

Oracle 有一个 rad 教程,Creating a GUI With Swing。跳过 Netbeans 部分。

当我创建 Swing GUI 时,我使用 model/view/controller (MVC) 模式。这种模式让我可以将关注点分开,一次只专注于应用程序的一个部分。

在 Swing 中,MVC 模式意味着:

  • 视图从模型中读取信息
  • 视图可能不会更新模型
  • 控制器更新模型并重新绘制/重新验证视图。

通常没有一个控制器可以“统辖”它们。每个侦听器控制其模型和视图的一部分。

当我组装一个应用程序时,我会编写一小段代码,然后运行测试。我可能进行了两到三打测试,这主要是由你编写的。

型号

我创建了一个BoatImage 类来读取船图像。这是一个单独的类,所以我可以在开始构建 GUI 之前读取图像。

查看

我创建了一个JFrame。我用CardLayout 创建了一个主JPanel

我使用CardLayout 来布局按钮JPanel 和图像JPanel。这样,JFrame 的大小就不会不断变化。

我将JFrameJPanels 创建为单独的方法/类。这让包括您自己在内的其他人更容易阅读和理解视图代码。

控制器

我对@9​​87654337@ 进行了编码,以将按钮JPanel 更改为图像JPanel。这是您放置图像动画代码的地方。

代码

这是完整的可运行代码。我将所有额外的类都设为内部类,这样我就可以将这段代码作为一个块发布。

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;

import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

public class MainContentPaneSwitching implements Runnable {
    
    public static void main(String[] args) {
        // Swing code must always be used in the Event Dispatch Thread.
        SwingUtilities.invokeLater(new MainContentPaneSwitching()); 
    }
    
    private AnimationPane animationPane;
    
    private BoatImage boatImage;
    
    private CardLayout cardLayout;
    
    private JPanel mainPanel;
    
    public MainContentPaneSwitching() {
        this.boatImage = new BoatImage();
    }
    
    @Override
    public void run() {
        JFrame frame = new JFrame("My application");
        // Tells the frame that when the user closes it, it
        // must terminate the application.
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.mainPanel = createMainPanel();
        frame.add(mainPanel, BorderLayout.CENTER);
        // Resize the frame as necessary in order to fit as many contents 
        // as possible in the screen.
        frame.pack(); 
        // Place the frame in the center of the screen. As you can tell, this
        // needs its size to calculate the location, so we made sure in the
        // previous line of code that it is set.
        frame.setLocationRelativeTo(null); 
        frame.setVisible(true);
    }
    
    private JPanel createMainPanel() {
        cardLayout = new CardLayout();
        JPanel panel = new JPanel(cardLayout);
        
        panel.add(createButtonPanel(), "button");
        
        animationPane = new AnimationPane(boatImage);
        panel.add(animationPane, "image");
        
        return panel;
    }
    
    private JPanel createButtonPanel() {
        JPanel panel = new JPanel(new FlowLayout());
        panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
        
        JButton changeContentPaneButton = new JButton(
                "Click to go to the next image!");
        changeContentPaneButton.addActionListener(
                new ChangeContentPaneListener(this, boatImage));
        panel.add(changeContentPaneButton);
        
        return panel;
    }
    
    public JPanel getAnimationPane() {
        return animationPane;
    }
    
    public void repaint() {
        animationPane.repaint();
    }

    public class AnimationPane extends JPanel {
        
        private static final long serialVersionUID = 1L;
        
        private BoatImage boat;

        public AnimationPane(BoatImage boat) {
            this.boat = boat;
            BufferedImage image = boat.getBoat();
            this.setPreferredSize(new Dimension(image.getWidth(), 
                    image.getHeight()));
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);

            BufferedImage image = boat.getBoat();
            int x = getWidth() - image.getWidth();
            g.drawImage(image, x, boat.getyPos(), this);
        }

    }
    
    private class ChangeContentPaneListener implements ActionListener {
        
        private int direction, yPos;
        
        private final MainContentPaneSwitching view;
        
        private final BoatImage model;
         
        public ChangeContentPaneListener(MainContentPaneSwitching view, 
                BoatImage model) {
            this.view = view;
            this.model = model;
            this.direction = 1;
            this.yPos = 0;
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            cardLayout.show(mainPanel, "image");
        }
    }
    
    public class BoatImage {
        
        private int yPos;
        
        private BufferedImage boat;
        
        public BoatImage() {
            try {
                URL url = new URL("https://i.stack.imgur.com/memI0.png");
                boat = ImageIO.read(url); // boat.jpg
            } catch (MalformedURLException e) {
                e.printStackTrace();
                boat = null;
            } catch (IOException e) {
                e.printStackTrace();
                boat = null;
            }
            
            this.yPos = 0;
        }

        public BufferedImage getBoat() {
            return boat;
        }

        public void setyPos(int yPos) {
            this.yPos = yPos;
        }

        public int getyPos() {
            return yPos;
        }
        
    }
    
}

【讨论】:

    猜你喜欢
    • 2012-10-10
    • 1970-01-01
    • 2020-11-14
    • 2018-03-13
    • 1970-01-01
    • 2014-05-15
    • 1970-01-01
    • 2020-10-01
    • 2018-01-06
    相关资源
    最近更新 更多