如何在Java Swing MVC架构中显示图像? [英] How do I display an Image in Java Swing MVC architecture?

查看:102
本文介绍了如何在Java Swing MVC架构中显示图像?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的Java应用程序中,我的目标是使用MVC架构显示或输出图像.我的Java应用程序由imagecontroller(main),imageview和image模型组成.我目前能够选择一个图像,编译器会确认已从c:驱动器中选择了图像,但是它不会输出或显示该图像......................................................................................................................这是下面我的代码的副本:

 包imagecontroller;导入javax.swing.SwingUtilities;导入java.io.File;公共类ImageController {私有的最终ImageModel模型;私有的最终ImageView视图;公共ImageController(){this.view = new ImageView(this);this.model = new ImageModel(this.view);公共静态无效启动(){新的ImageController();}公共静态void main(String [] args){SwingUtilities.invokeLater(ImageController :: launch);}} 


 包imagecontroller;导入java.awt.Dimension;导入java.io.File;导入javax.swing.JFileChooser;导入javax.swing.JFrame;导入javax.swing.filechooser.FileNameExtensionFilter;公共类ImageView扩展了JFrame {私有的最终ImageController控制器;公共ImageView(ImageController控制器){this.controller =控制器;JFileChooser Chooser =新的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);整数结果Chooser.showOpenDialog(null);如果(结果== JFileChooser.APPROVE_OPTION){Chooser.setAcceptAllFileFilterUsed(true);文件selectedFile = Chooser.getSelectedFile();System.out.println(所选文件:" + selectedFile.getAbsolutePath());JFrame框架=新的JFrame();frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);frame.setTitle("ImageAnnotator");frame.setVisible(true);frame.setSize(new Dimension(500,500));}}} 


 包imagecontroller;导入java.awt.Color;导入java.awt.Dimension;导入java.awt.Graphics;导入java.awt.image.BufferedImage;导入java.io.File;导入java.io.IOException;导入javax.imageio.ImageIO;导入javax.swing.JComponent;导入javax.swing.JOptionPane;公共类ImageModel扩展了JComponent {私有的最终ImageView视图;私有BufferedImage图像;public ImageModel(ImageView view){this.view =视图;}公共无效的CustomComponent(文件png){BufferedImage image = null;setPreferredSize(new Dimension(400,400));尝试 {this.image = ImageIO.read(new File("640px-Pleiades_large.png")));} catch(IOException x){JOptionPane.showMessageDialog(null,不是图像文件,请选择图像");}}@Override公共无效paintComponent(Graphics g){super.paintComponent(g);g = g.create();g.setColor(Color.WHITE);g.fillRect(0,0,getWidth(),getHeight());整数保证金= 20;int w =(getWidth()-(2 *保证金+ 2))/2;int h = this.image.getHeight()* w/this.image.getWidth();g.drawImage(image,h,h,WIDTH,HEIGHT,view);}} 

解决方案

我真的觉得这很有趣,并想进一步研究它.从

TestApp.java :

  import javax.swing.SwingUtilities;公共类TestApp {公共TestApp(){createAndShowGUI();}公共静态void main(String [] args){SwingUtilities.invokeLater(TestApp :: new);}私人无效createAndShowGUI(){LoginModel模型=新的LoginModel();LoginView视图=新的LoginView();LoginController控制器=新的LoginController(视图,模型);}} 

LoginView.java:

  import java.awt.Color;导入java.awt.Component;导入java.beans.PropertyChangeEvent;导入java.beans.PropertyChangeListener;导入javax.swing.BoxLayout;导入javax.swing.JButton;导入javax.swing.JComponent;导入javax.swing.JFrame;导入javax.swing.JLabel;导入javax.swing.JOptionPane;导入javax.swing.JPanel;导入javax.swing.JTextField;导入javax.swing.border.EmptyBorder;公共类LoginView实现PropertyChangeListener {私有JFrame框架;私人JPanel loginPanel;私有JTextField usernameTextField;私有JTextField passwordTextField;私人JLabel errorLabel;私有JButton loginButton;公共LoginView(){initView();}私人无效initView(){frame = new JFrame("TestApp");frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);loginPanel = createLoginPanel();frame.add(loginPanel);frame.pack();frame.setVisible(true);}私人JPanel createLoginPanel(){JPanel面板=新的JPanel();panel.setBorder(newEmptyBorder(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 =新的JLabel("Password:");passwordLabel.setAlignmentX(Component.CENTER_ALIGNMENT);passwordTextField =新的JTextField();passwordTextField.setAlignmentX(Component.CENTER_ALIGNMENT);passwordTextField.setColumns(20);loginButton = new JButton("Login");loginButton.setAlignmentX(Component.CENTER_ALIGNMENT);errorLabel =新的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);返回面板;}公共JButton getLoginButton(){返回loginButton;}公共JTextField getUsernameTextField(){返回usernameTextField;}公共JTextField getPasswordTextField(){返回passwordTextField;}公共JFrame getFrame(){返回框架}@Override公共无效propertyChange(PropertyChangeEvent evt){字符串propertyName = evt.getPropertyName();对象newValue = evt.getNewValue();开关(propertyName){情况已认证"://验证完成后,我们可以做点什么onAuthenticatedPropertyChange((Boolean)newValue);休息;情况认证"://让我们在验证时禁用用户界面errorLabel.setVisible(false);disableLoginPanelComponents(true);休息;情况"usernameInvalid":showError((String)newValue);休息;情况"passwordInvalid":showError((String)newValue);休息;}}私人无效onAuthenticatedPropertyChange(已验证布尔值){如果(已验证== true){errorLabel.setVisible(false);JOptionPane.showMessageDialog(frame,您在!");} 别的 {showError(无效的用户名或密码!");}//验证成功后重新启用组件,无论失败或失败disableLoginPanelComponents(false);}私人无效showError(String error){errorLabel.setText(错误);errorLabel.setVisible(true);}私人void disableLoginPanelComponents(boolean disable){for(int i = 0; i< loginPanel.getComponentCount(); i ++){组件component =(Component)loginPanel.getComponent(i);if(JTextField的instance instanceof || JButton的component instanceof){((JComponent)loginPanel.getComponent(i)).setEnabled(!disable);}}}} 

LoginController:

  import java.awt.event.ActionEvent;导入javax.swing.SwingWorker;导入javax.swing.event.SwingPropertyChangeSupport;公共类LoginController {私有的最终SwingPropertyChangeSupport属性ChangeSupport;私有的最终LoginView视图;私有的最终LoginModel模型;公共LoginController(LoginView视图,LoginModel模型){this.view =视图;this.model =模型;propertyChangeSupport =新的SwingPropertyChangeSupport(this,true);initController();}私人无效initController(){//使视图成为模型和控制器的侦听器,因为两者都可以发送事件,视图也必须对此做出反应model.addPropertyChangeListener(view);propertyChangeSupport.addPropertyChangeListener(view);view.getLoginButton().addActionListener((ActionEvent e)-> {//让我们对用户名和密码字段进行一些基本验证字符串用户名= view.getUsernameTextField().getText();字符串密码= view.getPasswordTextField().getText();//在将用户输入发送到模型之前对其进行验证(这是控制者的工作-遵守业务规则,即用户名不存在等)如果(username.isEmpty()){propertyChangeSupport.firePropertyChange("usernameInvalid",null,用户名不能为空!");返回;}如果(password.isEmpty()){propertyChangeSupport.firePropertyChange("passwordInvalid",null,"Password不能为空!");返回;}//调用模型以在后台线程上登录,因为模型可能会查询数据库或访问API等新的SwingWorker< Void,Void>(){@Override受保护的Void doInBackground()引发异常{model.login(用户名,密码);返回null;}}.执行();});}} 

LoginModel.java:

  import java.beans.PropertyChangeListener;导入java.util.logging.Level;导入java.util.logging.Logger;导入javax.swing.event.SwingPropertyChangeSupport;公共类LoginModel {私有的最终SwingPropertyChangeSupport属性ChangeSupport;已验证的私有布尔值;公共LoginModel(){propertyChangeSupport =新的SwingPropertyChangeSupport(this,true);//我们在事件调度线程上将true传递给聪明的观察者}公共无效登录名(字符串用户名,字符串密码){propertyChangeSupport.firePropertyChange("authenticating",null,true);//让我们模拟查询数据库或某物3秒钟尝试 {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",为空,已验证);}公共无效addPropertyChangeListener(PropertyChangeListener prop){propertyChangeSupport.addPropertyChangeListener(prop);}public boolean isAuthenticated(){返回已认证的;}} 

以上内容是通用的,并不能直接回答您的问题,但会为您提供Swing中MVC模式的示例.

更新:

以下是针对您的问题的示例

  import java.awt.Color;导入java.awt.Component;导入java.awt.Dimension;导入java.awt.Graphics;导入java.awt.event.ActionEvent;导入java.awt.image.BufferedImage;导入java.beans.PropertyChangeEvent;导入java.beans.PropertyChangeListener;导入java.io.File;导入java.io.IOException;导入javax.imageio.ImageIO;导入javax.swing.BoxLayout;导入javax.swing.JButton;导入javax.swing.JFileChooser;导入javax.swing.JFrame;导入javax.swing.JLabel;导入javax.swing.JPanel;导入javax.swing.SwingUtilities;导入javax.swing.border.EmptyBorder;导入javax.swing.border.LineBorder;导入javax.swing.event.SwingPropertyChangeSupport;导入javax.swing.filechooser.FileNameExtensionFilter;公共类TestApp {公共TestApp(){createAndShowGUI();}公共静态void main(String [] args){SwingUtilities.invokeLater(TestApp :: new);}私人无效createAndShowGUI(){DisplayImageModel模型= new DisplayImageModel();DisplayImageView view = new DisplayImageView();DisplayImageController控制器=新的DisplayImageController(视图,模型);}类DisplayImageView实现PropertyChangeListener {私有JFrame框架;私人ImagePanel imagePanel;私人JLabel imageLabel;私有JButton pickImageButton;公共DisplayImageView(){initView();}私人无效initView(){frame = new JFrame("TestApp");frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);JPanel面板= createImagePanel();frame.add(panel);frame.pack();frame.setVisible(true);}私人JPanel createImagePanel(){JPanel面板=新的JPanel();panel.setBorder(newEmptyBorder(20,20,20,20));panel.setLayout(new BoxLayout(panel,BoxLayout.Y_AXIS));pickImageButton = new JButton("Pick a image");pickImageButton.setAlignmentX(Component.CENTER_ALIGNMENT);imagePanel = new ImagePanel();imagePanel.getPanel().setAlignmentX(Component.CENTER_ALIGNMENT);panel.add(imagePanel.getPanel());panel.add(pickImageButton);返回面板;}公共JButton getPickAnImageButton(){返回pickImageButton;}公共JLabel getImageLabel(){返回imageLabel;}公共JFrame getFrame(){返回框架}@Override公共无效propertyChange(PropertyChangeEvent evt){字符串propertyName = evt.getPropertyName();对象newValue = evt.getNewValue();开关(propertyName){案例图片":onImagePropertyChange(((BufferedImage)newValue);休息;}}私人无效onImagePropertyChange(BufferedImage image){imagePanel.setImage(image);frame.pack();}}类DisplayImageModel {私有的最终SwingPropertyChangeSupport属性ChangeSupport;私有BufferedImage图像;公共DisplayImageModel(){propertyChangeSupport =新的SwingPropertyChangeSupport(this,true);//我们在事件调度线程上将true传递给聪明的观察者}public void setImage(BufferedImage image){this.image =图片;propertyChangeSupport.firePropertyChange("image",null,image);}公共无效addPropertyChangeListener(PropertyChangeListener prop){propertyChangeSupport.addPropertyChangeListener(prop);}公共BufferedImage getImage(){返回图像;}}类DisplayImageController {私有的最终SwingPropertyChangeSupport属性ChangeSupport;私有的最终DisplayImageView视图;私有的最终DisplayImageModel模型;公共DisplayImageController(DisplayImageView视图,DisplayImageModel模型){this.view =视图;this.model =模型;propertyChangeSupport =新的SwingPropertyChangeSupport(this,true);initController();}私人无效initController(){//使视图成为模型和控制器的侦听器,因为两者都可以发送事件,视图也必须对此做出反应model.addPropertyChangeListener(view);propertyChangeSupport.addPropertyChangeListener(view);view.getPickAnImageButton().addActionListener((ActionEvent e)-> {JFileChooser选择器=新的JFileChooser();FileNameExtensionFilter filter = new FileNameExtensionFilter(" JPG&PNG图片","jpg","png");choicer.addChoosableFileFilter(filter);choicer.setFileSelectionMode(JFileChooser.FILES_ONLY);int结果= Chooser.showOpenDialog(view.getFrame());如果(结果== JFileChooser.APPROVE_OPTION){文件selectedFile = Chooser.getSelectedFile();BufferedImage图片;尝试 {图片= ImageIO.read(selectedFile);model.setImage(image);} catch(IOException ex){ex.printStackTrace();}}});}}类ImagePanel {私人的最终JPanel面板;私有BufferedImage图像;公共ImagePanel(){this.panel = new JPanel(){@Override公共维度getPreferredSize(){if(image!= null){返回新的Dimension(image.getWidth(),image.getHeight());} 别的 {返回新的Dimension(200,200);}}@Override受保护的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 =图片;panel.revalidate();panel.repaint();}公共JPanel getPanel(){返回面板;}}} 

In my java application, my objective is to display or output an image using MVC architecture. My java application is comprised of an imagecontroller(main), imageview, and image model. I am currently able to select an image, the compiler acknowledges where the image has been selected from in the c: drive however it does not output or display the image. Here is a copy of my code below:

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

解决方案

I really found this interesting and thought to explore it a little more. Taking pointers from The MVC pattern and Swing (which I suggest you read especially the accepted answer) lets try have a go.

Explanation:

Brief Summary of the code to follow (based off of the above link)

The LoginView. The view is simply your UI components, with getter methods for any components needed by the LoginController as well as implementing a PropertyChangeListener which is used by the view to receive PropertyChangeEvents which could be fired by our LoginController or LoginModel.

The LoginController The controller has access to both the view and the model. The controller sets up the necessary events on the views components and reacts to them by validating input from the view and then asks the model to do its job and potentially that will change its state. The controller takes your views actions and interprets them. If you click on a button, it's the controller's job to figure out what that means and how the model should be manipulated based on that action.

The controller may also ask the view to change it does this by subscribing the view (which implements PropertyChangeListener) to its SwingPropertyChangeSupport. When the controller receives an action from the view, in this case the Login button pressed it validates inputs from the view and fires the necessary validation errors (if any). It then calls the model to do the actual validation.

The LoginModel The controller calls methods on the model which intern notifies the view when its state has changed. 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.

The view can also ask the model for state. The view gets the state it displays directly from the model. For instance, if we pass in a model instance to our view which already has authenticated set to true, you will immediately receive the message to say you are logged in (this has not been demonstrated here, but would entail passing the model into the views constructor and after initializing the initView() doing something like 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 listeners are fired back on the EDT

Here is the code which demonstrates the above:

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

LoginView.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);
            }
        }
    }

}

LoginController:

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

    }
}

LoginModel.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;
    }
}

The above is generic and doesn't directly answer YOUR question but gives you an example of an MVC pattern in Swing.

Update:

Here is an example specific to your issue

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

}

这篇关于如何在Java Swing MVC架构中显示图像?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