PDA

View Full Version : [JAVA] Impostare JTextArea da un'altra classe


Sergei
06-09-2012, 21:53
Salve forum :)

sto praticamente impazzendo con la creazione di questo programmino inutile... ma ormai mi ha preso e finché non lo finisco sto male :D

Ho quasi sistemato tutto solo che ho un piccolo problema. In una classe devo fare in modo che modifichi il contenuto della JTextArea che è presente in un'altra classe. Ora, io ricordo che tempo fa chiesi già questa cosa risolvendo mi pare creando un oggetto nella classe con la JTextArea e poi passando questo oggetto al costruttore nella classe che mi deve modificare la Jtextarea. Il problema è che questa classe ha un Thread praticamente è più o meno così:
public class CatturaThread implements Runnable {
Boolean vero = true;
String dati = "dati.txt";
CatturaMetodi cm = new CatturaMetodi();
CatturaAutomatica ca = new CatturaAutomatica();


public void run() {
try {
FileOutputStream fos = new FileOutputStream(dati, true);
while (vero != false) {
String clip = cm.getClipboard();
if (clip != null) {
System.out.println(clip);
ca.elenco.setText(clip);
clip = clip + "\n";
fos.write(clip.getBytes());
}

cm.setDelete();
Thread.sleep(500);
}
} catch (Exception ecc) {
System.out.println(ecc);
}
}
}

Si può passare l'oggetto come parametro nel metodo run? A dire la verità c'ho provato ma non funziona :stordita:
C'è qualche modo?

sottovento
07-09-2012, 07:36
Lo puoi passare nel costruttore.
Attenzione pero' che Swing non e' multithreaded....

Sergei
07-09-2012, 13:20
ti ringrazio per la risposta :)

Ho provato ma non va lo stesso :(.

public class CatturaAutomatica extends JFrame {

private JPanel pannello;
JScrollPane scrollBar;
JButton btnAvvia;
public JTextArea elenco;
CatturaMetodi cm = new CatturaMetodi();
Boolean vero = true;
String versione = "0.1 beta";
CatturaThread ct;
CatturaAutomatica auto = this;

/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
CatturaAutomatica frame = new CatturaAutomatica();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}

/**
* Create the frame.
*/
public CatturaAutomatica() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 600, 445);
pannello = new JPanel();
pannello.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(pannello);
pannello.setLayout(null);

btnAvvia = new JButton("Avvia");
btnAvvia.setBounds(236, 49, 117, 25);
pannello.add(btnAvvia);

scrollBar = new JScrollPane();
scrollBar.setBounds(44, 118, 486, 277);
pannello.add(scrollBar);

elenco = new JTextArea();
elenco.setEditable(false);
elenco.setLineWrap(true);
scrollBar.setViewportView(elenco);

btnAvvia.addActionListener(new ActionListener() {

@Override
public void actionPerformed(ActionEvent e) {

if (e.getSource() == btnAvvia) {
CatturaThread ct = new CatturaThread();
Thread t = new Thread(ct);
t.start();


}
}
});

}
}


Io ho creato CatturaAutomatica auto = this; che passo al costruttore, poi creo un oggetto di CatturaAutomatica (esempio ca) e do ca = auto; giusto?
Poi associo ca alla jtextarea e al metodo settext. Il problema è che quando passo al costruttore quella parte mi dice che devo implementare un metodo, lo implemento e mi ripiazza sotto run() :confused:

Forse è per questo che non va, boh

sottovento
07-09-2012, 13:58
ti ringrazio per la risposta :)

Ho provato ma non va lo stesso :(.
<CUT>



Riesci a produrre un piccolo esempio che si possa postare e provare?

Sergei
07-09-2012, 14:03
Certo, anzi mi scuso per non averlo fatto direttamente :)

