PDA

View Full Version : [JAVA] Come stampare ???


PaVi90
14-04-2008, 08:18
Ciao a tutti,
avrei necessità di stampare (non a video, ma con la stampante connessa al pc da cui il programma viene eseguito) un array dinamico di record (con due campi: nome prodotto e prezzo), ed in più aggiungere una intestazione sulla pagina stampata. Vorrei realizzare, insomma, una specie di scontrino.
Ho cercato con google ma ho trovato solo un paio di risultati, ma di difficile comprensione :mc:

Chi sa darmi qualche dritta, magari facile facile? :p

Thanks ;)

andbin
14-04-2008, 08:33
avrei necessità di stampare (non a video, ma con la stampante connessa al pc da cui il programma viene eseguito) un array dinamico di record (con due campi: nome prodotto e prezzo), ed in più aggiungere una intestazione sulla pagina stampata. Vorrei realizzare, insomma, una specie di scontrino.Una soluzione è usare le Printing API di Java SE, vedi <qui> (http://java.sun.com/javase/technologies/desktop/printing/).
Un'altra è usare tools/librerie apposite (e più complesse) per la gestione dei report, una è JasperReports (http://www.jasperforge.org).

PaVi90
14-04-2008, 09:29
Grazie :)

Ma non ci ho capito niente :stordita: :cry: :cry:

andbin
14-04-2008, 10:11
Ma non ci ho capito niente :stordita: :cry: :cry:Nemmeno l'esempio minimale/basilare/stupido HelloWorldPrinter.java (http://java.sun.com/docs/books/tutorial/2d/printing/examples/HelloWorldPrinter.java) del tutorial?? :fagiano:

PaVi90
14-04-2008, 10:22
Nemmeno l'esempio minimale/basilare/stupido HelloWorldPrinter.java (http://java.sun.com/docs/books/tutorial/2d/printing/examples/HelloWorldPrinter.java) del tutorial?? :fagiano:
Uhm ora provo... ma non ti assicuro niente :stordita:

PaVi90
14-04-2008, 10:29
Ho riportato l'esempio copincollandolo (:fagiano:) e funge :stordita:
Ma non capisco come accidenti fa a funzionare, le classi a cosa servono, i vari metodi, i cosi grafici... :cry:

Il codice copincollato è questo, a cui ho aggiunto i commenti solo alle righe di codice che sono riuscito a comprendere; i commenti in inglese, invece, sono quelli che già c'erano all'origine:


package helloworldprinter;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.print.*;

public class HelloWorldPrinter implements Printable, ActionListener {


public int print(Graphics g, PageFormat pf, int page) throws PrinterException {

if (page > 0) { /* We have only one page, and 'page' is zero-based */
return NO_SUCH_PAGE;
}

/* User (0,0) is typically outside the imageable area, so we must
* translate by the X and Y values in the PageFormat to avoid clipping
*/
Graphics2D g2d = (Graphics2D)g;
g2d.translate(pf.getImageableX(), pf.getImageableY());

/* Now we perform our rendering */
// Ciò che stampa, con i margini dall'angolo della pagina:
g.drawString("Hello world!", 100, 100);

/* tell the caller that this page is part of the printed document */
return PAGE_EXISTS;
}

public void actionPerformed(ActionEvent e) {
PrinterJob job = PrinterJob.getPrinterJob();
job.setPrintable(this);
boolean ok = job.printDialog();
if (ok) {
try {
job.print();
} catch (PrinterException ex) {
/* The job did not successfully complete */
}
}
}

public static void main(String args[]) {

//UIManager.put("swing.boldMetal", Boolean.FALSE);

// Dichiarazione del frame con intestazione:
JFrame f = new JFrame("Hello World Printer");

// Oggetto ascoltatore per la chiusura del frame:
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {System.exit(0);}
});

// Dichiarazione pulsante con la scritta <<Print Hello World>>:
JButton printButton = new JButton("Print Hello World");

