0
I modified it this example of MVC to try to make it more like my MVC vision (in which the role of the Controller is not very clear). I ended up with a program that only has Views and Model, without Controller. Where the Controller should be?
One thing that surprised me was that I created a behavior of observing the state of the view. My idea was that there would be only observation of the state of the Model, then I realized that I needed to implement the view state observation (method OneOfTheViews.update()
). This behavior is expected to occur in the MVC?
Another relatively unexpected thing was that the views are nested, that is, there is a MainPanel
that is the mother of other views. I don’t know if this is right in MVC or not.
P.S.: The program was set up with the short classes, right? Point for MVC :D
Mvcgame.java
package piovezan.mvcdesktop_trashgod;
import java.awt.EventQueue;
import javax.swing.JFrame;
import piovezan.mvcdesktop_trashgod.view.MainPanel;
public class MvcGame implements Runnable {
public static void main(String[] args) {
// Componentes Swing devem ser construídos no EDT (event-dispatching thread).
EventQueue.invokeLater(new MvcGame());
}
@Override
public void run() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new MainPanel().asComponent());
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
Piece java.
package piovezan.mvcdesktop_trashgod.model;
import java.awt.Color;
public enum Piece {
RED(Color.red),
GREEN(Color.green),
BLUE(Color.blue);
private final Color color;
private Piece(Color color) {
this.color = color;
}
public Color getColor() {
return color;
}
}
Java model.
package piovezan.mvcdesktop_trashgod.model;
import java.util.Observable;
import java.util.Random;
/**
* Model
*/
public class Model extends Observable {
private static final Random RAND_NUM_GEN = new Random();
private Piece hidden = init();
private Piece init() {
Piece[] pieces = Piece.values();
return pieces[RAND_NUM_GEN.nextInt(pieces.length)];
}
public void reset() {
hidden = init();
setChanged();
notifyObservers();
}
public void check(Piece guess) {
setChanged();
notifyObservers(guess.equals(hidden));
}
}
Java mainpanel.
package piovezan.mvcdesktop_trashgod.view;
import java.awt.BorderLayout;
import javax.swing.JLabel;
import javax.swing.JPanel;
import piovezan.mvcdesktop_trashgod.model.Model;
public final class MainPanel {
private final JPanel mainPanel;
public MainPanel() {
mainPanel = new JPanel(new BorderLayout());
Model model = new Model();
JLabel label = new JLabel("Guess what color!", JLabel.CENTER);
mainPanel.add(label, BorderLayout.NORTH);
OneOfTheViews view = new OneOfTheViews(model);
mainPanel.add(view.asComponent(), BorderLayout.CENTER);
ControlPanel controlPanel = new ControlPanel(model);
mainPanel.add(controlPanel.asComponent(), BorderLayout.SOUTH);
}
public JPanel asComponent() {
return mainPanel;
}
}
Oneoftheviews.java
package piovezan.mvcdesktop_trashgod.view;
import java.awt.BorderLayout;
import java.awt.Color;
import java.util.Observable;
import java.util.Observer;
import javax.swing.JLabel;
import javax.swing.JPanel;
import piovezan.mvcdesktop_trashgod.model.Model;
import piovezan.mvcdesktop_trashgod.model.Piece;
/**
* View
*/
public class OneOfTheViews {
private static final String TEXT_CLICK_A_BUTTON = "Click a button.";
private final JPanel panel = new JPanel(new BorderLayout());
private final ColorRoundIcon icon = new ColorRoundIcon(80, Color.gray);
private final JLabel labelMoveOutcome = initLabel();
private final Model model;
public OneOfTheViews(Model model) {
this.model = model;
model.addObserver(new ModelObserver());
panel.add(labelMoveOutcome, BorderLayout.CENTER);
panel.add(genButtonPanel(), BorderLayout.SOUTH);
}
public JPanel asComponent() {
return panel;
}
private JLabel initLabel() {
JLabel label = new JLabel(TEXT_CLICK_A_BUTTON, icon, JLabel.CENTER);
label.setVerticalTextPosition(JLabel.BOTTOM);
label.setHorizontalTextPosition(JLabel.CENTER);
return label;
}
private JPanel genButtonPanel() {
JPanel panel = new JPanel();
for (Piece piece : Piece.values()) {
PieceButton pieceButton = new PieceButton(piece, this);
panel.add(pieceButton.asComponent());
}
return panel;
}
public void update(Piece piece) {
icon.setColor(piece.getColor());
labelMoveOutcome.repaint();
model.check(piece);
}
private class ModelObserver implements Observer {
@Override
public void update(Observable o, Object arg) {
if (arg == null) {
labelMoveOutcome.setText(TEXT_CLICK_A_BUTTON);
icon.setColor(Color.gray);
} else if ((Boolean) arg) {
labelMoveOutcome.setText("Win!");
} else {
labelMoveOutcome.setText("Keep trying.");
}
}
}
}
Controlpanel.java
package piovezan.mvcdesktop_trashgod.view;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JPanel;
import piovezan.mvcdesktop_trashgod.model.Model;
/**
* Control panel
*/
public class ControlPanel {
private static final String RESET_LABEL = "Reset";
private final Model model;
private final JPanel panel = new JPanel();
private final JButton resetButton = new JButton(RESET_LABEL);
public ControlPanel(Model model) {
this.model = model;
panel.add(resetButton);
resetButton.addActionListener(new ResetButtonHandler());
}
public JPanel asComponent() {
return panel;
}
private class ResetButtonHandler implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
String cmd = e.getActionCommand();
if (RESET_LABEL.equals(cmd)) {
model.reset();
}
}
}
}
Colorroundicon.java
package piovezan.mvcdesktop_trashgod.view;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.util.Objects;
import javax.swing.Icon;
public final class ColorRoundIcon implements Icon {
private final int size;
private Color color;
public ColorRoundIcon(int size, Color color) {
this.size = size;
this.color = color;
}
@Override
public void paintIcon(Component c, Graphics g, int x, int y) {
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(color);
g2d.fillOval(x, y, size, size);
}
@Override
public int getIconWidth() {
return size;
}
@Override
public int getIconHeight() {
return size;
}
public void setColor(Color color) {
this.color = Objects.requireNonNull(color);
}
}
Piecebutton.java
package piovezan.mvcdesktop_trashgod.view;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import piovezan.mvcdesktop_trashgod.model.Piece;
public final class PieceButton {
private final JButton pieceButton;
private final Piece piece;
private final OneOfTheViews view;
public PieceButton(Piece piece, OneOfTheViews view) {
this.piece = piece;
this.view = view;
this.pieceButton = new JButton(new ColorRoundIcon(16, piece.getColor()));
this.pieceButton.addActionListener(new PieceButtonHandler());
}
public Piece getPiece() {
return piece;
}
public JButton asComponent() {
return pieceButton;
}
private class PieceButtonHandler implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
view.update(piece);
}
}
}
Your answer went out of the question. OP wanted to know where the controller is and you just tried to explain what the MVC is. It didn’t help much.
– Fernando Silveira