Torna indietro   Hardware Upgrade Forum > Software > Programmazione

Polestar 3 Performance, test drive: comodità e potenza possono convivere
Polestar 3 Performance, test drive: comodità e potenza possono convivere
Abbiamo passato diversi giorni alla guida di Polestar 3, usata in tutti i contesti. Come auto di tutti i giorni è comodissima, ma se si libera tutta la potenza è stupefacente
Qualcomm Snapdragon X2 Elite: l'architettura del SoC per i notebook del 2026
Qualcomm Snapdragon X2 Elite: l'architettura del SoC per i notebook del 2026
In occasione del proprio Architecture Deep Dive 2025 Qualcomm ha mostrato in dettaglio l'architettura della propria prossima generazione di SoC destinati ai notebook Windows for ARM di prossima generazione. Snapdragon X2 Elite si candida, con sistemi in commercio nella prima metà del 2026, a portare nuove soluzioni nel mondo dei notebook sottili con grande autonomia
Recensione DJI Mini 5 Pro: il drone C0 ultra-leggero con sensore da 1 pollice
Recensione DJI Mini 5 Pro: il drone C0 ultra-leggero con sensore da 1 pollice
DJI Mini 5 Pro porta nella serie Mini il primo sensore CMOS da 1 pollice, unendo qualità d'immagine professionale alla portabilità estrema tipica di tutti i prodotti della famiglia. È un drone C0, quindi in un peso estremamente contenuto e che non richiede patentino, propone un gimbal rotabile a 225 gradi, rilevamento ostacoli anche notturno e autonomia fino a 36 minuti. Caratteristiche che rendono il nuovo drone un riferimento per creator e appassionati
Tutti gli articoli Tutte le news

Vai al Forum
Rispondi
 
Strumenti
Old 26-07-2007, 13:54   #1
carosene
Member
 
Iscritto dal: Jan 2004
Messaggi: 173
[Java] pattern Model-View-Controller e Swing

Sto provando a mettere in pratica il pattern Model-View-Controller in un'applicazione basata su Swing. Il dilemma è questo:
Come faccio in pratica a notificare alla View qualsiasi modifica al Model?
Più semplicemente:
Esiste una tecnica consolidata per aggiornare tutti i componenti di una gui che visualizzano un dato, quando quest'ultimo viene aggiornato?
carosene è offline   Rispondi citando il messaggio o parte di esso
Old 26-07-2007, 15:06   #2
mad_hhatter
Senior Member
 
L'Avatar di mad_hhatter
 
Iscritto dal: Oct 2006
Messaggi: 1105
Quote:
Originariamente inviato da carosene Guarda i messaggi
Sto provando a mettere in pratica il pattern Model-View-Controller in un'applicazione basata su Swing. Il dilemma è questo:
Come faccio in pratica a notificare alla View qualsiasi modifica al Model?
Più semplicemente:
Esiste una tecnica consolidata per aggiornare tutti i componenti di una gui che visualizzano un dato, quando quest'ultimo viene aggiornato?
certo, applichi il pattern "observer"
mad_hhatter è offline   Rispondi citando il messaggio o parte di esso
Old 26-07-2007, 15:25   #3
PGI-Bis
Senior Member
 
L'Avatar di PGI-Bis
 
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
MVC è una sigla parziale. Il pattern MVC è in verità MNVC, dove N sta per Notifiable. La N è quello che permette al modello di comunicare con le viste senza che le viste possiedano un riferimento al modello.

Riassumento in due righe pseudo-Javesche, lo schema è:

Model:
+addNotifiable(Notifiable n);

Notifiable:
+qualcosaNotify(...dati notificati)

View implements Notifiable, usa Controller

Controller usa Model

Quando il modello subisce una mutazione ad opera del controllo altro non fa che notificare la mutazione agli oggetti registrati come candidati alle notifiche (da cui il nome Notifiable). La vista o è un Notifiable o usa un Notifiable, in ogni caso è indirettamente collegata al modello.
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me!
PGI-Bis è offline   Rispondi citando il messaggio o parte di esso
Old 26-07-2007, 16:40   #4
carosene
Member
 
Iscritto dal: Jan 2004
Messaggi: 173
Molte grazie per le risposte.

Ho scartato il modello "observer" perchè impone che l'oggetto osservato estenda Observable. Tutto questo mi limiterebbe nel creare una mia gerarchia di classi.

PGI-Bis è molto interessante quello che mi hai scritto. Potresti farmi un esempio pratico su come implementare il tutto?
carosene è offline   Rispondi citando il messaggio o parte di esso
Old 26-07-2007, 17:06   #5
mad_hhatter
Senior Member
 
L'Avatar di mad_hhatter
 
Iscritto dal: Oct 2006
Messaggi: 1105
Quote:
Originariamente inviato da carosene Guarda i messaggi
Molte grazie per le risposte.

Ho scartato il modello "observer" perchè impone che l'oggetto osservato estenda Observable. Tutto questo mi limiterebbe nel creare una mia gerarchia di classi.

PGI-Bis è molto interessante quello che mi hai scritto. Potresti farmi un esempio pratico su come implementare il tutto?
in realtà non è necessario che estenda Observable (che a me non piace)... basta che ti fai una semplicissima interface Observable con i metodi addObserver, removeObserver e notifyObservers e un'interface Observer con un metodo update per ricevere le notifiche... così puoi crearti la tua gerarchia senza problemi

inoltre quanto detto da PGI-bis credo vada proprio in quella direzione: quello che lui chiama Notifiable è il mio Observer, mentre il Model è l'observable
mad_hhatter è offline   Rispondi citando il messaggio o parte di esso
Old 26-07-2007, 19:18   #6
PGI-Bis
Senior Member
 
L'Avatar di PGI-Bis
 
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
Interessante per modo di dire. L'MVC sa un po' di stantìo .

Supponiamo che i dati contenuti nel modello siano... una stringa. Chi volesse ricevere una notifica sull'intervenuta mutazione dei dati del modello potrebbe semplicemente dire d'essere un:

Codice:
public interface ModelNotifiable {

	void dataChangeNotify(String value);
}
Ecco, l'MVC è bell'e che finito.

Il modello è una cosa che ha una stringa e un registro di oggetti "ModelNotifiable". Quando la stringa cambia, il modello piglia e invoca il metodo dataChangeNotify di ogni ModelNotifiable registrato. Per farlo basta una lista.

Codice:
import java.util.*;

public class Model {
	private LinkedList<ModelNotifiable> notifiables = new LinkedList<ModelNotifiable>();
	private String data;
	
	public void addNotifiable(ModelNotifiable n) {
		notifiables.add(n);
	}
	
	public void setData(String value) {
		this.data = value;
		notifyDataChange();
	}
	
	private void notifyDataChange() {
		for(int i = 0; i < notifiables.size(); i++) {
			notifiables.get(i).dataChangeNotify(data);
		}
	}
}
Qui che si fa. Si fa:

Model model = new Model();
model.addNotifiable(la vista);

e fine della storia: a questo punto ogni volta che il modello rileva una mutazione del suo dato, spara un dataChangeNotify, la vista lo riceve e aggiorna la presentazione dei dati. Nulla di trascendentale.

Una vista degna di cotanto modello potrebbe essere:

Codice:
import java.awt.*;
import javax.swing.*;

public class FakeView implements ModelNotifiable {
	private JFrame window = new JFrame("FakeView Frame");
	private JLabel dataLabel = new JLabel("", JLabel.CENTER);
	
	public FakeView() {
		window.add(new JLabel("Valore", JLabel.CENTER), BorderLayout.NORTH);
		window.add(dataLabel, BorderLayout.CENTER);
		window.setPreferredSize(new Dimension(300, 200));
		window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}
	
	public void show() {
		EventQueue.invokeLater(new Runnable() { public void run() {
			window.pack();
			window.setLocationRelativeTo(null);
			window.setVisible(true);
		}});
	}

	public void dataChangeNotify(final String value) {
		EventQueue.invokeLater(new Runnable() { public void run() {
			dataLabel.setText(value);
		}});
	}
}
Una finestra con due etichette. Come noti FakeView è un ModelNotifiable. E' il fatto di essere un ModelNotifiable (o di possedere un ModelNotifiable, ma lo MVC "classico" vuole che la vista sia un notificabile) che consente alla vista di presentare dei dati senza avere cognizione del luogo da cui provengono.

Manca il controller. Originariamente (MVC nasce nel campo delle interfacce grafiche con il proposito di separare la presentazione dei dati dal dispositivo di input usato dall'utente) il controllo era un ponte tra l'utente ed il modello.

Ad esempio:

Codice:
public class ConsoleController {
	private Model model;

	public ConsoleController(Model model) {
		this.model = model;
	}
	
	public void start() {
		java.io.Console console = System.console();
		console.printf("Benvenuto nel 1967!%n");
		console.printf("Inserisci una stringa e premi invio%n");
		console.printf("La stringa quit chiude il programma%n");
		String line;
		while(!(line = console.readLine()).equals("quit")) {
			model.setData(line);
		}
		console.printf("Fine dell'interazione%n");
	}
}
Oggi è ancora un ponte tra l'utente ed il modello ma in un modo diverso. Per Controller si intende spesso il componente che si occupa di applicare la logica del programma all'input utente, dove l'input viene catturato dalla vista.

Bisogna stare attenti perchè le due interpretazioni sembrano simili ma non lo sono.

Un esempio di controller per Modello, che usa la console come periferica di input (ai tempi andati il controller avrebbe interagito direttamente con la tastiera), è:

Codice:
public class ConsoleController {
	public void link(Model model) {
		java.io.Console console = System.console();
		console.printf("Benvenuto nel 1967!%n");
		console.printf("Inserisci una stringa e premi invio%n");
		console.printf("La stringa quit chiude il programma%n");
		String line;
		while(!(line = console.readLine()).equals("quit")) {
			model.setData(line);
		}
		console.printf("Fine dell'interazione%n");
	}
}
Il punto d'entrata dell'applicazione MVC mette insieme i tre pezzi. Crea un modello, crea una vista, registra la vista come ricevitore di notifiche dal modello, crea il controllo. Quando il controllo è collegato al modello, l'utente può iniziare ad interagire con l'applicazione.

Codice:
public class Main {

	public static void main(String[] args) {
		Model model = new Model();
		FakeView view = new FakeView();
		model.addNotifiable(view);
		view.show();
		ConsoleController controller = new ConsoleController();
		controller.link(model);
	}
}
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me!
PGI-Bis è offline   Rispondi citando il messaggio o parte di esso
Old 26-07-2007, 23:51   #7
carosene
Member
 
Iscritto dal: Jan 2004
Messaggi: 173
PGI-Bis sei stato chiarissimo e gentilissimo.
Grazie di cuore…
carosene è offline   Rispondi citando il messaggio o parte di esso
Old 06-08-2007, 18:31   #8
carosene
Member
 
Iscritto dal: Jan 2004
Messaggi: 173
Sto provando a mettere in pratica il tutto, per realizzare un programma che accede ad un database, visualizza i dati in diverse Jtable, in modo che possano essere modificati.
Per realizzare tutto questo ho creato tre package: Model, View e Controller.
  • Nel primo ho inserito tutte le classi che rappresentano un dato.
  • Nel secondo tutte le classi che si occupano di visualizzare i dati all'utente.
  • Nel terzo una classe che colleghi i primi due strati, e tutte le classi che incapsulano un'interazione con l'utente.
I dubbi sono questi:
Dove vanno inseriti i renderers delle celle?
Chiedo questo perché sono componenti grafici, ma comunque specifici di un modello. Di conseguenza mi riesce difficile immaginare un modo per separarli completamente.
Dove vanno inseriti gli editor di cella?
Al loro interno incapsulano un Component, ma al tempo stesso devono funzionare da controller, perché non tutti i dati inseriti dall'utente possono essere accettati.
Dove bisogna controllare l'input dell'utente?
Nel modello o nel controller?
Come gestire le modifiche dei dati?
In alcune circostanze, potrebbe essere necessario che per accettare una modifica di un determinato dato, ci debba essere una determinata condizione. Dove gestire il tutto: nel modello o nel controller?

Sto pensando a tutto questo perché immagino a come possa essere convertito un programma standalone in “altro”. Questo comporterebbe il rifacimento di tutto il controller e di tutte le viste. Giusto?
carosene è offline   Rispondi citando il messaggio o parte di esso
Old 06-08-2007, 21:57   #9
PGI-Bis
Senior Member
 
L'Avatar di PGI-Bis
 
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
L'input utente è gestito dal controller. Intendo per input l'interazione dell'utente e non la validità delle informazioni immesse dall'utente.

La verifica dell'input è gestita dal modello o dal controllo. Dal modello se la validità dell'immissione dipende da un valore noto al modello. Altrimenti deve essere gestita dal controllo. Tale verifica assume le vesti di una convalida a posteriori solo nel caso di gestione da parte del modello. Nel caso in cui essa sia gestita dal controllo (in quanto non dipendente da uno stato del modello), la verifica è una semplice formattazione dell'input.

Due esempi astratti.

1. Verifica da parte del modello.

Il modello contiene delle chiavi a cui possono essere associati dei valori. Un valore può essere inserito solo se esiste una chiave a cui associare quel valore. L'utente inserisce coppie chiave (esistente) valore (nuovo). Chi controlla che la chiave esista prima di inserire il valore? Il modello. Lo fa il modello perchè la validità dell'input dipende da uno stato del modello (la presenza di una certa chiave).

2. Verifica da parte del controllo.

Il modello contiene numeri interi maggiori di 35. L'utente inserisce 30. Chi controlla che il numero sia maggiore di 35? Il controllo, perchè la validità dell'input non dipende da uno stato del modello. In questo caso il controllo opera come semplice "formattatore" dell'input. E' come se il modello richiedesse una sequenza di caratteri ed il controllo dovesse produrla a partire da una tastiera virtuale gestita col mouse. Il controllo si occupa di ricondurre una varietà di input ad un insieme predefinito di valori ciò che può essere fatto dal controllo in autonomia se e solo se i "limiti" di quell'insieme siano noti a priori. E' chiaro che questo può accadere solo se quei limiti non siano variabili. Nel caso in cui siano variabili, quella variabilità, in quanto informazione, sarà gestita dal modello.
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me!
PGI-Bis è offline   Rispondi citando il messaggio o parte di esso
Old 07-08-2007, 09:00   #10
Nous
Senior Member
 
Iscritto dal: Oct 2002
Città: Como
Messaggi: 708
Quote:
Originariamente inviato da PGI-Bis Guarda i messaggi
La verifica dell'input è gestita dal modello o dal controllo. Dal modello se la validità dell'immissione dipende da un valore noto al modello. Altrimenti deve essere gestita dal controllo.
In altre parole, applica il pattern Expert e risolvi tutti i tuoi dubbi...chi deve fare un'operazione? L'esperto per il problema che l'operazione risolve
__________________
Cristian ,il nOUS che invoglia
i5-2500 (Sandy Bridge) Quad-Core 3,30 Ghz - Asus P8Z68-V PRO / GEN3 - 2x4GB DDR3 - GeForce GTX 550 Ti Pci-E 4 Gb ddr3 - Barracuda 7200.12 1 Tb Sata 600 Buffer 32 Mb 7200 Rpm
Nous è offline   Rispondi citando il messaggio o parte di esso
Old 07-08-2007, 11:36   #11
pierosa
Member
 
Iscritto dal: Jan 2007
Messaggi: 189
Ti propongo un esmpio semplice di un pattern molto simile al MVC, il pattern Model-View-Presenter(MVP).
In questo pattern Model e View sono gli stessi del MVC e il Controller è chiamto Presenter e si occupa anche di aggirnare la view.
Ci sono 2 varianti quella che ti presento è la Passive View.
Supponiamo di avere un form con 1 campi di testo dove puoi inserire un nome e cliccado su un pulsante esegui una ricerca in una rubrica telefonica, visualizzando il numero di telefono in una label.
Non uso java da troppo tempo per cui l'esempio sarà in pseudocodice simile a java.
Il Model è molto semplice
Codice:
public class Model{
  private String name;
  private String number;
  
  public void SetName(String name){
    this.name = name;
  }
  
  public String getName(){
    return this.name;
  }
  // set e get per number
}
LA view implementa una interfaccia che stabilisce un contratto tra la stessa view e il presenter. Questo ti permette di cambiare view a patto che questa implementi l'interfaccia richiesta
Codice:
public interface ISearchView {
  public void setNumber(String number);
  public void displayError(String error);
}

public class SearchView implements ISearchView {
  private SearchPresenter presenter;
  private JTextField  = new JTextField();
  private JLabel numberLabel = new Jlabel();
  private JLabel errorLabel = new Jlabel();
  private JButton searchButton = new Jbutton();
    
  public SearchView(){
    // ogni view crea un presenter e si inietta nello stesso
    presenter = = new SearchPresenter(this);
  }
  
  public void setNumber(String number){
    numberLabel.setText(number);
  }

  public void displayError(String error){
    errorLabel.setText(error);
  }
  
  public void buttonClick(){
    // al click del bottone la view richiama il metodo search del presenter
    // che si occupa di validare l'input e effettuare le operazioni richieste
    presenter.search(nameTextField.getText());
  }
}
come vedi la view conosce il presenter, nel costruttore crea un nuovo presenter e si inietta nello stesso.

Il presenter non conosce direttamente la view (intesa come implementazione specifica di una view) ma conosce l'interfaccia che essa implementa. Per cui può agire sulla stessa richiedendo delle oprazioni, il modo in cui le operazioni sarranno implementate dipende esclusivamente dalla view. Se devo mostrare un messaggio di errore il presenter esegue la richiesta, ma sarà la view a decidere come visualizzare l'errore (per esempio può visualizzare un testo in una label, oppure inserire un * vicino al campo non validato).
Codice:
public class SearchPresenter{
  private ISearchView view;
  // supponiamo che ModelDao sia una classe che che effettua operazioni su database
  ModelDao dao; 
  Model model;

  public SearchPresenter(ISearchView view){
    this.view = view;
  }
  
  public void search(String name){
    // questo metodo vaiilda l'input 
    // esegue le operazioni di ricerca e aggiorna la view
    // altrimenti notifica alla view di visualizzare un errore
    if (controllo se name è valido){
      model = dao.search(name);
      view.setNumber(model.getNumber());
    } else 
      view.displayError("Inserisci un nome");
  }
}
e poi il main è semplice
Codice:
public class Main {
	public static void main(String[] args) {
		SearchView view = new SearchView();
                view.Show();
	}
}
Ciao
pierosa è offline   Rispondi citando il messaggio o parte di esso
Old 07-08-2007, 17:00   #12
carosene
Member
 
Iscritto dal: Jan 2004
Messaggi: 173
Grazie per i vostri suggerimenti.
Ho tuttavia i seguenti dubbi:
  • Se nel modello si dovesse determinare che l'input è errato, si applica il pattern Observer per avvisare l'utente?
  • Nel pattern MVP, avere l'esigenza dello stesso Presenter in due componenti differenti della gui. È da considerare un errore di design dell'intero applicativo?
  • In entrambi i pattern MVP e MVC dove si gestiscono le meccaniche della gui? Ad esempio: solo se un elemento di un elenco è selezionato, bisogna abilitare un pulsante.
carosene è offline   Rispondi citando il messaggio o parte di esso
Old 07-08-2007, 17:32   #13
PGI-Bis
Senior Member
 
L'Avatar di PGI-Bis
 
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
Le meccaniche della gui si gestiscono nel modello.

La vista fa vedere e stop.

Il pulsante è attivo solo se un elemento della lista è selezionato: significa che nel modello c'è un'informazione "elementoSelezionato" e un'informazione "stato del pulsante", che la mutazione del valore "elementoSelezionato" causa una mutazione del valore "stato del pulsante". Queste mutazioni sono comunicate alla vista tramite Notifiable e la vista aggiorna il suo aspetto in conseguenza della notifica ricevuta.
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me!
PGI-Bis è offline   Rispondi citando il messaggio o parte di esso
Old 07-08-2007, 17:57   #14
pierosa
Member
 
Iscritto dal: Jan 2007
Messaggi: 189
Nel Passive view tutte le dinamiche della view sono gestite dal presenter (la vista è passiva, come dal nome)
all'evento della selezione della lista richiami il presenter notificandogli l'evento e di conseguenza il presenter richiederà l'aggiornamento della view attivando il bottone.
Quote:
Nel pattern MVP, avere l'esigenza dello stesso Presenter in due componenti differenti della gui. È da considerare un errore di design dell'intero applicativo?
non ho ben capito cosa intendi
pierosa è offline   Rispondi citando il messaggio o parte di esso
Old 10-08-2007, 18:00   #15
carosene
Member
 
Iscritto dal: Jan 2004
Messaggi: 173
Scusatemi per il ritardo con il quale sto rispondendo.
Ho cercato di mettere in pratica il tutto, creando una semplice rubrica con il pattern MVP. Il programma non è di alcuna utilità, mi è servito solo per esercitarmi. Tecnicamente consente di aggiungere o rimuovere un contatto ad una collection, attraverso una JTable.
Mi piacerebbe molto avere qualsiasi vostro commento, perchè non sono un professionista o uno studente, ma un semplice hobbysta.

Quote:
Originariamente inviato da pierosa Guarda i messaggi

non ho ben capito cosa intendi
Volevo chiedere: Nel caso in cui un presenter dovesse gestire più di una finestra, non sarebbe più possibile crearlo nel costruttore della finestra. Come fare?
Allegati
File Type: zip MVP.zip (6.1 KB, 9 visite)
carosene è offline   Rispondi citando il messaggio o parte di esso
 Rispondi


Polestar 3 Performance, test drive: comodità e potenza possono convivere Polestar 3 Performance, test drive: comodit&agra...
Qualcomm Snapdragon X2 Elite: l'architettura del SoC per i notebook del 2026 Qualcomm Snapdragon X2 Elite: l'architettura del...
Recensione DJI Mini 5 Pro: il drone C0 ultra-leggero con sensore da 1 pollice Recensione DJI Mini 5 Pro: il drone C0 ultra-leg...
ASUS Expertbook PM3: il notebook robusto per le aziende ASUS Expertbook PM3: il notebook robusto per le ...
Test ride con Gowow Ori: elettrico e off-road vanno incredibilmente d'accordo Test ride con Gowow Ori: elettrico e off-road va...
ESA: rilevati 40 mila asteroidi vicino a...
La batteria salva fabbriche di EQORE ott...
SpaceX Starship: iniziati i test della t...
Datacenter IA nello spazio entro 5 anni,...
Telescopio spaziale James Webb: rilevato...
Ericsson Mobility Report: nel 2025 il 5G...
PLAI DEMO DAY: si chiude il secondo cicl...
Google rilascia Nano Banana Pro: il nuov...
ChatGPT si rinnova ancora: disponibile l...
Ring lancia super sconti di Black Friday...
Black Friday 2025: 450 euro di sconto su...
Tutte le offerte Blink in un unico posto...
OpenAI e Foxconn uniscono le forze per r...
Ricarica delle auto elettriche in 3 minu...
Lucid presenta Gravity Touring, il SUV e...
Chromium
GPU-Z
OCCT
LibreOffice Portable
Opera One Portable
Opera One 106
CCleaner Portable
CCleaner Standard
Cpu-Z
Driver NVIDIA GeForce 546.65 WHQL
SmartFTP
Trillian
Google Chrome Portable
Google Chrome 120
VirtualBox
Tutti gli articoli Tutte le news Tutti i download

Strumenti

Regole
Non Puoi aprire nuove discussioni
Non Puoi rispondere ai messaggi
Non Puoi allegare file
Non Puoi modificare i tuoi messaggi

Il codice vB è On
Le Faccine sono On
Il codice [IMG] è On
Il codice HTML è Off
Vai al Forum


Tutti gli orari sono GMT +1. Ora sono le: 20:20.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Served by www3v