Visualizzazione dei risultati da 1 a 5 su 5
  1. #1
    Utente di HTML.it
    Registrato dal
    Oct 2011
    Messaggi
    3

    GUI per Client/Server trasferimento immagini

    Per prima cosa non abbiate paura di quando è lunga la spiegazione : è così lunga perché voglio essere chiaro e spero di esserlo. Seconda cosa: vi ringrazio già se solo leggete e se mi date una mano vi ringrazio ancora di più

    Comunque, passiamo alla spiegazione di cosa sto cercando di fare, come lo sto facendo e quali sono i problemi che ho nel farlo:
    sto scrivendo un programma Client che deve semplicemente richiedere ad un server un'immagine che, ad esempio, è relativa ad una strada di una città.
    Il Server viene solo simulato e non devo svilupparlo, quindi una volta che il Client si connette, il Server permette semplicemente di inviare una qualsiasi immagine che abbiamo sul pc.
    Funziona tutto bene, ma da quando sto provando ad inserire un'interfaccia grafica per il Client le cose si sono un po' complicate.

    Il Client che ho scritto ha un'interfaccia semplice formata da due JPanel:

    -Uno con questi pulsanti : "Lista Strade", che invia al server la richiesta di una lista delle strade monitorate (lista fittizia in quanto il Server è simulato e non monitora un cavolo), una casella di testo in modo da poter scrivere direttamente la strada di cui vogliamo l'immagine (Ad esempio "via numero x"), un pulsante "OK" per inviare il contenuto della casella di testo;

    -L'altro JPanel è “addetto” alla visualizzazione della lista con relativo pulsante per inviare l'elemento scelto e per visualizzare l'immagine una volta inviata la richiesta in conseguenza alla scelta dalla lista.

    Il programma, attualmente, funziona in questo modo:
    Premendo "Lista strade", il server mi invia un array di stringhe con le possibili scelte che il Client può effettuare.
    Problema N°1: Non riesco a far visualizzare l'oggetto List nel JPanel se non dopo aver cambiato la dimensione della finestra e non so come mettere lo scroll nel caso la lista sia troppo lunga.

    Comunque, una volta fatta comparire la lista con questo escamotage riesco a fare la scelta e ad inviarla al server che risponde con l'immagine.
    Problema N°2: Una volta visualizzata l'immagine (che adatto alle dimensioni attuali del JPanel), se cambio la dimensione della finestra la sua dimensione non viene aggiornata. In realtà vorrei visualizzare l'immagine o in modo che rientri nella finestra ridimensionata in modo che rispetti le proporzioni, oppure che venga visualizzata nelle dimensioni originali ma aggiungendo, quindi, degli eventuali scroll al JPanel. Preferirei sviluppare la prima opzione.

    Il secondo modo per richiedere un immagine al Server è la “scelta diretta”, ovvero scrivere il nome della via di cui vogliamo l'immagine nella casella di testo ed inviare la richiesta al Server e qui mi funziona benissimo, il problema in questo caso è uguale al “Problema N°2” che ho descritto sopra.

    Spero possiate darmi una mano...di seguito inserisco il codice completo anche del Server in modo che possiate provare il codice. Il codice del Server l'ho trovato su internet e l'ho modificato un po' secondo esigenza, mentre per il Client mi sono visto vari esempi e sto cercando di “attaccargli la grafica”.

    CLIENT:
    codice:
    import java.awt.*;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.io.*;
    import java.net.Socket;
    
    import javax.swing.*;
    
    public class Client extends JFrame{
    	private static final long serialVersionUID = 1L;
    	Pannello panel;
    	Socket socket;
    	ObjectOutputStream out;
    	ObjectInputStream in;
    	
    	BufferedReader is;
    	PrintStream os;
    	String message;
    	String[] list;
    	ButtonPanel bPanel;
    	List strade;
    	JButton OK;
    	
    	public Client(){
    		super("Client"); //chiama il costruttore di JFrame
    		Container c = getContentPane(); //inizializzo il contenitore
    		panel=new Pannello();
    		c.add(panel, BorderLayout.CENTER); //aggiungo il pannello al contenitore
    		bPanel = new ButtonPanel();
    		c.add(bPanel, BorderLayout.SOUTH);
    		setSize(700,600); //grandezza JFrame
    		setVisible(true);
    	}
    	
    	public void connessione(){
    		try{
    			socket = new Socket("localhost", 4000); // open a socket connection
    			// Apre i canali I/O
    			is = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    			os = new PrintStream(socket.getOutputStream(), true);
    			bPanel.aggiungi(this);
    		}catch(IOException e){
    		}
    	}
    	
    	public void richiediLista() throws NumberFormatException, IOException{
    		// Scrive al server
    		message="Lista"; //provo con "Lista" e poi con "via numero n"
    		os.println(message); //scrive la stringa sul socket
    		os.flush(); //svuota il buffer
    		
    		int i=Integer.parseInt(is.readLine());
    		list = new String[i];
    		strade = new List(i, false);
    		for(int j=0; j<i; j++){
    			list[j]=is.readLine();
    			System.out.println(list[j]);
    			strade.add(list[j]);
    		}
    		panel.add(strade);
    		OK = new JButton("OK");
    		panel.add(OK);
    		panel.repaint();
    		OK.addActionListener(new ActionListener(){
    			public void actionPerformed(ActionEvent event){
    				String scelta = strade.getSelectedItem();
    				try {
    					panel.remove(OK);
    					panel.remove(strade);
    					inviaScelta(scelta);
    				} catch (NumberFormatException e) {
    					// TODO Auto-generated catch block
    					e.printStackTrace();
    				} catch (IOException e) {
    					// TODO Auto-generated catch block
    					e.printStackTrace();
    				}
    			}
    		});
    		//Random rnd = new Random();
    		//message="via numero "+rnd.nextInt(9); //sceglie una stringa a caso
    		//inviaScelta(message);
    	}
    	
    	public void inviaScelta(String casella) throws NumberFormatException, IOException{		
    		os.println(casella); //scrive la stringa sul socket
    		os.flush(); //svuota il buffer
    		ricezioneImg1();
    }
    	
    	public void ricezioneImg1() throws IOException{
    		in = new ObjectInputStream(socket.getInputStream());
    		ricezioneImg2(); //chiama ricezioneImg2()	
    		}
    	
    	public void ricezioneImg2() throws IOException{
    		try{
    			while(true){
    				ImageIcon img = (ImageIcon) in.readObject(); //legge l'oggetto in input
    				Image sfondo = img.getImage();
    				sfondo = sfondo.getScaledInstance(panel.getWidth(), panel.getHeight(),
    						getDefaultCloseOperation());
    				ricezioneImg3(sfondo); //chiama scrivi su img
    			}	
    		}
    		catch(ClassNotFoundException e){
    		}	
    	}
    	
    	public void ricezioneImg3(final Image img){
    		//se più thread devono interagire su più componenti Swing anche se non sono condivisi,
    		//bisogna usare il metodo invokeLater per evitare eventuali problemi di gestione
    		SwingUtilities.invokeLater(new Runnable(){
    									public void run(){
    										panel.repaint(img);}});	
    	}	
    	
    	public static void main(String[] args){
    		Client cl = new Client();
    		cl.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    		cl.connessione();
    	}
    }
    
    
    class Pannello extends JPanel{
    	private static final long serialVersionUID = 8962525133515846829L;
    	Image img=null ;
    	
    	public Pannello(){
    		setBackground(Color.BLACK);
    	}
    	
    	public void paintComponent(Graphics g){
    		super.paintComponent(g);
    		if(img!=null)
    			g.drawImage(img, getX(), getY(), this);	
    	}	
    	
    	public void repaint(Image img){
    		this.img=img;
    		img = img.getScaledInstance(getWidth(), getHeight(), java.awt.Image.SCALE_SMOOTH);
    		repaint();
    	}
    }
    
    
    class ButtonPanel extends JPanel{
    	private static final long serialVersionUID = 1L;
    	JTextField via;
    	JButton ok;
    	JButton lista;
    	
    	public ButtonPanel(){
    		//crea i pulsanti
    		lista = new JButton("Lista Strade");
    		add(lista);
    		via = new JTextField("via numero ", 15);
    		add(via);
    		ok = new JButton("OK");
    		add(ok);
    	}
    	
    	public void aggiungi(final Client cl){
    		lista.addActionListener(new 
    				ActionListener(){
    			public void actionPerformed(ActionEvent event){
    				try {
    					cl.richiediLista();
    				} catch (NumberFormatException e) {
    					// TODO Auto-generated catch block
    					e.printStackTrace();
    				} catch (IOException e) {
    					// TODO Auto-generated catch block
    					e.printStackTrace();
    				}
    			}
    		});
    		
    		
    		ok.addActionListener(new 
    				ActionListener(){
    			public void actionPerformed(ActionEvent event){
    				String casella = via.getText();
    				try {
    					cl.inviaScelta(casella);
    				} catch (NumberFormatException e) {
    					// TODO Auto-generated catch block
    					e.printStackTrace();
    				} catch (IOException e) {
    					// TODO Auto-generated catch block
    					e.printStackTrace();
    				}
    			}
    		});
    	}
    }

    SERVER:
    codice:
    import java.io.*;
    import java.net.*;
    
    import javax.swing.ImageIcon;
    import javax.swing.JFileChooser;
    import javax.swing.JFrame;
     
    public class PrototipoServer extends Thread{
    	private ServerSocket listensk; //socket in ascolto
    	String[] list = new String[10];
    	
    	public static void main(String argv[]) throws Exception{
    		new PrototipoServer(); //crea un oggetto Server
    	}
    	
    	public PrototipoServer() throws Exception{
    		for(int i=0; i<10; i++)
    			list[i] = "via numero "+i;
    		listensk = new ServerSocket(4000);
    		System.out.println("Il Server è in attesa sulla porta 4000.");
    		this.start(); //fa partire il metodo run della classe Server
    	}
    	
    	public void run(){
    		while(true){
    			try{
    				System.out.println("In attesa di Connessione.");
    				Socket client = listensk.accept();
    				System.out.println("Connessione accettata da: "+client.getInetAddress());
    				new Connect(client, list); //crea un oggetto Connect (classe interna)
    			}
    			catch(Exception e){
    			}//fine try/catch
    		} //fine while
    	} //fine metodo run
    } //fine classe Server
    
    class Connect extends JFrame{
    	private static final long serialVersionUID = 1L;
    	private Socket client = null;
    	BufferedReader in = null;
    	PrintStream out = null;
    	String message = null;
    	String[] list;
    	
    	public Connect(){}
    	
    	public Connect(Socket clientSocket, String[] list){
    		this.list = list;
    		client = clientSocket;
    		try{
    			in = new BufferedReader(new InputStreamReader(client.getInputStream()));
    			out = new PrintStream(client.getOutputStream(), true);	
    		}catch(Exception e1){
    			try{
    				client.close();	
    			}catch(Exception e){
    				System.out.println(e.getMessage());	
    			}//fine try/catch interno
    			return;	
    		} //fine try/catch esterno
    		this.run(); //fa partire il metodo run della classe Connect
    	} //fine costruttore Connect
    	
    	public void run(){
    		try{
    			while(true){
    				// Legge dal client
    				message = in.readLine();
    				if(message.equals("Lista")){ //invia l'array di stringhe list
    					out.println(list.length); //scrive il numero di elementi da ricevere
    					out.flush(); //svuota il buffer
    					for(int i=0; i<list.length; i++){
    						out.println(list[i]); //scrive gli elementi al client
    						out.flush(); //svuota il buffer
    					}
    				}
    				else{ //invia l'immagine di "via esempio" se esiste
    					int i;
    					for(i=0; i<list.length; i++){
    						if(message.equals(list[i])){
    							// Strada trovata
    							break;
    						}
    					}
    					if(i==list.length){ //invio errore
    						out.println("Errore: strada non presente."); //scrive la stringa sul socket
    						out.flush(); //svuota il buffer	
    					}
    					else{ //invio l'immagine
    						try{
    							ObjectOutputStream out;
    							out = new ObjectOutputStream(client.getOutputStream());
    							out.flush();
    							JFileChooser fc=new JFileChooser(); //permette di scegliere un file
    							fc.setFileSelectionMode(JFileChooser.FILES_ONLY); //permette la selezione di un solo file
    							fc.showOpenDialog(this);
    							File f = fc.getSelectedFile(); //prende il file selezionato
    							out.writeObject( new ImageIcon(""+f) );	//invia l'immagine selezionata
    							out.close();
    						}
    						catch(IOException e){
    						}
    						/**Prima inviavo solo una stringa
    						 * out.println("Immagine di "+list[i]);
    						 * out.flush();*/
    					}
    					break; //una volta trovata la strada o l'errore esce dal while
    				}
    			}
    			
    			// chiude gli stream e le connessioni
    			out.close();
    			in.close();
    			client.close();	
    		}catch(Exception e){
    		}	
    	}
    }

  2. #2
    non ho letto il codice ma ho letto i tuoi problemi.

    il 1 mi pare il classico problemi di layout...in che layout metti la tua lista? usi anche uno JscrollPane sulla lista?

    il 2 problema io ti posso consigliarlo di risolverlo in modo "bizzaro" (magari però non ho campito bene).
    invece di permettere la visualizzazione enllo stesso frame, perchè non apri un nuovo frame e come unico pannello metti la foto? ovviametne devi ridefinire il paint del pannello, ma credo che sia una soluzione veloce e alternativa. se ho failato qualcosa dimmi pure.

  3. #3
    Utente di HTML.it
    Registrato dal
    Oct 2011
    Messaggi
    3
    non ho letto il codice ma ho letto i tuoi problemi. il 1 mi pare il classico problemi di layout...in che layout metti la tua lista? usi anche uno JscrollPane sulla lista? il 2 problema io ti posso consigliarlo di risolverlo in modo "bizzaro" (magari però non ho campito bene). invece di permettere la visualizzazione enllo stesso frame, perchè non apri un nuovo frame e come unico pannello metti la foto? ovviametne devi ridefinire il paint del pannello, ma credo che sia una soluzione veloce e alternativa. se ho failato qualcosa dimmi pure.
    utilizzo queste istruzioni:
    codice:
    super("Client"); //chiama il costruttore di JFrame 		
    Container c = getContentPane(); //inizializzo il contenitore 		
    panel=new Pannello(); 		
    c.add(panel, BorderLayout.CENTER); //aggiungo il pannello al contenitore 		
    bPanel = new ButtonPanel(); 		
    c.add(bPanel, BorderLayout.SOUTH); 		
    setSize(700,600); //grandezza JFrame 		
    setVisible(true);
    In pratica divido il layout dell'oggetto Container in sud e centro e, quindi, aggiungo il pannello con i pulsanti "Lista Strade", la JTextField e il pulsante "OK" relativo alla JTextField a sud dell'oggetto Container e "panel" al centro dell'oggetto Container.
    In "panel" viene visualizzata l'immagine inviata dal server, ma, se premo sul pulsante "Lista Strade", deve venire visualizzato prima un oggetto List con un pulsante "OK".

    Questo è il codice con cui aggiungo l'oggetto List "strade" ed il pulsante "OK" al Pannello "panel":
    codice:
    panel.add(strade);
    OK = new JButton("OK"); 		
    panel.add(OK); 		
    panel.repaint();
    Gli oggetti vengono entrambi aggiunti e funzionano, solo che vengono visualizzati solo se cambio le dimensioni della finestra e, quindi, quando mi fa il refresh del Pannello. Facendo però "panel.repaint()" non dovrebbe visualizzare subito l'oggetto List e il pulsante appena aggiunti??


    Per il secondo problema cencando un po' qua e là ho trovato un modo per visualizzare l'immagine nelle sue dimensioni reali e con uno JScrollPanel la riesco a vedere tutta, però vorrei che l'immagine si adattasse al pannello rispettando le proporzioni. Se la visualizzo in grandezza originale, molte immagini vannò fuori schermo e mi tocca navigare con le barre di scroll che mi sono aggiunto per vedere l'immagine.
    In questo codice riesco a ridurre la dimensione dell'immagine ma non in maniera proporzionata, riesco solamente a renderla delle dimensioni del pannello e, quindi, a seconda delle dimensioni originali, l'immagine verrà visualizzata schiacciata o allungata rispetto all'origine.

    Detto questo non dimentico di ringraziarti per la risposta: grazie mille!!!

  4. #4
    Utente di HTML.it
    Registrato dal
    Oct 2011
    Messaggi
    3
    Ho risolto, in parte, i miei problemi. Appena riesco a risolvere tutto faccio sapere. Ora il problema è organizzare meglio il layout facendo comparire l'oggetto List più grande perché quando lo aggiungo al JPanel esce un rettangolo abbastanza piccolo. Prima il problema era dello scroll, ma mi sono accorto che, se necessario, si aggiunge in automatico. Mentre le immagini le ho ridimensionate secondo uno standard in modo che siano sempre proporzionate.
    I metodi per organizzare il layout che conosco abbastanza bene sono l'utilizzo di BorderLayout e di GridLayout, ma non riesco solo con questi ad organizzare il layout come vorrei. C'è qualcuno che mi può dare una mano?

  5. #5
    scrivi che vediamo come possiamo aiutarti

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.