Last active
April 5, 2019 08:24
-
-
Save paul-hammant/2a5ef0b23809f4a9a34815422b7116bc to your computer and use it in GitHub Desktop.
Demo of MVC concepts using Java's Swing.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import javax.swing.*; | |
import javax.swing.text.AttributeSet; | |
import javax.swing.text.BadLocationException; | |
import javax.swing.text.PlainDocument; | |
import java.awt.*; | |
import java.awt.event.WindowAdapter; | |
import java.awt.event.WindowEvent; | |
public class Swing_MVC_MultiCounterDemo extends JFrame { | |
// See also two inner classes: CounterWidget & CounterModel | |
final CounterModel model; | |
public Swing_MVC_MultiCounterDemo() {{ | |
setTitle("Counter MVC demo using Swing"); | |
model = new CounterModel(0); | |
add(new JPanel(){{ | |
setBorder(BorderFactory.createTitledBorder("Single Shared Model")); | |
add(new CounterWidget(model).view); | |
add(new CounterWidget(model).view); | |
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); | |
}}); | |
add(new JPanel(){{ | |
setBorder(BorderFactory.createTitledBorder("Two Separate Models")); | |
add(new CounterWidget(new CounterModel(3)).view); | |
add(new CounterWidget(new CounterModel(17)).view); | |
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); | |
}}); | |
getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS)); | |
pack(); | |
setLocation(500, 500); | |
}} | |
public static void main(String[] args) { | |
Swing_MVC_MultiCounterDemo demo = new Swing_MVC_MultiCounterDemo(); | |
demo.addWindowListener(new WindowAdapter() | |
{ | |
@Override | |
public void windowClosing(WindowEvent e) | |
{ | |
e.getWindow().dispose(); | |
System.out.println("Frame closed, views/controllers eligible for GC, model value = " | |
+ demo.model.getCount() + ". Now exit."); ; | |
} | |
}); | |
demo.setVisible(true); | |
} | |
public class CounterWidget { | |
final View view; | |
class View extends JPanel { | |
final JTextField text; | |
final JButton plus; | |
final JButton minus; | |
View(CounterModel model) {{ | |
add(new JLabel("Count:")); | |
text = new JTextField("0", 4); | |
text.setDocument(model); | |
add(text); | |
plus = new JButton("+"); | |
final int s = (int) (getFont().getSize() * 1.7); | |
plus.setPreferredSize(new Dimension(s, s)); | |
add(plus); | |
minus = new JButton("-"); | |
minus.setPreferredSize(new Dimension(s, s)); | |
add(minus); | |
}} | |
} | |
CounterWidget(CounterModel model) { | |
view = new View(model); | |
// controller logic | |
view.plus.addActionListener(e -> { | |
model.increment(); | |
}); | |
view.minus.addActionListener(e -> { | |
model.decrement(); | |
}); | |
} | |
} | |
public class CounterModel extends PlainDocument { | |
CounterModel(int initialValue) { | |
setCount(initialValue); | |
} | |
void increment() { | |
setCount(getCount() + 1); | |
} | |
void decrement() { | |
setCount(getCount() - 1); | |
} | |
private void setCount(int i) { | |
try { | |
super.remove(0, getLength()); | |
super.insertString(0, "" + i, null); | |
} catch (BadLocationException e) { | |
throw new UnsupportedOperationException(e); | |
} | |
} | |
int getCount() { | |
try { | |
return Integer.parseInt(super.getText(0, super.getLength())); | |
} catch (BadLocationException e) { | |
throw new UnsupportedOperationException(e); | |
} | |
} | |
public void insertString(int offset, String str, AttributeSet attr) throws BadLocationException { | |
for (int i = 0; i < str.length(); i++) { | |
final char c = str.charAt(i); | |
if (!"0123456789".contains(String.valueOf(c))) | |
if (i == 0 && c != '-') { | |
return; | |
} | |
} | |
super.insertString(offset, str, attr); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
That app, when running, looks like:
The first two counters move up and down together. The third and fourth two are independent of each other (as well as independent to the first two).