Visualizzazione dei risultati da 1 a 10 su 10
  1. #1

    [Java and C] Sviluppare una GUI e realizzare comunicazione

    Ciao a tutti

    Ho sviluppato una piccola applicazione C che, presi in input dei dati dall'utente tramite banali chiamate ad scanf() (alcuni numeri reali ed una stringa), elabora tali dati e produce dell'output a video tramite chiamate a printf().

    Ora, mi sono stati richiesti due diversi sviluppi da apportare alla mia applicazione:

    1) fornire una GUI a tale applicazione (richiesta espressamente in Java) per l'inserimento dei dati e per la visualizzazione dell'input: si badi bene, NON riscrivere in Java tutto il programma, ma fornire un interfaccia Java al programma C;

    2) rendere possibile l'utilizzo dell'applicazione direttamente da una pagina web: praticamente, dividerla in una parte client (l'interfaccia) caricabile in una pagina web, ed una parte server (la parte che esegue l'elaborazione).

    Ora, mentre in C ho una certa esperienza, di Java sono quasi a digiuno (sulle GUI totalmente a digiuno...) pertanto vorrei chiedervi inizialmente qualcosa di generico, del tipo:
    secondo voi è fattibile?
    come impostereste il lavoro?
    per essere caricata in una pagina web deve necessariamente trattarsi di un applet?
    può comunicare con la parte in C?
    quali librerie usare (ho letto sia di awt che di swing...)?

    Una volta intrapresa una strada, poi probabilmente avrò altre domande da porre....

    Grazie a tutti comunque

  2. #2
    Utente di HTML.it
    Registrato dal
    Apr 2007
    Messaggi
    906
    Per il punto uno, non e' troppo complicato. C'e' la via performante, ma noiosa (quella di usare JNI) o una immediata che per operazioni semplici come la tua va benissimo. Consiste nel creare un processo esterno (il tuo eseguibile scritto in c) e prendere gli stream di I/O di questo per eseguire operazioni di lettura scrittura. La parte java d'esempio e' in grassetto. Il resto mi serviva per costruire la grafica del pannello. Per la grafica, usa swing. Ricorda che swing si basa su awt, e per usare bene il primo, sarebbe consigliato conoscere bene il secondo.
    Se vuoi provare l'esempio, fatti una classe main in java, crea un JFrame e aggiungici una istanza della classe TalkWithC. Compila il file c e mettilo nella stessa directory del class.
    codice:
    ***********PROGRAMMA C*********
    #include <stdio.h>
    
    main ()
    {
       char stringa[100];
       scanf("%s", stringa);
       printf("Hello %s", stringa);
    }
    
    ********PROGRAMMA JAVA*********
    import java.awt.BorderLayout;
    import java.awt.event.*;
    import java.io.*;
    import javax.swing.*;
    
    public class TalkWithC extends JPanel implements ActionListener {
        private JTextField testo;
        private JButton bottone;
        private JTextArea output;
        private JPanel up;
        
        /** Creates a new instance of TalkWithC */
        public TalkWithC() {
            super();
            this.setLayout(new BorderLayout());
            up = new JPanel();
            testo = new JTextField(10);
            bottone = new JButton("Test");
            bottone.addActionListener(this);
            output = new JTextArea("Output: \n");
            output.setEditable(false);
            output.setRows(10);
            up.add(testo);
            up.add(bottone);
            this.add(up, BorderLayout.NORTH);
            this.add(output, BorderLayout.CENTER);
        }
        
        public void actionPerformed(ActionEvent e) {
            ProcessBuilder builder = new ProcessBuilder("C:\\Documents and Settings\\Simone\\classes\\a.exe"); //CI vuole il percorso assoluto.
            Process p;
            try {
                p = builder.start();
                BufferedReader reader=new BufferedReader(new InputStreamReader(p.getInputStream()));
                PrintWriter writer = new PrintWriter(new OutputStreamWriter(p.getOutputStream()));
                writer.write(testo.getText()+"\n");
                writer.flush();
                String line;
                while((line = reader.readLine()) != null) {
                    output.append(line+"\n");
                }
                reader.close();
                int status = p.exitValue();
            } catch(Exception ex) {
                ex.printStackTrace();
            }
        }
    }

  3. #3
    Allora, chiedo un attimo di pasienza ma come dicevo sono alle prime esperienze in Java... Ho provato a scrivere il main per il codice che hai postato così:
    Codice PHP:
    import java.awt.event.*;
    import java.io.*;
    import javax.swing.*;
    public class 
    Test
    {
       private 
    JFrame f;
       private 
    TalkWithC twc;
       public 
    void main(String args[])
       {
          
    = new JFrame();
          
    twc = new TalkWithC();
          
    f.add(twc);
       }

    Messo tutto nella stessa cartella dove c'è anche il file C già compilato, cambiato ovviamente il path assoluto nel file TalkWithC.java ma come risultato all'atto della compilazione ottengo:

    "C:\MiaProva\TalkWithC.java:33: cannot find symbol
    symbol : constructor ProcessBuilder(java.lang.String)
    location: class java.lang.ProcessBuilder
    ProcessBuilder builder = new ProcessBuilder("C:\\MiaProva\\prova.exe"); //CI vuole il percorso assoluto.
    ^
    1 error"

    Cosa sbaglio? Mi pare di capire che non trova il costruttore per ProcessBuilder...

  4. #4
    Utente di HTML.it
    Registrato dal
    Apr 2007
    Messaggi
    906
    Che versione di java stai usando? La classe ProcessBuilder e' disponibile dalla 1.5.
    A me non da problemi, quindi non ti so dire.
    Puoi provare ad usare un altro metodo(disponibile anche nelle versioni precedenti) che fa una cosa analoga.
    codice:
    Runtime r = Runtime.getRuntime();
    //ProcessBuilder builder = new ProcessBuilder("C:\\MiaProva\\prova.exe");
    Process p;
    try {
       //p = builder.start();
       p = r.exec("C:\\MiaProva\\prova.exe");
    Un'appunto sulla classe di test. Il main e' impreciso, in java dev'essere obbligatoriamente static. In piu' quando si crea un Frame si devono settare l'operazione di chiusura (altrimenti il programma continua ad andare anche chiudendo la finestra) e le dimensioni.
    codice:
    import javax.swing.*;
    
    public class Test1{
        public static void main(String[] args) {
            JFrame f = new JFrame();
            TalkWithC twc = new TalkWithC();
            f.add(twc);
    
            //Operazioni di default sul JFrame. Setto cosa fare in chiusura, le dimensioni e mostro il frame
            f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
            f.setSize(200,200);
            f.setVisible(true);
        }
    }

  5. #5
    Con exec tutto funzionante. Credo di riuscire ad adattarlo ora alla mia applicazione C... Grazie mille!!
    (è strano però che il primo tentativo non sia andato bene, anch'io ho Java 1.5.).

    Sul punto 2, ovvero permettere agli utenti di utilizzare l'applicazione (tramite la nuova interfaccia...) direttamente da una pagina online, come mi consigliereste di organizzarmi? Deve necessariamente trattarsi di un appelT per funzionare da pagina web o ho altre vie da percorrere? Quali limiti ci sarebbero? Grazie, ciao..

  6. #6
    Utente di HTML.it
    Registrato dal
    Apr 2007
    Messaggi
    906
    Se devi usare l'interfaccia, mi sa che l'unica via percorribile e' quella dell'applet. Il problema e' che le applet hanno delle limitazioni (tipo non possono lanciare processi o caricare librarie) quindi temo che ci sia un po' da lavorare su questo punto. Probabilmente l'applet anda' firmata.

  7. #7
    Brutta storia questa delle limitazioni delle appleT, mi sa che dovrò lavorarci parecchio...

    Tornando un attimo al primo punto (e scusami se abuso della tua pasienza...), modificando il file C in:
    codice:
    #include <stdio.h>
    
    main ()
    {
       int x;
       float y;
       char stringa[100];
       scanf("%s", stringa);
       scanf("%d", &x);
       scanf("%f", &y);
       printf("Hello %s", stringa);
       printf("Intero = %d", x);
       printf("Reale = %f", y);
    }
    come dovrei andare a modificare la classe TalkWithC? (immagino inserimento di 2 nuove caselle di testo, ma mi mostreresti il codice?).

    Mi sei stato comunque già di grande aiuto, grazie 1000..

  8. #8
    Utente di HTML.it
    Registrato dal
    Apr 2007
    Messaggi
    906
    Per la parte grafica e' piu' costruttivo se il codice lo scrivi tu.
    C'e' un tutorial ufficiale che introduce abbastanza bene i vari componenti grafici.
    Per la parte di comunicazione, dopo che hai avviato il processo e preso i due Stream di input/output, basta che fai le read e le write nel giusto ordine.

  9. #9
    Effettivamente hai ragione, quel che mi occorre ora è fare un pò di pratica... Dopo essermi documentato un pò ho prodotto questo (sempre "lavorando" sul tuo):

    codice:
    CODICE C:
    #include <stdio.h>
    
    main ()
    {
       char nome[100], cognome[100];
       int age;
       scanf("%s", nome);
       scanf("%s", cognome);
       scanf("%d", &age);
       printf("%s\n", nome);
       printf("%s\n", cognome);
       printf("%d\n", age);
    }
    
    CODICE JAVA:
    import java.awt.BorderLayout;
    import java.awt.event.*;
    import java.io.*;
    import javax.swing.*;
    
    public class TalkWithC extends JPanel implements ActionListener
    {
       private JTextField testo;
       private JTextField testo2;
       private JTextField testo3;
       private JLabel lab;
       private JLabel lab2;
       private JLabel lab3;
       private JButton bottone;
       private JTextArea output;
       private JPanel up;
    
       /** Creates a new instance of TalkWithC */
       public TalkWithC()
       {
          super();
          this.setLayout(new BorderLayout());
          up = new JPanel();
          testo = new JTextField(10);
          testo2 = new JTextField(10);
          testo3 = new JTextField(10);
          lab = new JLabel("Nome");
          lab2 = new JLabel("Cognome");
          lab3 = new JLabel("Eta");
          bottone = new JButton("Test");
          bottone.addActionListener(this);
          output = new JTextArea("Output: \n");
          output.setEditable(false);
          output.setRows(10);
          up.add(lab);
          up.add(testo);
          up.add(lab2);
          up.add(testo2);
          up.add(lab3);
          up.add(testo3);
          up.add(bottone);
          this.add(up, BorderLayout.NORTH);
          this.add(output, BorderLayout.CENTER);
       }
    
       public void actionPerformed(ActionEvent e)
       {
          Runtime r = Runtime.getRuntime();
          Process p;
          try
          {
             p = r.exec("C:\\Documents and Settings\\Ida\\Desktop\\Nuo\\prova.exe");
    
             BufferedReader reader=new BufferedReader(new InputStreamReader(p.getInputStream()));
             PrintWriter writer = new PrintWriter(new OutputStreamWriter(p.getOutputStream()));
             writer.write(testo.getText() + "\n");
             writer.write(testo2.getText() + "\n");
             writer.write(testo3.getText() + "\n");
             writer.flush();
             String line;
             while((line = reader.readLine()) != null)
             {
                output.append(line+"\n");
             }
             reader.close();
             int status = p.exitValue();
          } catch(Exception ex)
          {
             ex.printStackTrace();
          }
       }
    }
    che funziona esattamente come dovrebbe (pur non servendo a nulla...).

    Solo due considerazioni:
    1) secondo te è corretto acquisire anche l'eta (quindi un valore numerico) con getText (quindi come stringa...)? C'è un modo migliore? Secondo me non è molto corretto, ma poi ho visto (modificando il main.c) che in realtà il valore acquisito viene trattato proprio come un intero, quindi no problemm (almeno credo...)
    2) se le 3 TextField le volessi disporre una sotto l'altra e non una dopo l'altra come dovrei fare?

    Grazie

  10. #10
    Utente di HTML.it
    Registrato dal
    Apr 2007
    Messaggi
    906
    E' corretto perche' le JTextField hanno solo getText() per leggere stringhe. Inoltre PrintWriter scrive delle stringhe. Il programma C comunque non sa che in java il valore era una stringa perche' lui prende le info come stream di byte. Teoricamente potresti fare una classe che estende JTextField che ti prende in input solo interi e che ha un metodo per restituire un int, ma mi sembra superfluo. Puoi pero' convertire il valore in un int usando Integer.parseInt() per controllare se il valore e' di tipo numerico.
    codice:
    int eta;
    try {
       eta = Integer.parseInt(testo3.getText());
    } catch(NumberFormatException) {
       output.append("Eta non corretta. Inserire un valore numerico.\n");
    }
    Per la domanda due,devi usare un layout apposito. Ad esempio un GridLayout.
    codice:
    up = new JPanel();
    up.setLayout(new GridLayout(2,4));

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.