// ???
printButton.addActionListener(new HelloWorldPrinter());

// Aggiunge al centro del frame il pulsante printButton:
f.add("Center", printButton);

// Resize del frame in modo da contenere in modo ottimale il pulsante:
f.pack();

// Rende visibile il frame:
f.setVisible(true);
}
}


Potresti aiutarmi a capire il resto del codice, quello senza commenti? Thanks :ave:


Cmq grazie di tutto! ;)

andbin
14-04-2008, 12:24
Quell'esempio è sì abbastanza semplice ma ci sono delle cose da comprendere bene.

Nel main() viene creato un JFrame in cui viene messo un pulsante. Al pulsante viene aggiunto un ActionListener che è una istanza di HelloWorldPrinter (che appunto implementa ActionListener).

Fino a qui si tratta di un normale e semplice uso di Swing.

Quando viene premuto il pulsante, viene invocato actionPerformed(). Qui inizia la parte da capire bene.

PrinterJob.getPrinterJob() serve per ottenere una istanza di PrinterJob, che è la classe principale che controlla la stampa. Inizialmente è associato al PrinterJob la stampante di default, quella predefinita.

setPrintable() serve per indicare quale è l'oggetto "stampabile". Qui viene usata una interfaccia. Alla Printing API interessa solamente sapere quale è l'oggetto che implementa l'interfaccia Printable che quindi implementa il metodo print(blabla....). È la Printing API che "chiede" all'oggetto Printable di stampare la/e pagina/e invocando di volta in volta il metodo print().

printDialog() presenta la classica finestra di selezione delle stampanti. Scegli la stampante e premi OK. Se il ritorno è true, allora hai selezionato una stampante, quindi a quel punto si invoca print().

La Printing API invoca print() di Printable in sequenza per ogni pagina (le pagine partono da 0) fino a quando print() non ritorna NO_SUCH_PAGE.

All'interno di print() hai il Graphics, hai le informazioni sul formato (PageFormat) e il numero di pagina. Quindi puoi stampare quello che vuoi sulla pagina. L'unica nota: per default l'unità di misura è in 72esimi di pollice.
Si possono naturalmente fare traslazioni, scalamenti o altro sul Graphics.

PaVi90
14-04-2008, 12:42
:cry: Non ho capito quasi nulla :stordita:
E se volessi stampare semplicemente una stringa?! :p

andbin
14-04-2008, 12:58
:cry: Non ho capito quasi nulla :stordita:
E se volessi stampare semplicemente una stringa?! :pMa .... è proprio quello che fa l'esempio!!! Stampa "Hello world!" sull'unica pagina stampata.

Comunque tutto il nocciolo della questione è l'interfaccia Printable. Alla Printing API non interessa sapere dove è, cosa è o cosa fa l'oggetto Printable. Interessa solo sapere che appunto è-un Printable e quindi implementa certamente il metodo print(....).

Quando c'è bisogno di stampare la Printing API invoca il metodo print(), come se dicesse: "senti Printable, stampa la pagina 0". Se la pagina 0 esiste, tu disegni sul Graphics e ritorni PAGE_EXISTS. Poi la Printing API continua: "senti Printable, stampa la pagina 1". Se come nell'esempio la pagina 1 (la seconda) non c'è, allora fai ritornare NO_SUCH_PAGE e finisce tutto lì.

PaVi90
14-04-2008, 13:00
Ma .... è proprio quello che fa l'esempio!!! Stampa "Hello world!" sull'unica pagina stampata.

Comunque tutto il nocciolo della questione è l'interfaccia Printable. Alla Printing API non interessa sapere dove è, cosa è o cosa fa l'oggetto Printable. Interessa solo sapere che appunto è-un Printable e quindi implementa certamente il metodo print(....).

