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){
}
}
}