Classe main con interfaccia grafica:
public class CatturaAutomatica extends JFrame {

private JPanel pannello;
JScrollPane scrollBar;
JButton btnAvvia;
public JTextArea elenco;
CatturaMetodi cm = new CatturaMetodi();
Boolean vero = true;
String versione = "0.1 beta";
CatturaThread ct;
CatturaAutomatica auto = this;

/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
CatturaAutomatica frame = new CatturaAutomatica();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}

/**
* Create the frame.
*/
public CatturaAutomatica() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 600, 445);
pannello = new JPanel();
pannello.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(pannello);
pannello.setLayout(null);

btnAvvia = new JButton("Avvia");
btnAvvia.setBounds(236, 49, 117, 25);
pannello.add(btnAvvia);

scrollBar = new JScrollPane();
scrollBar.setBounds(44, 118, 486, 277);
pannello.add(scrollBar);

elenco = new JTextArea();
elenco.setEditable(false);
elenco.setLineWrap(true);
scrollBar.setViewportView(elenco);

btnAvvia.addActionListener(new ActionListener() {

@Override
public void actionPerformed(ActionEvent e) {

if (e.getSource() == btnAvvia) {
CatturaThread ct = new CatturaThread();
Thread t = new Thread(ct);
t.start();


}
}
});

}
}

Classe che deve modificare la JTextArea
public class CatturaThread implements Runnable {
Boolean vero = true;
String dati = "dati.txt";
CatturaMetodi cm = new CatturaMetodi();
CatturaAutomatica ca;



public void run(CatturaAutomatica auto) {
ca = auto;
try {
FileOutputStream fos = new FileOutputStream(dati, true);
while (vero != false) {
String clip = cm.getClipboard();
if (clip != null) {
System.out.println(clip);
ca.elenco.setText(clip);
clip = clip + "\n";
fos.write(clip.getBytes());
}

cm.setDelete();
Thread.sleep(500);
}
} catch (Exception ecc) {
System.out.println(ecc);
}
}



@Override
public void run() {
// TODO Auto-generated method stub

}


}

Classe con i metodi vari
public class CatturaMetodi {
// If a string is on the system clipboard, this method returns it;
// otherwise it returns null.
public static String getClipboard() {
Transferable t = Toolkit.getDefaultToolkit().getSystemClipboard()
.getContents(null);

try {
if (t != null && t.isDataFlavorSupported(DataFlavor.stringFlavor)) {
String text = (String) t
.getTransferData(DataFlavor.stringFlavor);
return text;

}
} catch (UnsupportedFlavorException e) {
} catch (IOException e) {
}
return null;
}

// This method writes a string to the system clipboard.
// otherwise it returns null.
public static void setClipboard(String str) {
StringSelection ss = new StringSelection(str);
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(ss, null);
}

// Quando viene invocato questo metodo cancellera' il contenuto presente
// nella clipboard
public static void setDelete() {
Toolkit.getDefaultToolkit().getSystemClipboard()
.setContents(new Transferable() {
public DataFlavor[] getTransferDataFlavors() {
return new DataFlavor[0];
}

public boolean isDataFlavorSupported(DataFlavor flavor) {
return false;
}

public Object getTransferData(DataFlavor flavor)
throws UnsupportedFlavorException {
throw new UnsupportedFlavorException(flavor);
}
}, null);
}

}

sottovento
08-09-2012, 22:06
Dear
scusa il ritardo, ma il padrone di casa mi ha cacciato fuori senza alcun preavviso poiche' qualcuno era interessato al mio appartamento, e ho dovuto trovarne un altro in tutta fretta.

Scusami anche per averti dato un suggerimento forse un po' troppo stringato: quando dicevo di passarlo nel costruttore, intendevo questo:


public class CatturaThread implements Runnable
{
...
public CatturaThread (CatturaAutomatica catturaAutomatica)
{
ca = catturaAutomatica;
}


il metodo run() doveva restare senza costruttori, quindi il codice che hai scritto nel metodo run(CatturaAutomatica auto) non veniva mai eseguito.

Se ho interpretato bene il tuo pensiero, qui trovi il codice modificato:


import java.io.*;

public class CatturaThread implements Runnable
{
Boolean vero = true;
String dati = "dati.txt";
CatturaMetodi cm = new CatturaMetodi();
CatturaAutomatica ca;

public CatturaThread (CatturaAutomatica catturaAutomatica)
{
ca = catturaAutomatica;
}

@Override
public void run()
{
try
{
FileOutputStream fos = new FileOutputStream(dati, true);
while (vero != false)
{
String clip = cm.getClipboard();
if (clip != null)
{
System.out.println(clip);
ca.elenco.setText(clip);
clip = clip + "\n";
fos.write(clip.getBytes());
}

cm.setDelete();
Thread.sleep(500);
}
}
catch (Exception ecc)
{
System.out.println(ecc);
}
}
}

import java.io.*;
import java.awt.*;
import java.awt.dnd.*;
import java.awt.datatransfer.*;

public class CatturaMetodi
{
// If a string is on the system clipboard, this method returns it;
// otherwise it returns null.
public static String getClipboard()
{
Transferable t = Toolkit.getDefaultToolkit().getSystemClipboard().getContents(null);

try
{
if (t != null && t.isDataFlavorSupported(DataFlavor.stringFlavor))
{
String text = (String) t.getTransferData(DataFlavor.stringFlavor);
return text;
}
}
catch (UnsupportedFlavorException e)
{
}
catch (IOException e)
{
}
return null;
}

// This method writes a string to the system clipboard.
// otherwise it returns null.
public static void setClipboard(String str)
{
StringSelection ss = new StringSelection(str);
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(ss, null);
}

// Quando viene invocato questo metodo cancellera' il contenuto presente
// nella clipboard
public static void setDelete()
{
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new Transferable()
{
public DataFlavor[] getTransferDataFlavors()
{
return new DataFlavor[0];
}

public boolean isDataFlavorSupported(DataFlavor flavor)
{
return false;
}

public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException
{
throw new UnsupportedFlavorException(flavor);
}
}, null);
}
}
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.border.*;

public class CatturaAutomatica extends JFrame
{

private JPanel pannello;
JScrollPane scrollBar;
JButton btnAvvia;
public JTextArea elenco;
CatturaMetodi cm = new CatturaMetodi();
Boolean vero = true;
String versione = "0.1 beta";
CatturaThread ct;
CatturaAutomatica auto = this;

/**
* Launch the application.
*/
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
try
{
CatturaAutomatica frame = new CatturaAutomatica();
frame.setVisible(true);
}
catch (Exception e)
{
e.printStackTrace();
}
}
});
}

/**
* Create the frame.
*/
public CatturaAutomatica()
{
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 600, 445);
pannello = new JPanel();
pannello.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(pannello);
pannello.setLayout(null);

btnAvvia = new JButton("Avvia");
btnAvvia.setBounds(236, 49, 117, 25);
pannello.add(btnAvvia);

scrollBar = new JScrollPane();
scrollBar.setBounds(44, 118, 486, 277);
pannello.add(scrollBar);

elenco = new JTextArea();
elenco.setEditable(false);
elenco.setLineWrap(true);
scrollBar.setViewportView(elenco);

final CatturaAutomatica myself = this;
btnAvvia.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{

if (e.getSource() == btnAvvia)
{
CatturaThread ct = new CatturaThread(myself);
Thread t = new Thread(ct);
t.start();
}
}
});
}
}



Questo codice ha l'effetto di mostrare nella text area il testo che e' stato copiato nella clipboard di sistema.


Gli import li ho aggiunti grossolanamente a mano, ma il tuo ambiente sapra' far di meglio.

Spero di esserti stato d'aiuto

Sergei
09-09-2012, 15:18
Ti ringrazio per la risposta :)

Sono proprio rinco, avrei dovuto pensarci prima, avevo fatto proprio così con un altro programma, solo che la concentrazione ogni tanto va a farsi friggere e avevo scambiato il metodo run() per il costruttore :mbe:

Funziona! Grazie mille!

L'unico problema è copia il testo nella jtextarea ma poi il testo dopo anziché andare a capo va a sostituirsi a quello già esistente, non ho capito bene il perché di questo :confused: nonostante abbia provato con ca.elenco.setText(clip + "\n"); e setWrapStyleWord(true);
uhm, mi pare strano... c'è qualcosa che ancora una volta mi sfugge :stordita:

sottovento
10-09-2012, 06:32
Ti ringrazio per la risposta :)

Sono proprio rinco, avrei dovuto pensarci prima, avevo fatto proprio così con un altro programma, solo che la concentrazione ogni tanto va a farsi friggere e avevo scambiato il metodo run() per il costruttore :mbe:

Funziona! Grazie mille!

L'unico problema è copia il testo nella jtextarea ma poi il testo dopo anziché andare a capo va a sostituirsi a quello già esistente, non ho capito bene il perché di questo :confused: nonostante abbia provato con ca.elenco.setText(clip + "\n"); e setWrapStyleWord(true);
uhm, mi pare strano... c'è qualcosa che ancora una volta mi sfugge :stordita:

Ti basta aggiungere una linea nella CatturaThread.run():

Dove hai scritto:

if (clip != null)
{
System.out.println(clip);
ca.elenco.setText(clip);
clip = clip + "\n";
fos.write(clip.getBytes());
}

Potresti farlo diventare:

if (clip != null)
{
System.out.println(clip);
String text = ca.elenco.getText() + "\n" + clip;
ca.elenco.setText(text);
clip = clip + "\n";
fos.write(clip.getBytes());
}


Ti consiglio di aggiungere un controllo sulla dimensione del testo (il testo continua a crescere e se il programma gira per tanto tempo, le dimensioni potrebbero essere inaccettabili e rallentare l'esecuzione, o peggio ancora produrre un OutOfMemory).

Sergei
11-09-2012, 14:24
perfetto, funziona!

Senti, una curiosità proprio a livello di logica, perché prima non funzionava?
Cioè scrivere ca.elenco.setText(clip + "\n"); non è equivalente a quello che mi hai consigliato perché chiaramente non funziona, solo che non riesco a capire il perché? Perché mancava il metodo getText()?

Grazie mille e scusa le domande :D

sottovento
12-09-2012, 08:50
perfetto, funziona!

Senti, una curiosità proprio a livello di logica, perché prima non funzionava?
Cioè scrivere ca.elenco.setText(clip + "\n"); non è equivalente a quello che mi hai consigliato perché chiaramente non funziona, solo che non riesco a capire il perché? Perché mancava il metodo getText()?

Grazie mille e scusa le domande :D
Ti chiedo scusa un'altra volta per il ritardo.
Quello che ho scritto e':
1 - leggi il testo attualmente visualizzato nella text area;
2 - aggiungi il nuovo testo al testo precedente;
3 - visualizza il risultato con la setText();

quello che avevi scritto prima semplicemente visualizzava il contenuto corrente della clipboard (i.e. non sommava il contenuto attuale con quello precedente). Detto fra noi, mi piace anche di piu' :D ma si tratta di un parere personale.

ciao

banryu79
12-09-2012, 13:03
Aggiungo che per appendere del testo a una JTextArea si può usare il metodo specifico "append"

Sergei
14-09-2012, 20:18
Ti chiedo scusa un'altra volta per il ritardo.
Quello che ho scritto e':
1 - leggi il testo attualmente visualizzato nella text area;
2 - aggiungi il nuovo testo al testo precedente;
3 - visualizza il risultato con la setText();

quello che avevi scritto prima semplicemente visualizzava il contenuto corrente della clipboard (i.e. non sommava il contenuto attuale con quello precedente). Detto fra noi, mi piace anche di piu' :D ma si tratta di un parere personale.

ciao

afferrato :)

Aggiungo che per appendere del testo a una JTextArea si può usare il metodo specifico "append"

:stordita: non so come mai non c'ho pensato subito :doh: