簡體   English   中英

如何在 Java Swing MVC 架構中顯示圖像?

[英]How do I display an Image in Java Swing MVC architecture?

在我的 java 應用程序中,我的目標是使用 MVC 架構顯示或 output 圖像。 我的 java 應用程序由圖像控制器(主)、imageview 和圖像 model 組成。 我目前能夠 select 圖像,編譯器確認從 c 中選擇圖像的位置:驅動器但它不 output 或顯示圖像。 下面是我的代碼的副本:

package imagecontroller;

import javax.swing.SwingUtilities;
import java.io.File;

    public class ImageController {
    
    private final ImageModel model;
    private final ImageView view; 

public ImageController () {
    this.view = new ImageView(this);
    this.model = new ImageModel(this.view);

public static void launch () {
    new ImageController();

}
    public static void main(String[] args) {
    SwingUtilities.invokeLater(ImageController::launch);   
    } 
}   

package imagecontroller;

import java.awt.Dimension;
import java.io.File;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.filechooser.FileNameExtensionFilter;    

      public class ImageView extends JFrame{
       
     private final ImageController controller;
    
        public ImageView(ImageController controller) {
            this.controller = controller;
    
            JFileChooser Chooser = new JFileChooser();
            FileNameExtensionFilter filter = new FileNameExtensionFilter("JPG & PNG Images", "jpg", "png");
            Chooser.addChoosableFileFilter(filter);
            Chooser.setCurrentDirectory(new File(System.getProperty("user.home")));
            Chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
            int result 

      

         Chooser.showOpenDialog(null);
            if (result == JFileChooser.APPROVE_OPTION) {
                Chooser.setAcceptAllFileFilterUsed(true);
                File selectedFile = Chooser.getSelectedFile();
                System.out.println("Selected file: " + selectedFile.getAbsolutePath());
    
                JFrame frame = new JFrame();
                frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                frame.setTitle("ImageAnnotator");
                frame.setVisible(true);
                frame.setSize(new Dimension (500,500));
        
        } 
        
        }
    }

package imagecontroller;


import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JComponent;
import javax.swing.JOptionPane;
    
    
        public class ImageModel extends JComponent  {    
            private final ImageView view;
            private BufferedImage image;
           
            public ImageModel(ImageView view) {
                this.view = view;
            }
            public void CustomComponent (File png) {
                BufferedImage image = null; 
                setPreferredSize(new Dimension(400, 400));
              try {
                    this.image = ImageIO.read(new File("640px-Pleiades_large.png"));
                } catch (IOException x) {
                    JOptionPane.showMessageDialog(null, "Not an ImageFile, Please Select an Image");
                }
            }
            @Override
             public void paintComponent(Graphics g){
                super.paintComponent(g);
                g = g.create();
                g.setColor(Color.WHITE);
                g.fillRect(0, 0, getWidth(), getHeight());
                int margin = 20;
                int w = (getWidth() - (2 * margin + 2)) / 2;
                int h = this.image.getHeight() * w / this.image.getWidth();
                g.drawImage(image, h, h, WIDTH, HEIGHT, view);
        
        }
        }

我真的覺得這很有趣,並想進一步探索它。 MVC 模式和 Swing (我建議您特別閱讀已接受的答案)中獲取指針,讓我們嘗試使用 go。

說明

要遵循的代碼的簡要摘要(基於上述鏈接)

登錄視圖 視圖只是您的 UI 組件,為LoginController所需的任何組件提供了getter方法,並實現了一個PropertyChangeListener視圖使用它來接收可由我們的LoginControllerLoginModel觸發PropertyChangeEvent

LoginController controller 可以訪問視圖model controller 在視圖組件上設置必要的事件,並通過驗證來自視圖的輸入來對它們做出反應,然后要求 model 完成其工作,這可能會改變其 Z9ED39E2EA931586B3A985A69EZEF5。 controller 采取您的意見行動並解釋它們。 如果您單擊一個按鈕,控制器的工作就是確定這意味着什么以及如何根據該操作操作model

controller還可以通過將視圖(實現PropertyChangeListener )訂閱到其SwingPropertyChangeSupport來要求視圖更改它。 controller視圖接收到一個動作時,在這種情況下,按下登錄按鈕會驗證來自視圖的輸入並觸發必要的驗證錯誤(如果有)。 然后調用model進行實際驗證。

LoginModel controller調用 model 上的方法,當其 state 發生更改時,該方法會通知視圖 When something changes in the model , based either on some action you took (like clicking a button) the model notifies the view that its state has changed through the same mechanism as the controller .

視圖還可以向 model 詢問 state。 該視圖獲取 state,它直接從 model 顯示。 例如,如果我們將model實例傳遞給已經將authenticated設置為 true 的視圖,您將立即收到消息說您已登錄(此處尚未演示,但需要將model傳遞給視圖構造函數並在初始化initView()之后執行類似onAuthenticatedPropertyChange(model.isAuthenticated()) ) 的操作。

Some extra information is both controller and model implement the observer pattern (as in the view observes changes to the controller and models in order to react to them) The controller also does all model execution on a background thread via a SwingWorker , and all property change聽眾在 EDT 上被反擊

這是演示上述內容的代碼:

![在此處輸入圖像描述

TestApp.java

import javax.swing.SwingUtilities;

public class TestApp {

    public TestApp() {
        createAndShowGUI();

    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(TestApp::new);
    }

    private void createAndShowGUI() {
        LoginModel model = new LoginModel();
        LoginView view = new LoginView();
        LoginController controller = new LoginController(view, model);
    }
}

登錄視圖.java:

import java.awt.Color;
import java.awt.Component;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.EmptyBorder;

public class LoginView implements PropertyChangeListener {

    private JFrame frame;
    private JPanel loginPanel;
    private JTextField usernameTextField;
    private JTextField passwordTextField;
    private JLabel errorLabel;
    private JButton loginButton;

    public LoginView() {
        initView();
    }

    private void initView() {
        frame = new JFrame("TestApp");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        loginPanel = createLoginPanel();

        frame.add(loginPanel);
        frame.pack();
        frame.setVisible(true);
    }

    private JPanel createLoginPanel() {
        JPanel panel = new JPanel();
        panel.setBorder(new EmptyBorder(20, 20, 20, 20));
        panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
        JLabel usernameLabel = new JLabel("Username:");
        usernameLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
        usernameTextField = new JTextField();
        usernameTextField.setAlignmentX(Component.CENTER_ALIGNMENT);
        usernameTextField.setColumns(20);
        JLabel passwordLabel = new JLabel("Password:");
        passwordLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
        passwordTextField = new JTextField();
        passwordTextField.setAlignmentX(Component.CENTER_ALIGNMENT);
        passwordTextField.setColumns(20);
        loginButton = new JButton("Login");
        loginButton.setAlignmentX(Component.CENTER_ALIGNMENT);
        errorLabel = new JLabel();
        errorLabel.setForeground(Color.RED);
        errorLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
        errorLabel.setVisible(false);
        panel.add(usernameLabel);
        panel.add(usernameTextField);
        panel.add(passwordLabel);
        panel.add(passwordTextField);
        panel.add(errorLabel);
        panel.add(loginButton);
        return panel;
    }

    public JButton getLoginButton() {
        return loginButton;
    }

    public JTextField getUsernameTextField() {
        return usernameTextField;
    }

    public JTextField getPasswordTextField() {
        return passwordTextField;
    }

    public JFrame getFrame() {
        return frame;
    }

    @Override
    public void propertyChange(PropertyChangeEvent evt) {
        String propertyName = evt.getPropertyName();
        Object newValue = evt.getNewValue();

        switch (propertyName) {
            case "authenticated":
                // authentication has finished lets do something
                onAuthenticatedPropertyChange((Boolean) newValue);
                break;
            case "authenticating":
                // lets disable the UI as we authenticate
                errorLabel.setVisible(false);
                disableLoginPanelComponents(true);
                break;
            case "usernameInvalid":
                showError((String) newValue);
                break;
            case "passwordInvalid":
                showError((String) newValue);
                break;

        }
    }

    private void onAuthenticatedPropertyChange(Boolean authenticated) {
        if (authenticated == true) {
            errorLabel.setVisible(false);
            JOptionPane.showMessageDialog(frame, "You are in!");
        } else {
            showError("Invalid username or password!");
        }

        // re-enable components after authentication regadless of fail or pass
        disableLoginPanelComponents(false);
    }

    private void showError(String error) {
        errorLabel.setText(error);
        errorLabel.setVisible(true);
    }

    private void disableLoginPanelComponents(boolean disable) {
        for (int i = 0; i < loginPanel.getComponentCount(); i++) {
            Component component = (Component) loginPanel.getComponent(i);
            if (component instanceof JTextField || component instanceof JButton) {
                ((JComponent) loginPanel.getComponent(i)).setEnabled(!disable);
            }
        }
    }

}

登錄控制器:

import java.awt.event.ActionEvent;
import javax.swing.SwingWorker;
import javax.swing.event.SwingPropertyChangeSupport;

public class LoginController {

    private final SwingPropertyChangeSupport propertyChangeSupport;
    private final LoginView view;
    private final LoginModel model;

    public LoginController(LoginView view, LoginModel model) {
        this.view = view;
        this.model = model;
        propertyChangeSupport = new SwingPropertyChangeSupport(this, true);
        initController();
    }

    private void initController() {
        // make the view a listener of both the model and controller as both can send events which the view must react too
        model.addPropertyChangeListener(view);
        propertyChangeSupport.addPropertyChangeListener(view);

        view.getLoginButton().addActionListener((ActionEvent e) -> {

            // lets do some basic validation of username and password fields
            String username = view.getUsernameTextField().getText();
            String password = view.getPasswordTextField().getText();

            // validate user input before sending it to the model (this is the contorllers job - besdoes business rules i..e username doesnt exist etc)
            if (username.isEmpty()) {
                propertyChangeSupport.firePropertyChange("usernameInvalid", null, "Username cannot be empty!");
                return;
            }

            if (password.isEmpty()) {
                propertyChangeSupport.firePropertyChange("passwordInvalid", null, "Password cannot be empty!");
                return;
            }

            // call the model to login on a background thread as the model may query the db or hit an API etc
            new SwingWorker<Void, Void>() {
                @Override
                protected Void doInBackground() throws Exception {
                    model.login(username, password);
                    return null;
                }
            }.execute();
        });

    }
}

登錄型號.java:

import java.beans.PropertyChangeListener;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.event.SwingPropertyChangeSupport;

public class LoginModel {

    private final SwingPropertyChangeSupport propertyChangeSupport;
    private boolean authenticated;

    public LoginModel() {
        propertyChangeSupport = new SwingPropertyChangeSupport(this, true); // we pass in true to noifty observers on the Event Dispatch Thread
    }

    public void login(String username, String password) {
        
        propertyChangeSupport.firePropertyChange("authenticating", null, true);
        
        // lets simulate query a database or something for 3 seconds
        try {
            Thread.sleep(3000);
        } catch (InterruptedException ex) {
            Logger.getLogger(LoginModel.class.getName()).log(Level.SEVERE, null, ex);
        }
        
        authenticated = username.equals("admin") && password.equals("password");
        propertyChangeSupport.firePropertyChange("authenticated", null, authenticated);
    }

    public void addPropertyChangeListener(PropertyChangeListener prop) {
        propertyChangeSupport.addPropertyChangeListener(prop);
    }
    
    public boolean isAuthenticated() {
        return authenticated;
    }
}

以上是通用的,並沒有直接回答的問題,而是為您提供了 Swing 中的 MVC 模式示例。

更新:

這是特定於您的問題的示例

在此處輸入圖像描述

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
import javax.swing.event.SwingPropertyChangeSupport;
import javax.swing.filechooser.FileNameExtensionFilter;

public class TestApp {

    public TestApp() {
        createAndShowGUI();
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(TestApp::new);
    }

    private void createAndShowGUI() {
        DisplayImageModel model = new DisplayImageModel();
        DisplayImageView view = new DisplayImageView();
        DisplayImageController controller = new DisplayImageController(view, model);
    }

    class DisplayImageView implements PropertyChangeListener {

        private JFrame frame;
        private ImagePanel imagePanel;
        private JLabel imageLabel;
        private JButton pickImageButton;

        public DisplayImageView() {
            initView();
        }

        private void initView() {
            frame = new JFrame("TestApp");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

            JPanel panel = createImagePanel();

            frame.add(panel);
            frame.pack();
            frame.setVisible(true);
        }

        private JPanel createImagePanel() {
            JPanel panel = new JPanel();
            panel.setBorder(new EmptyBorder(20, 20, 20, 20));
            panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
            pickImageButton = new JButton("Pick an image");
            pickImageButton.setAlignmentX(Component.CENTER_ALIGNMENT);
            imagePanel = new ImagePanel();
            imagePanel.getPanel().setAlignmentX(Component.CENTER_ALIGNMENT);
            panel.add(imagePanel.getPanel());
            panel.add(pickImageButton);
            return panel;
        }

        public JButton getPickAnImageButton() {
            return pickImageButton;
        }

        public JLabel getImageLabel() {
            return imageLabel;
        }

        public JFrame getFrame() {
            return frame;
        }

        @Override
        public void propertyChange(PropertyChangeEvent evt) {
            String propertyName = evt.getPropertyName();
            Object newValue = evt.getNewValue();

            switch (propertyName) {
                case "image":
                    onImagePropertyChange((BufferedImage) newValue);
                    break;
            }
        }

        private void onImagePropertyChange(BufferedImage image) {
            imagePanel.setImage(image);
            frame.pack();
        }
    }

    class DisplayImageModel {

        private final SwingPropertyChangeSupport propertyChangeSupport;
        private BufferedImage image;

        public DisplayImageModel() {
            propertyChangeSupport = new SwingPropertyChangeSupport(this, true); // we pass in true to noifty observers on the Event Dispatch Thread
        }

        public void setImage(BufferedImage image) {
            this.image = image;
            propertyChangeSupport.firePropertyChange("image", null, image);
        }

        public void addPropertyChangeListener(PropertyChangeListener prop) {
            propertyChangeSupport.addPropertyChangeListener(prop);
        }

        public BufferedImage getImage() {
            return image;
        }
    }

    class DisplayImageController {

        private final SwingPropertyChangeSupport propertyChangeSupport;
        private final DisplayImageView view;
        private final DisplayImageModel model;

        public DisplayImageController(DisplayImageView view, DisplayImageModel model) {
            this.view = view;
            this.model = model;
            propertyChangeSupport = new SwingPropertyChangeSupport(this, true);
            initController();
        }

        private void initController() {
            // make the view a listener of both the model and controller as both can send events which the view must react too
            model.addPropertyChangeListener(view);
            propertyChangeSupport.addPropertyChangeListener(view);

            view.getPickAnImageButton().addActionListener((ActionEvent e) -> {
                JFileChooser chooser = new JFileChooser();
                FileNameExtensionFilter filter = new FileNameExtensionFilter(
                        "JPG & PNG Images", "jpg", "png");
                chooser.addChoosableFileFilter(filter);
                chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);

                int result = chooser.showOpenDialog(view.getFrame());
                if (result == JFileChooser.APPROVE_OPTION) {
                    File selectedFile = chooser.getSelectedFile();
                    BufferedImage image;
                    try {
                        image = ImageIO.read(selectedFile);
                        model.setImage(image);
                    } catch (IOException ex) {
                        ex.printStackTrace();
                    }
                }
            });

        }
    }

    class ImagePanel {

        private final JPanel panel;
        private BufferedImage image;

        public ImagePanel() {
            this.panel = new JPanel() {
                @Override
                public Dimension getPreferredSize() {
                    if (image != null) {
                        return new Dimension(image.getWidth(), image.getHeight());
                    } else {
                        return new Dimension(200, 200);
                    }
                }

                @Override
                protected void paintComponent(Graphics g) {
                    super.paintComponent(g);
                    if (image != null) {
                        g.drawImage(image, 0, 0, this);
                    }
                }
            };
            panel.setBorder(new LineBorder(Color.GRAY, 1));
        }

        public void setImage(BufferedImage image) {
            this.image = image;
            panel.revalidate();
            panel.repaint();
        }

        public JPanel getPanel() {
            return panel;
        }
    }

}

MVC 模式之所以稱為 MVC 模式,是因為顧名思義。 換句話說,創建 model,然后是視圖,然后是控制器。

這是我放在一起的圖像顯示 GUI。

圖像顯示圖形用戶界面

所以,讓我們從 model 開始。 對於圖像查看器 GUI,model 非常簡單。

public class ImageDisplayModel {
    
    private BufferedImage image;
    
    private File file;

    public BufferedImage getImage() {
        return image;
    }

    public void setImage(BufferedImage image) {
        this.image = image;
    }

    public File getFile() {
        return file;
    }

    public void setFile(File file) {
        this.file = file;
    }
    
}

ImageDisplayModel class 是一個普通的 Java class ,它包含一個BufferedImage和一個File路徑。 通過保存File路徑,下次用戶選擇圖片時,目錄將設置為與上一張圖片相同。

ImageDisplayModel class 是一個普通的 getter/setter class。

下一步是創建視圖。

public class ImageDisplay implements Runnable {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new ImageDisplay());
    }
    
    private ImageDisplayModel model;
    
    private ImagePanel imagePanel;
    
    private JFrame frame;
    
    public ImageDisplay() {
        this.model = new ImageDisplayModel();
    }
    
    @Override
    public void run() {
        frame = new JFrame("Image Display");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setJMenuBar(createMenuBar());
        
        imagePanel = new ImagePanel(model);
        frame.add(imagePanel, BorderLayout.CENTER);
        
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }
    
    private JMenuBar createMenuBar() {
        JMenuBar menubar = new JMenuBar();
        
        JMenu filemenu = new JMenu("File"); 
  
        JMenuItem openitem = new JMenuItem("Open...");
        openitem.addActionListener(new OpenFileListener(this, model));
        filemenu.add(openitem);
        
        menubar.add(filemenu);
        
        return menubar;
    }
    
    public void updateImagePanel(int width, int height) {
        imagePanel.setPreferredSize(width, height);
        imagePanel.repaint();
        frame.pack();
    }
    
    public JFrame getFrame() {
        return frame;
    }

}

我們通過調用SwingUtilitiesinvokeLater方法來啟動應用程序。 此方法確保在Event Dispatch Thread上創建和執行 Swing 組件。

視圖構造函數實例化應用程序 model。

JFrame代碼在run方法中。

JMenuBar方法允許我們一個接一個地 select 多個圖像。

getFrame方法允許最終的 controller class 訪問JFrame實例。 updateImagePanel方法允許最終的 controller class 更新圖像面板。

接下來,我們創建繪圖面板DrawingPanel

public class ImagePanel extends JPanel {

    private static final long serialVersionUID = 1L;
    
    private ImageDisplayModel model;
    
    public ImagePanel(ImageDisplayModel model) {
        this.model = model;
        this.setPreferredSize(649, 480);
    }
    
    public void setPreferredSize(int width, int height) {
        this.setPreferredSize(new Dimension(width, height));
    }
    
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        
        BufferedImage image = model.getImage();
        if (image != null) {
            g.drawImage(image, 0, 0, this);
        }
    }
    
}

簡單明了。 如果存在,我們繪制BufferedImage 我們還調整了JPanel的大小,以使圖像適合。

繪圖面板 class 需要的唯一信息是DrawingPanel class。 繪圖面板將繪制圖像。 時期。

最后,我們創建 controller class。

public class OpenFileListener implements ActionListener {
    
    private ImageDisplay frame;
    
    private ImageDisplayModel model;

    public OpenFileListener(ImageDisplay frame, ImageDisplayModel model) {
        this.frame = frame;
        this.model = model;
    }

    @Override
    public void actionPerformed(ActionEvent event) {
        JFileChooser chooser = new JFileChooser();
        FileNameExtensionFilter filter = new FileNameExtensionFilter(
                "JPG & PNG Images", "jpg", "png");
        chooser.addChoosableFileFilter(filter);
        chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
        
        File file = model.getFile();
        if (file != null) {
            chooser.setCurrentDirectory(file);            
        }
        
        int result = chooser.showOpenDialog(frame.getFrame());
        if (result == JFileChooser.APPROVE_OPTION) {
            File selectedFile = chooser.getSelectedFile();
            model.setFile(selectedFile);
            BufferedImage image;
            try {
                image = ImageIO.read(selectedFile);
                model.setImage(image);
                frame.updateImagePanel(image.getWidth(), 
                        image.getHeight());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
}

controller class 更新 model 信息並指示視圖重新繪制自身。 controller 與視圖內部無關。 controller 需要知道的只是視圖可以更新。

最后,這是完整的可運行代碼。 我將類設為內部類,因此我可以將此代碼作為一個塊發布。

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.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.filechooser.FileNameExtensionFilter;

public class ImageDisplay implements Runnable {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new ImageDisplay());
    }
    
    private ImageDisplayModel model;
    
    private ImagePanel imagePanel;
    
    private JFrame frame;
    
    public ImageDisplay() {
        this.model = new ImageDisplayModel();
    }
    
    @Override
    public void run() {
        frame = new JFrame("Image Display");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setJMenuBar(createMenuBar());
        
        imagePanel = new ImagePanel(model);
        frame.add(imagePanel, BorderLayout.CENTER);
        
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }
    
    private JMenuBar createMenuBar() {
        JMenuBar menubar = new JMenuBar();
        
        JMenu filemenu = new JMenu("File"); 
  
        JMenuItem openitem = new JMenuItem("Open...");
        openitem.addActionListener(new OpenFileListener(this, model));
        filemenu.add(openitem);
        
        menubar.add(filemenu);
        
        return menubar;
    }
    
    public void updateImagePanel(int width, int height) {
        imagePanel.setPreferredSize(width, height);
        imagePanel.repaint();
        frame.pack();
    }
    
    public JFrame getFrame() {
        return frame;
    }
    
    public class ImagePanel extends JPanel {

        private static final long serialVersionUID = 1L;
        
        private ImageDisplayModel model;
        
        public ImagePanel(ImageDisplayModel model) {
            this.model = model;
            this.setPreferredSize(649, 480);
        }
        
        public void setPreferredSize(int width, int height) {
            this.setPreferredSize(new Dimension(width, height));
        }
        
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            
            BufferedImage image = model.getImage();
            if (image != null) {
                g.drawImage(image, 0, 0, this);
            }
        }
        
    }
    
    public class OpenFileListener implements ActionListener {
        
        private ImageDisplay frame;
        
        private ImageDisplayModel model;

        public OpenFileListener(ImageDisplay frame, ImageDisplayModel model) {
            this.frame = frame;
            this.model = model;
        }

        @Override
        public void actionPerformed(ActionEvent event) {
            JFileChooser chooser = new JFileChooser();
            FileNameExtensionFilter filter = new FileNameExtensionFilter(
                    "JPG & PNG Images", "jpg", "png");
            chooser.addChoosableFileFilter(filter);
            chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
            
            File file = model.getFile();
            if (file != null) {
                chooser.setCurrentDirectory(file);            
            }
            
            int result = chooser.showOpenDialog(frame.getFrame());
            if (result == JFileChooser.APPROVE_OPTION) {
                File selectedFile = chooser.getSelectedFile();
                model.setFile(selectedFile);
                BufferedImage image;
                try {
                    image = ImageIO.read(selectedFile);
                    model.setImage(image);
                    frame.updateImagePanel(image.getWidth(), 
                            image.getHeight());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        
    }
    
    public class ImageDisplayModel {
        
        private BufferedImage image;
        
        private File file;

        public BufferedImage getImage() {
            return image;
        }

        public void setImage(BufferedImage image) {
            this.image = image;
        }

        public File getFile() {
            return file;
        }

        public void setFile(File file) {
            this.file = file;
        }
        
    }

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM