0

I'm trying to implement my first MVC app which allows to push a button and increment a label on it.

This is the view:

public class View extends javax.swing.JFrame {

/**
 * Creates new form View
 */
public View() {
    initComponents();
    buttonAzzera.setEnabled(false);
}

/**
 * This method is called from within the constructor to initialize the form.
 * WARNING: Do NOT modify this code. The content of this method is always
 * regenerated by the Form Editor.
 */
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">                          
private void initComponents() {

    labelNumber = new javax.swing.JLabel();
    buttonAzzera = new javax.swing.JButton();
    buttonIncrementa = new javax.swing.JButton();

    setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
    getContentPane().setLayout(new java.awt.GridLayout(1, 0));

    labelNumber.setText("              0");
    getContentPane().add(labelNumber);

    buttonAzzera.setText("Azzera");
    getContentPane().add(buttonAzzera);

    buttonIncrementa.setText("Incrementa");
    getContentPane().add(buttonIncrementa);

    pack();
}// </editor-fold>                        

// Variables declaration - do not modify                     
private javax.swing.JButton buttonAzzera;
private javax.swing.JButton buttonIncrementa;
private javax.swing.JLabel labelNumber;
// End of variables declaration                   

public JButton getButtonIncrementa() {
    return buttonIncrementa;
}

public JButton getButtonAzzera() {
    return buttonAzzera;
}

public void setLabelNumber(String valore) {
    labelNumber.setText(valore);
}

}

and this is the simple Model:

public class Model {

    private int number;
    private boolean azzerabile;

    public Model() {
        number = 0;
        azzerabile = false;
    }

    //<editor-fold defaultstate="collapsed" desc="Getters and Setters">
    public int getNumber() {
        return number;
    }

    public void setNumber(int number) {
        this.number = number;
    }

    public boolean isAzzerabile() {
        return azzerabile;
    }

    public void setAzzerabile(boolean azzerabile) {
        this.azzerabile = azzerabile;
    }
//</editor-fold>

    public void incrementa() {
        number++;
        if (number == 5) {
            azzerabile = true;
        }
    }

    public void azzera() {
        number = 0;
        azzerabile = false;
    }

}

Now, Model and View are interconnected thanks to the Controller:

public class Controller {

private View view;
private Model model;


public Controller(View view, Model model) {
    this.view = view;
    this.model = model;
}


public void assegnaGestori() {
    ActionListener gestoreIncremento;
    ActionListener gestoreAzzeramento;

    gestoreIncremento = new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            model.incrementa();
            view.setLabelNumber(Integer.toString(model.getNumber()));
            // System.out.println("Ciao");
            if (model.isAzzerabile()) {
                view.getButtonAzzera().setEnabled(true);
            }
        }
    };

    view.getButtonIncrementa().addActionListener(gestoreIncremento);

    gestoreAzzeramento = new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            model.azzera();
            view.setLabelNumber("0");
            view.getButtonAzzera().setEnabled(false);
        }
    };

    view.getButtonAzzera().addActionListener(gestoreAzzeramento);

}

}

And I use a Main class to run the app:

public class Main {

public static void main(String args[]) {
    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
           Model model = new Model();
           View view = new View();
           Controller controller = new Controller(view, model);
           controller.assegnaGestori();
        }
    });
}

}

Unfortunately, when I click run no JFrame is shown, as this image shows:

no jframe shown

  • Where's the mistake?
  • 3
    At no point is your frame made visible (windows are hidden by default). I would, personally, be careful about using `JFrame` as a "view" and instead allow it to be a container for other "views", but that's me – MadProgrammer Nov 28 '19 at 22:09
  • 1
    If you're interested in why I might consider avoiding using `JFrame` (or any window based component) as a "view", you can have a look at [this](https://stackoverflow.com/questions/31576623/how-mvc-work-with-java-swing-gui/31576899#31576899) and [this](https://stackoverflow.com/questions/31602113/listener-placement-adhering-to-the-traditional-non-mediator-mvc-pattern/31604919#31604919) and [this](https://stackoverflow.com/questions/26517856/java-and-gui-where-do-actionlisteners-belong-according-to-mvc-pattern/26518274#26518274) – MadProgrammer Nov 28 '19 at 22:20
  • 2
    I use to say that Swing was not a "pure" MVC, but after lots more research, I think it's safer to say that what people consider a "MVC" is a misconception of the original intent. Remember, Swing is already based on MVC, so you're now complicating the problem by wrapping a MVC in a MVC :/. The original intention of MVC was to decouple the various layers of a user interface, so that the "model" was independent of the user interface/interaction and could be further applied to different domains (such as a GUI or a command line). I think people are taught MVC incorrectly now days - I know I was – MadProgrammer Nov 28 '19 at 22:23
  • @MadProgrammer: can you elaborate, perhaps even post an answer that details just what you mean in your last comment? This looks to be important information to share – Hovercraft Full Of Eels Nov 28 '19 at 22:27
  • 1
    [This blog](https://medium.com/flawless-app-stories/the-only-viable-ios-architecture-c42f7b4c845d) relates to iOS (and the mess people are making of it :D), but is relevant to any "mvc" as it talks about the original intention of MVC, which was never meant to be a "architecture" or "pattern" but a collection of concepts that could be used to decouple a complex problem. When you look at from that point of view, Swing's implementation of MVC makes a lot more sense. @HovercraftFullOfEels – MadProgrammer Nov 28 '19 at 22:32
  • @MadProgrammer thank you! – Hovercraft Full Of Eels Nov 28 '19 at 22:35
  • 1
    @abc123 For what's it's worth - IMHO - I would avoid exposing UI elements from the view to the controller directly. The view should be managing the UI elements itself and passing information to the controller through one or more contracts (ie listeners/observers). This way you further decouple the controller from the view, which is one of the (many) intents of MVC – MadProgrammer Nov 28 '19 at 22:37
  • I followed a tutorial in which MVC was implemented like this –  Nov 29 '19 at 08:11

1 Answers1

0

You just needed to change the name where you instantiated the new instance of the Controller class.

For example:

import javax.swing.SwingUtilities;

public class Main {

    public static void main(String args[]) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                Model model = new Model();
                View view = new View();
                Controller control = new Controller(view, model);
                control.assegnaGestori();
            }
        });
    }
}

Image of your project