GUI refactoring
- used only nodefactory for creation - merged MyDecisionPanel with LW
This commit is contained in:
@@ -21,7 +21,7 @@ public class PrototypeGUI extends MyDecisionPanel {
|
||||
};
|
||||
|
||||
public PrototypeGUI() {
|
||||
super(SmileLib.getNetworkFrom(PROTOTIPO), NODES);
|
||||
this.buildPanel(SmileLib.getNetworkFrom(PROTOTIPO), NODES);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -23,7 +23,7 @@ public class VehicleGUI extends MyDecisionPanel {
|
||||
};
|
||||
|
||||
public VehicleGUI() {
|
||||
super(SmileLib.getNetworkFrom(VEICOLO), NODES);
|
||||
this.buildPanel(SmileLib.getNetworkFrom(VEICOLO), NODES);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
package net.berack.upo.ai.gui;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Dimension;
|
||||
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JMenuBar;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JSeparator;
|
||||
|
||||
@@ -32,6 +35,7 @@ public class MainGUI extends JFrame {
|
||||
public final PrototypeGUI PrototypeGUI = new PrototypeGUI();
|
||||
public final VehicleGUI VehicleGUI = new VehicleGUI();
|
||||
|
||||
private final Dimension size = new Dimension(500, 400);
|
||||
private final JMenuBar menuBar = new JMenuBar();
|
||||
|
||||
/**
|
||||
@@ -44,7 +48,7 @@ public class MainGUI extends JFrame {
|
||||
this.setJMenuBar(menuBar);
|
||||
|
||||
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
this.setSize(500, 400);
|
||||
this.setSize(this.size);
|
||||
this.setResizable(false);
|
||||
this.setLocationRelativeTo(null);
|
||||
this.setVisible(true);
|
||||
@@ -88,11 +92,15 @@ public class MainGUI extends JFrame {
|
||||
*/
|
||||
private void setPanel(MyPanel panel) {
|
||||
if(panel instanceof MyDecisionPanel) {
|
||||
var scroll = new JScrollPane(panel);
|
||||
var temp = new JPanel(new BorderLayout());
|
||||
temp.add(panel, BorderLayout.NORTH);
|
||||
temp.setBorder(BorderFactory.createEmptyBorder(5, 5, 0, 5));
|
||||
|
||||
var scroll = new JScrollPane(temp);
|
||||
scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
|
||||
scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
|
||||
scroll.getVerticalScrollBar().setUnitIncrement(20);
|
||||
scroll.setPreferredSize(new Dimension(500, 400));
|
||||
scroll.setPreferredSize(this.size);
|
||||
this.setContentPane(scroll);
|
||||
}
|
||||
else this.setContentPane(panel);
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package net.berack.upo.ai.gui;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Font;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -24,21 +23,47 @@ import smile.Network;
|
||||
*/
|
||||
public abstract class MyDecisionPanel extends MyPanel {
|
||||
|
||||
public final Network net;
|
||||
private final List<NodeGUI> update = new ArrayList<>();
|
||||
protected Network net;
|
||||
protected final List<NodeGUI> update = new ArrayList<>();
|
||||
private Component[] components = new Component[0];
|
||||
|
||||
/**
|
||||
* Aggiunge dei componenti nel caso siano necessari che verranno mostrati nella prima parte del pannello
|
||||
* @param components i componenti da mostrare (devono essere pari)
|
||||
*/
|
||||
protected void setExtraComponents(Component[] components) {
|
||||
if(components.length % 2 != 0) throw new IllegalArgumentException("Must be a an even length array");
|
||||
this.components = components;
|
||||
}
|
||||
|
||||
/**
|
||||
* Costruisce il dinamicamente da una rete e da una lista di nodi da mostrare.
|
||||
* Il risultato sarà già inserito nel pannello e per vedere i valori bisognerà utilizzare il metodo updateAll()
|
||||
* @param net la rete da mostrare
|
||||
* @param nodes il sottoinsieme di nodi da mostrare
|
||||
* @param nodes il sottoinsieme di nodi da mostrare o (empty / null) per tutti i nodi
|
||||
*/
|
||||
protected MyDecisionPanel(Network net, String...nodes) {
|
||||
public void buildPanel(Network net, String...nodes) {
|
||||
this.net = net;
|
||||
var layout = new GroupLayout(this);
|
||||
if(this.net == null) return;
|
||||
|
||||
var size = new Dimension(500, 400);
|
||||
this.setSize(size);
|
||||
if(nodes == null || nodes.length == 0)
|
||||
this.buildNodes(this.net.getAllNodes());
|
||||
else {
|
||||
var handles = new int[nodes.length];
|
||||
for(var i = 0; i < nodes.length; i++) handles[i] = this.net.getNode(nodes[i]);
|
||||
this.buildNodes(handles);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Costruisce i nodi passati in input nel pannello
|
||||
* @param handles i nodi da costruire
|
||||
*/
|
||||
private void buildNodes(int[] handles) {
|
||||
this.update.clear();
|
||||
this.removeAll();
|
||||
|
||||
var layout = new GroupLayout(this);
|
||||
this.setLayout(layout);
|
||||
layout.setAutoCreateGaps(true);
|
||||
|
||||
@@ -47,8 +72,18 @@ public abstract class MyDecisionPanel extends MyPanel {
|
||||
var gBarch = layout.createParallelGroup();
|
||||
var vGroup = layout.createSequentialGroup();
|
||||
|
||||
for(var node: nodes) {
|
||||
var handle = net.getNode(node);
|
||||
for(var i = 0; i < this.components.length; i += 2) {
|
||||
var comp1 = this.components[i];
|
||||
var comp2 = this.components[i+1];
|
||||
|
||||
gLabel.addComponent(comp1);
|
||||
gBarch.addComponent(comp2);
|
||||
vGroup.addGroup(layout.createParallelGroup()
|
||||
.addComponent(comp1)
|
||||
.addComponent(comp2));
|
||||
}
|
||||
|
||||
for(var handle : handles) {
|
||||
var panel = factory.create(handle);
|
||||
update.add(panel);
|
||||
|
||||
@@ -78,7 +113,7 @@ public abstract class MyDecisionPanel extends MyPanel {
|
||||
* Utile per cambiare il font in BOLD e aumentarne la grandezza
|
||||
* @param component il componente da cambiare il font
|
||||
*/
|
||||
private void setFont(Component component) {
|
||||
protected void setFont(Component component) {
|
||||
var font = component.getFont();
|
||||
font = new Font(font.getName(), Font.BOLD, font.getSize() + 2);
|
||||
component.setFont(font);
|
||||
|
||||
@@ -60,7 +60,7 @@ public class DecisionNodeGUI extends NodeGUI {
|
||||
@Override
|
||||
public void updateNode() {
|
||||
var selected = this.net.isEvidence(this.node)? this.net.getEvidence(this.node) : -1;
|
||||
var values = this.net.getNodeValue(this.node);
|
||||
var values = this.getValues();
|
||||
var max = -1;
|
||||
if(values.length == this.buttons.length) {
|
||||
max = 0;
|
||||
|
||||
@@ -12,6 +12,7 @@ public abstract class NodeGUI extends JPanel {
|
||||
|
||||
public final Network net;
|
||||
public final int node;
|
||||
private double[] values = null;
|
||||
|
||||
/**
|
||||
* Salva informazioni essenziali del nodo
|
||||
@@ -27,6 +28,28 @@ public abstract class NodeGUI extends JPanel {
|
||||
this.node = node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Permette di impostare dei valori custom da mostrare.
|
||||
* Dopo la chiamata non verranno modificati i valori a schermo se non
|
||||
* si ha chiamato il metodo updateNode.
|
||||
*
|
||||
* @param values i valori da mostrare (dovranno essere compresi tra 0 e 1)
|
||||
*/
|
||||
public void setValues(double[] values) {
|
||||
for(var val : values) if(val < 0 || val > 1) throw new IllegalArgumentException();
|
||||
this.values = values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mostra i valori del nodo. Se sono stati passati dei valori custom allora userà quelli,
|
||||
* altrimenti prenderà i valori contenuti all'interno della rete.
|
||||
* @return i valori del nodo
|
||||
*/
|
||||
public double[] getValues() {
|
||||
if(this.values != null) return this.values;
|
||||
return this.net.getNodeValue(this.node);
|
||||
}
|
||||
|
||||
/**
|
||||
* In questo metodo si deve fare un refresh dei valori mostrati nel pannello.
|
||||
* I valori potranno essere presi direttamente dalla rete utilizzando le proprietà pubbliche net e node.
|
||||
|
||||
@@ -2,6 +2,7 @@ package net.berack.upo.ai.gui.nodes;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.GridLayout;
|
||||
import java.awt.Label;
|
||||
import java.util.function.Consumer;
|
||||
@@ -68,10 +69,7 @@ public class ProbabilityNodeGUI extends NodeGUI {
|
||||
if(action == null) lName.setBorder(null);
|
||||
else lName.addActionListener(a -> action.accept(index));
|
||||
|
||||
var size = barchart.getPreferredSize();
|
||||
size.width = 100;
|
||||
size.height = 10;
|
||||
barchart.setPreferredSize(size);
|
||||
barchart.setPreferredSize(new Dimension(100, 10));
|
||||
barchart.setBackground(COLORS[i % COLORS.length]);
|
||||
|
||||
|
||||
@@ -91,8 +89,8 @@ public class ProbabilityNodeGUI extends NodeGUI {
|
||||
|
||||
@Override
|
||||
public void updateNode() {
|
||||
var values = this.net.getNodeValue(this.node);
|
||||
var evidence = this.net.isEvidence(this.node)? this.net.getEvidence(node) : -1;
|
||||
var values = this.getValues();
|
||||
var evidence = this.net.isEvidence(this.node)? this.net.getEvidence(this.node) : -1;
|
||||
var enable = (values.length == this.outcomes.length);
|
||||
|
||||
for(var i = 0; i < this.outcomes.length; i++) {
|
||||
|
||||
@@ -39,7 +39,7 @@ public class UtilityNodeGUI extends NodeGUI {
|
||||
|
||||
@Override
|
||||
public void updateNode() {
|
||||
var values = this.net.getNodeValue(this.node);
|
||||
var values = this.getValues();
|
||||
var val = (values.length == 1) ? String.format("% 5.2f", values[0]) : " ";
|
||||
this.utility.setText(val);
|
||||
}
|
||||
|
||||
@@ -1,33 +1,24 @@
|
||||
package net.berack.upo.ai.problem3;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Component;
|
||||
import java.awt.FileDialog;
|
||||
import java.awt.Font;
|
||||
import java.util.Collection;
|
||||
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.GroupLayout;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JSeparator;
|
||||
import javax.swing.JTextArea;
|
||||
|
||||
import net.berack.upo.ai.gui.MyPanel;
|
||||
import net.berack.upo.ai.gui.MyDecisionPanel;
|
||||
|
||||
/**
|
||||
* Classe usata per far vedere il risultato di una run di lw su un network
|
||||
* @author Berack
|
||||
*/
|
||||
public class LikelihoodWeightingGUI extends MyPanel {
|
||||
public class LikelihoodWeightingGUI extends MyDecisionPanel {
|
||||
|
||||
private LikelihoodWeighting lw = null;
|
||||
private OutcomeChartGUI[] chartGUI = null;
|
||||
|
||||
private final JPanel scroll = new JPanel(); // tried using JScrollPane but nothing shows up
|
||||
private int totalRuns = 1000;
|
||||
|
||||
/**
|
||||
@@ -35,8 +26,13 @@ public class LikelihoodWeightingGUI extends MyPanel {
|
||||
* Siccome non c'è nessun network, il pannello sarà vuoto finchè non si apriranno dei network
|
||||
*/
|
||||
public LikelihoodWeightingGUI() {
|
||||
this.scroll.setPreferredSize(new Dimension(500, 400));
|
||||
this.add(this.scroll);
|
||||
var totLabel = new JLabel("Total Runs");
|
||||
var totValue = new JComboBox<>(new Integer[] {this.totalRuns, 5 * this.totalRuns, 10 * this.totalRuns, 20 * this.totalRuns});
|
||||
totValue.addItemListener(a -> this.totalRuns = (Integer) totValue.getSelectedItem());
|
||||
|
||||
this.setFont(totLabel);
|
||||
this.setExtraComponents(new Component[] { totLabel, totValue });
|
||||
this.buildPanel(null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -66,7 +62,15 @@ public class LikelihoodWeightingGUI extends MyPanel {
|
||||
try {
|
||||
var net = SmileLib.getNetworkFrom(fileName);
|
||||
this.lw = new LikelihoodWeighting(net);
|
||||
this.chartGUI = null;
|
||||
this.buildPanel(net);
|
||||
var totLabel = new JLabel("Total Runs");
|
||||
var totValue = new JComboBox<>(new Integer[] {this.totalRuns, 5 * this.totalRuns, 10 * this.totalRuns, 20 * this.totalRuns});
|
||||
totValue.addItemListener(a -> this.totalRuns = (Integer) totValue.getSelectedItem());
|
||||
this.setFont(totLabel);
|
||||
|
||||
this.add(totLabel);
|
||||
this.add(totValue);
|
||||
|
||||
this.updateAll();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
@@ -81,93 +85,11 @@ public class LikelihoodWeightingGUI extends MyPanel {
|
||||
if(this.lw == null) return;
|
||||
|
||||
this.lw.updateNetwork(totalRuns);
|
||||
var nodes = this.lw.getAllNodes();
|
||||
|
||||
if(chartGUI == null) buildPanel(nodes);
|
||||
|
||||
var i = 0;
|
||||
for(var node : nodes) chartGUI[i++].updateValues(node.values, node.evidence);
|
||||
|
||||
this.invalidate();
|
||||
this.validate();
|
||||
this.repaint();
|
||||
}
|
||||
|
||||
/**
|
||||
* Crea il pannello da zero usando i nodi passati in input come valori
|
||||
* @param nodes i nodi da mostrare
|
||||
*/
|
||||
private void buildPanel(Collection<NetworkNode> nodes) {
|
||||
var panel = new JPanel();
|
||||
var layout = new GroupLayout(panel);
|
||||
|
||||
panel.setLayout(layout);
|
||||
layout.setAutoCreateGaps(true);
|
||||
|
||||
var gLabel = layout.createParallelGroup();
|
||||
var gBarch = layout.createParallelGroup();
|
||||
var vGroup = layout.createSequentialGroup();
|
||||
|
||||
var totLabel = new JLabel("Total Runs");
|
||||
var totValue = new JComboBox<>(new Integer[] {this.totalRuns, 5 * this.totalRuns, 10 * this.totalRuns, 20 * this.totalRuns});
|
||||
totValue.addItemListener(a -> this.totalRuns = (Integer) totValue.getSelectedItem());
|
||||
|
||||
var font = totLabel.getFont();
|
||||
font = new Font(font.getName(), Font.BOLD, font.getSize() + 2);
|
||||
totLabel.setFont(font);
|
||||
|
||||
gLabel.addComponent(totLabel);
|
||||
gBarch.addComponent(totValue);
|
||||
vGroup.addGroup(layout.createParallelGroup()
|
||||
.addComponent(totLabel)
|
||||
.addComponent(totValue));
|
||||
|
||||
this.chartGUI = new OutcomeChartGUI[nodes.size()];
|
||||
var i = 0;
|
||||
|
||||
for(var node : nodes) {
|
||||
var net = node.net;
|
||||
var handle = node.handle;
|
||||
|
||||
var label = new JTextArea(node.name);
|
||||
label.setEditable(false);
|
||||
label.setLineWrap(true);
|
||||
label.setWrapStyleWord(true);
|
||||
label.setOpaque(false);
|
||||
label.setBorder(BorderFactory.createEmptyBorder());
|
||||
|
||||
var barch = new OutcomeChartGUI(node.outcomes, e -> {
|
||||
if(net.isEvidence(handle) && net.getEvidence(handle) == e)
|
||||
net.clearEvidence(handle);
|
||||
else net.setEvidence(handle, e);
|
||||
this.updateAll();
|
||||
});
|
||||
this.chartGUI[i++] = barch;
|
||||
|
||||
font = label.getFont();
|
||||
font = new Font(font.getName(), Font.BOLD, font.getSize() + 2);
|
||||
label.setFont(font);
|
||||
|
||||
gLabel.addComponent(label);
|
||||
gBarch.addComponent(barch);
|
||||
vGroup.addGroup(layout.createParallelGroup()
|
||||
.addComponent(label)
|
||||
.addComponent(barch));
|
||||
for(var node : this.update) {
|
||||
var values = this.lw.getNodeValue(node.node);
|
||||
node.setValues(values);
|
||||
node.updateNode();
|
||||
}
|
||||
|
||||
var hGroup = layout.createSequentialGroup();
|
||||
hGroup.addGroup(gLabel).addGroup(gBarch);
|
||||
|
||||
layout.setVerticalGroup(vGroup);
|
||||
layout.setHorizontalGroup(hGroup);
|
||||
|
||||
var sizes = this.scroll.getPreferredSize();
|
||||
sizes.height = panel.getMinimumSize().height;
|
||||
sizes.width -= 10;
|
||||
panel.setPreferredSize(sizes);
|
||||
|
||||
this.scroll.removeAll();
|
||||
this.scroll.add(panel);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,110 +0,0 @@
|
||||
package net.berack.upo.ai.problem3;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
import java.awt.GridLayout;
|
||||
import java.awt.Label;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
|
||||
/**
|
||||
* Classe che rappresenta gli outcome di un nodo di un network.
|
||||
* I valori deli outcome vengono visualizzati con un grafico.
|
||||
* @author Berack
|
||||
*/
|
||||
public class OutcomeChartGUI extends JPanel {
|
||||
public static final Color[] COLORS = {
|
||||
new Color(255,127,0),
|
||||
new Color(0,127,255),
|
||||
new Color(0,255,127),
|
||||
new Color(255,0,127),
|
||||
new Color(127,0,255),
|
||||
new Color(127,255,0),
|
||||
};
|
||||
|
||||
private JButton[] outcomes;
|
||||
private Label[] valuesChart;
|
||||
private JLabel[] valuesPercent;
|
||||
|
||||
/**
|
||||
* Crea il JPanel da visualizzare a partire da un NetworkNode appropriamente inizializzato.
|
||||
* Quando verrà visualizzato, il nodo avrà il nome degli output e i suoi valori in %
|
||||
* con una barra colorata per indicare la grandezza visivamente.
|
||||
*
|
||||
* @param labels i label degli output del nodo
|
||||
* @param action una azione da fare nel caso in cui venga premuto su un outcome
|
||||
*/
|
||||
public OutcomeChartGUI(String[] labels, Consumer<Integer> action) {
|
||||
var layout = new GridLayout(labels.length, 2);
|
||||
this.setLayout(layout);
|
||||
this.setBorder(BorderFactory.createCompoundBorder(new EmptyBorder(1, 0, 0, 0), BorderFactory.createLineBorder(Color.GRAY)));
|
||||
|
||||
this.outcomes = new JButton[labels.length];
|
||||
this.valuesChart = new Label[labels.length];
|
||||
this.valuesPercent = new JLabel[labels.length];
|
||||
|
||||
for(var i = 0; i < labels.length; i++) {
|
||||
var lName = new JButton(labels[i]);
|
||||
var lValue = new JLabel();
|
||||
var barchart = new Label();
|
||||
|
||||
this.outcomes[i] = lName;
|
||||
this.valuesChart[i] = barchart;
|
||||
this.valuesPercent[i] = lValue;
|
||||
|
||||
final var index = i;
|
||||
lName.setContentAreaFilled(false);
|
||||
lName.setFocusable(false);
|
||||
if(action == null) lName.setBorder(null);
|
||||
else lName.addActionListener(a -> action.accept(index));
|
||||
|
||||
var size = barchart.getPreferredSize();
|
||||
size.width = 100;
|
||||
size.height = 100;
|
||||
barchart.setPreferredSize(size);
|
||||
barchart.setBackground(COLORS[i % COLORS.length]);
|
||||
|
||||
|
||||
var panel1 = new JPanel();
|
||||
panel1.setLayout(new GridLayout(1, 2));
|
||||
panel1.add(lName);
|
||||
panel1.add(lValue);
|
||||
|
||||
var panel2 = new JPanel();
|
||||
panel2.setLayout(new BorderLayout());
|
||||
panel2.add(barchart, BorderLayout.LINE_START);
|
||||
|
||||
this.add(panel1);
|
||||
this.add(panel2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Modifica i valori mostrati a schermo cambiando anche la grandezza
|
||||
* della barra indicante il valore
|
||||
* @param values i nuovi valori da mostrare
|
||||
* @param evidence indica l'evidenza del nodo
|
||||
*/
|
||||
public void updateValues(double[] values, int evidence) {
|
||||
if(this.outcomes.length != values.length) throw new IllegalArgumentException("Arrays length myst be equals!");
|
||||
|
||||
for(var i = 0; i < this.outcomes.length; i++) {
|
||||
var value = values[i] * 100;
|
||||
var barchart = this.valuesChart[i];
|
||||
|
||||
var size = barchart.getSize();
|
||||
size.width = (int) (value * 1.5);
|
||||
barchart.setSize(size);
|
||||
barchart.setPreferredSize(size);
|
||||
|
||||
this.valuesPercent[i].setText(String.format("% 4.2f%%", value));
|
||||
if(evidence == i) this.outcomes[i].setForeground(Color.RED);
|
||||
else this.outcomes[i].setForeground(Color.BLACK);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user