Quando c'è bisogno di stampare la Printing API invoca il metodo print(), come se dicesse: "senti Printable, stampa la pagina 0". Se la pagina 0 esiste, tu disegni sul Graphics e ritorni PAGE_EXISTS. Poi la Printing API continua: "senti Printable, stampa la pagina 1". Se come nell'esempio la pagina 1 (la seconda) non c'è, allora fai ritornare NO_SUCH_PAGE e finisce tutto lì.

Ora mi è un po' più chiaro ;)

PaVi90
14-04-2008, 14:38
Non ci ho capito ancora quasi niente :stordita: :asd:
Ho letto venti volte il tuo post ma nulla :muro: :what:
Sarà che mi mancano le basi :( :boh:

andbin
14-04-2008, 14:49
Non ci ho capito ancora quasi niente :stordita: :asd:
Ho letto venti volte il tuo post ma nulla :muro: :what:
Sarà che mi mancano le basi :( :boh:Scusa ma .. cosa non ti è chiaro in particolare?

Tu "dai" al PrinterJob (con setPrintable()) un oggetto che implementa Printable. Quando sarà necessario stampare, verrà invocato di volta in volta il metodo print() sul tuo oggetto. Questo perché ovviamente sei tu che hai implementato il Printable che "sai" cosa/come stampare la pagina e inoltre quante pagine ci sono.
La Printing API si limita solo ad invocare print() ... "ehi Printable ... senti, stampa la pagina X".

Come concetto non mi sembra difficile.

PaVi90
14-04-2008, 14:55
Aspetta aspetta... cosa vuol dire <<dai al PrinterJob (con setPrintable()) un oggetto che implementa Printable.>> ??
Mi sono già perso :stordita:

Ma non c'è un tutorial a livello di "asilo nido"?? Ho difficoltà a stare dietro al discorso...

andbin
14-04-2008, 15:38
Aspetta aspetta... cosa vuol dire <<dai al PrinterJob (con setPrintable()) un oggetto che implementa Printable.>> ??
Mi sono già perso :stordita:Nell'esempio fa: job.setPrintable(this);
Viene passato al PrinterJob ('job') tramite setPrintable() un reference ('this') che fa riferimento alla istanza di HelloWorldPrinter (che appunto implementa Printable).

Ma non c'è un tutorial a livello di "asilo nido"??Roba del tipo "Il manuale Java delle Giovani Marmotte" o "Primi passi in Java da 0 a 6 anni"??? No, non mi risulta. :p
Scusa la battuta eh ... ;)

nuovoUtente86
14-04-2008, 16:24
Aspetta aspetta... cosa vuol dire <<dai al PrinterJob (con setPrintable()) un oggetto che implementa Printable.>> ??
Mi sono già perso :stordita:

Ma non c'è un tutorial a livello di "asilo nido"?? Ho difficoltà a stare dietro al discorso...

Conosci il funzionamento e lo scopo di un' interfaccia?

PaVi90
14-04-2008, 17:17
Nell'esempio fa: job.setPrintable(this);
Viene passato al PrinterJob ('job') tramite setPrintable() un reference ('this') che fa riferimento alla istanza di HelloWorldPrinter (che appunto implementa Printable).

Roba del tipo "Il manuale Java delle Giovani Marmotte" o "Primi passi in Java da 0 a 6 anni"??? No, non mi risulta. :p
Scusa la battuta eh ... ;)
:stordita: :help:
Conosci il funzionamento e lo scopo di un' interfaccia?
Parli degli eventi asincroni e quella roba lì?

khelidan1980
14-04-2008, 17:31
:stordita: :help:

Parli degli eventi asincroni e quella roba lì?

mi sa che ti devi rivedere le interfacce! ;)

nuovoUtente86
14-04-2008, 18:13
:stordita: :help:

Parli degli eventi asincroni e quella roba lì?

Un' interfaccia è un contratto.....ovvero stabilisce che l'oggetto che la implementa esporterà delle funzionalità sotto forma di metodi stabilita a priori dall' interfaccia.Ad esempio l' interfaccia Comparable ha un unico metodo
public int compareTo(Object o) oppure

public int compareTo(MiaClasse mc) con l' utilizzo dei generici!

In sostanza avrai qualcosa del genere

public MiaClasse implements Comparable{
public int compareTo(Object o){
return 0;// esempio da non seguire ma che serve ad indicare il fatto che l' interfaccia garantisce che il metodo sia implementato, non che sia correttamente funzionale!
}
}

Implementare un ' interfaccia ti consente un assegnamento del tipo

Compareble c=new MiaClasse();
ed ovviamente di passare un oggetto che implementa l' interfaccia ad un metodo con questa firma

public void metodo(Comparable c){}

PaVi90
14-04-2008, 18:52
Uhm... non ho capito moltissimo ma qualcosa ho capito :stordita:

franksisca
15-04-2008, 08:07
scusa se mi intrometto....ma conosci java???


cosa hai fatto fino ad ora, perchè a me sembra che ti manchino le basi....

gugoXX
15-04-2008, 08:17
Mmmh.

http://knowfree.net/wp-content/uploads/2007/04/047008716101_sclzzzzzzz_.jpghttp://www.lsl.com.au/images/images-ref/java-all-in-one-desk-reference-for-dummies.jpghttp://images-eu.amazon.com/images/P/0764526464.02.LZZZZZZZ.jpg

PaVi90
15-04-2008, 08:19
Guarda che hai sbagliato tag per le immagini :Prrr:
EDIT: ora lo hai aggiustato :D
Cmq cercavo qualcosa di simile, effettivamente... :asd:

Cmq tornando a noi, io a differenza dell'esempio dove c'è scritto "public class HelloWorldPrinter implements Printable, ActionListener", ho un progetto (in cui devo implementare la funzione di stampa) con: "public class Bar extends javax.swing.JFrame". Se dopo l'extends gli scrivo "implements Printable, ActionListener" mi dà errore. Perchè? :stordita:

gugoXX
15-04-2008, 08:25
Comunque, scherzi a parte, quella di inziare dalle basi, con un libro che spiega tutto anche per le pietre, non e' male.
Io stesso 5 anni fa ho iniziato il C# con una guida per bambini, nonostante arrivassi da ASm, C, C++, Java, etc.
Lo ritengo un modo veloce per entrare nell'ordine di idee corretto.

Ed e' lo stesso che utilizzavo, quando potevo, all'universita'.
Avevo comprato un libro divulgativo con tanti colori e tante immagini per studiare fisica2. Poi ovviamente bisogna passare alle cose serie, ma almeno se capisci la suddivisione dei capitoli e il suo perche' sei gia' a meta' dell'opera.

andbin
15-04-2008, 08:32
ho un progetto (in cui devo implementare la funzione di stampa) con: "public class Bar extends javax.swing.JFrame". Se dopo l'extends gli scrivo "implements Printable, ActionListener" mi dà errore. Perchè? :stordita:Beh, innanzitutto dovresti importare java.awt.print.* e poi ovviamente implementare nella classe il metodo:

public int print(Graphics graphics, PageFormat pageFormat, int pageIndex)

L'hai fatto?

PaVi90
15-04-2008, 08:41
Beh, innanzitutto dovresti importare java.awt.print.* e poi ovviamente implementare nella classe il metodo:

public int print(Graphics graphics, PageFormat pageFormat, int pageIndex)

L'hai fatto?


Si ora è ok; però ora quando nel main vado a fare questo codice:


public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new Bar().setVisible(true);
}
});
PulsanteOrdina.addActionListener(new Bar()); }


Mi dà errore :stordita:

andbin
15-04-2008, 08:45
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new Bar().setVisible(true);
}
});
PulsanteOrdina.addActionListener(new Bar()); }


Mi dà errore :stordita:No alt. La prima cosa che posso immaginare è che quella variabile PulsanteOrdina non sia "in scope". Poi comunque messa lì dopo l'invokeLater non ha per nulla senso ....

Ti manca "qualcosa" a livello di basi e anche su Swing, scusa se lo dico.

PaVi90
15-04-2008, 08:47
No alt. La prima cosa che posso immaginare è che quella variabile PulsanteOrdina non sia "in scope". Poi comunque messa lì dopo l'invokeLater non ha per nulla senso ....

Ti manca "qualcosa" a livello di basi e anche su Swing, scusa se lo dico.

Eh lo so che mi mancano le basi...
Premesso che il pulsante è PulsanteOrdina, dove dovrei inserirlo per associargli l'evento di stampa? In quale classe?

PaVi90
15-04-2008, 08:51
Ho messo l'istruzione del pulsante nel public Bar(); non dà errore, ma al run esce questo mega-errore:

run:
Exception in thread "AWT-EventQueue-0" java.lang.StackOverflowError
at sun.awt.Win32GraphicsConfig.getBounds(Native Method)
at sun.awt.Win32GraphicsConfig.getBounds(Win32GraphicsConfig.java:240)
at java.awt.Window.init(Window.java:368)
at java.awt.Window.<init>(Window.java:407)
at java.awt.Frame.<init>(Frame.java:402)
at java.awt.Frame.<init>(Frame.java:367)
at javax.swing.JFrame.<init>(JFrame.java:163)
at Bar.<init>(Bar.java:63)
at Bar.<init>(Bar.java:64)
at Bar.<init>(Bar.java:64)
at Bar.<init>(Bar.java:64)
at Bar.<init>(Bar.java:64)
at Bar.<init>(Bar.java:64)
........... (esce scritto tantissime volte)........
at Bar.<init>(Bar.java:64)
at Bar.<init>(Bar.java:64)

PaVi90
15-04-2008, 08:56
Ora invece l'ho messo all'esterno, associandolo ad un evento, e funge.

private void PulsanteOrdinaMouseClicked(java.awt.event.MouseEvent evt) {
// Al click del mouse, deve stampare lo scontrino con la stampante...
PulsanteOrdina.addActionListener(new Bar());
}

Però ho notato che mi esegue due volte il codice presente in public BAR()
Forse perchè al click del pulsante c'è il new Bar() ???
Come fare per far sì che il codice presente in bar venga eseguito una sola volta? Ho provato con un flag ma non funge...

gugoXX
15-04-2008, 09:01
Non so quanti linguaggi di programmazione hai imparato e conosci oggi.
Ma non si affronta cosi'.

Occorre capire ogni singola istruzione, dalla prima in alto all'ultima in basso. Almeno sapere a cosa serve.
E prima si fa sui libri, poi sul computer.

Ti consiglio seriamente di leggere almeno un tutorial prima.

Altrimenti farai la fine di quel mio amico delle medie, che copiava i programmi dal manuale, poi li salvava.
E si lamentava che tutti i programmi che scriveva si chiamavano
"PIPPO"

Gli avevo detto che per salvare doveva scrivere
SAVE "PIPPO".
E lui cosi' faceva.

PaVi90
15-04-2008, 09:02
Facciamo così... vi allego il sorgente; apritelo col Word altrimenti è un macello.

andbin
15-04-2008, 09:06
Ora invece l'ho messo all'esternoNo .. scusa eh ... non è che puoi continuare a provare a mettere le cose un po' lì ... un po' là ... un po' nel costruttore .... finché ti compila o magari ti "sembra" che funzioni ....

Prendi un bel libro e inizia a leggere e studiare le basi di Java. Poi cerca anche di prendere "confidenza" con il javadoc delle API di Java SE e se poi successivamente vuoi usare Swing leggi il tutorial della Sun e magari guarda gli esempi sul tutorial.

Lo dico seriamente.

andbin
15-04-2008, 09:24
Facciamo così... vi allego il sorgente; apritelo col Word altrimenti è un macello.Sì ho letto il codice. Gran parte (tutta quella relativa perlomeno alla GUI) è stata sicuramente autogenerata da un ambiente di sviluppo.

Ma ti dico una cosa: il codice è praticamente incomprensibile e illeggibile. Oltre a non essere mantenibile "a mano".
Non farti **mai** generare il codice da un IDE. Impara tu a scrivere il codice come si deve usando e strutturando i componenti e i layout manager giusti per quello che devi fare.

Oltretutto viene usata un sacco di roba di cui sicuramente non hai nemmeno idea. Il tuo programma così come è può funzionare solo con Java 6 (o superiore) in quanto è stato usato il layout manager GroupLayout, che è molto "avanzato" e disponibile solo da Java 6. Inoltre sono state usate delle stringhe "literal" con contenuti non ASCII, quindi bisogna anche vedere in quale charset è stato scritto il file (ad occhio deduco UTF-8).

PaVi90
15-04-2008, 09:28
A scuola usiamo NetBeans... lo so che molto codice è stato autogenerato (direi l'80% almeno :D)
Cmq senza NetBeans riuscire a fare quel progetto con un sacco di frame, pulsanti, liste, oggetti ascoltatori,... è un macello!
Il problema è ora riuscire a implementare quel prototipo "HelloWorldPrinter" in questo progetto, riuscendo a capire la <<corrispondenza>> con queste classi...

PaVi90
26-04-2008, 18:25
UP

Non so come (:asd:) sono riuscito ad integrare la stampa :stordita:

Però ho un problemino: se la lunghezza della pagina supera l'area di stampa effettiva del foglio, non mi stampa la seconda pagina (ed eventualmente la terza, la quarta, ecc...)
Come faccio? :)

andbin
27-04-2008, 09:45
Però ho un problemino: se la lunghezza della pagina supera l'area di stampa effettiva del foglio, non mi stampa la seconda pagina (ed eventualmente la terza, la quarta, ecc...)Sicuramente "mi ripeterò" perché l'ho già spiegato con altre parole nei post precedenti.

Le Printing API di Java SE sono tutto sommato semplici e minimali. Tutta la "intelligenza" nella formattazione e stampa dei dati nella pagina non sta nelle API ma deve stare nella "tua" applicazione.
Quando viene invocato il metodo print() che devi implementare, ti vengono passate tutte le informazioni relative alla pagina: il Graphics su cui disegnare, un PageFormat che ti fornisce indicazioni sul formato della pagina e l'indice della pagina (zero-based).
Sei tu che devi stabilire che un certo disegno, paragrafo di testo, ecc... (o qualunque altra cosa devi stampare) non ci sta nella pagina quindi ne stampi solo una parte e rimani "in attesa" di una nuova invocazione di print() per stampare su una nuova pagina.

PaVi90
27-04-2008, 11:23
Sicuramente "mi ripeterò" perché l'ho già spiegato con altre parole nei post precedenti.

Le Printing API di Java SE sono tutto sommato semplici e minimali. Tutta la "intelligenza" nella formattazione e stampa dei dati nella pagina non sta nelle API ma deve stare nella "tua" applicazione.
Quando viene invocato il metodo print() che devi implementare, ti vengono passate tutte le informazioni relative alla pagina: il Graphics su cui disegnare, un PageFormat che ti fornisce indicazioni sul formato della pagina e l'indice della pagina (zero-based).
Sei tu che devi stabilire che un certo disegno, paragrafo di testo, ecc... (o qualunque altra cosa devi stampare) non ci sta nella pagina quindi ne stampi solo una parte e rimani "in attesa" di una nuova invocazione di print() per stampare su una nuova pagina.
Ok ti ringrazio. Cercherò di vedere meglio il codice :stordita: