Serienausdruck per Applet

mathiu

Erfahrenes Mitglied
Hallo allerseits

In unserem Fakturierungs-Programm (PHP), das wir selbst entwickelt haben werden über ein Java-Applet direkt Einzahlungsscheine auf den Drucker geschickt. Nun soll das Programm so erweitert werden, dass auch Serienrechnungen ausgedruckt werden können. Die Rechnungen werden per PDF ausgedruckt, nur die Einzahlungsscheine gehen über das Applet.

Nun zu meiner Frage:

Bei einem Serienausdruck muss ich dem Applet ja jede Menge Daten übergeben, wie würdet ihr das machen? Ich sehe folgende Möglichkeiten:

1. Ich übergebe dem Applet sämtliche Daten über <param /> (nur sah ich keine Möglichkeit das irgendwie effizient zu machen, über ein Array zb.).

2. Ich rufe das Applet mehrmals auf, jedesmal mit anderen Parametern, was mir aber ziemlich "bastelig" erscheint.

3. Ich rufe das Applet über Javascript mehrmals auf und übergebe die Daten ebenfalls über ein Javascript an die Klasse (da hatte ich dann aber noch ein weiteres Problem, auch das ich ev. dann zurückkommen würde).

Irgendwie scheinen mir alle Varianten nicht besonders gut, aber irgendwie fehlen mir weitere Ideen. Was denkt ihr so darüber oder gibt es ev. noch andere Möglichkeiten
 
Lt. Selfhtml könnte die Parameterübergabe an den param-Tag des Applets per Javascript schwierig sein, da kein direkter Zugriff. Es lebe also das Basteln...

Ich würde warscheinlich eher im Applet einen eigenen "Immer-Lauf-Thread" starten, der geduldig auf "Futter" in Form von Daten wartet. Dazu wären 2 Parameter nötig:

HTML:
<script language="JavaScript">
function runPrint() {
var daten = "blabla"; //Deine Daten, die das Applet verarbeiten soll
document.getElementByName("neu").value = daten;
document.getElementByName("run").value = parseInt(document.getElementByName("run").value) + 1;
}
</script>
<applet ...>
<param name="neu" value="">
<param name="run" value="0">
</applet>

Code:
public class MyApplet extends Applet implements Runable {
private boolean start;
private int lauf = 0;
public void init() {
	Thread t = new Thread(this);
	start = true;
	t.start();
}
public void destroy() {
	start = false;
}
public void run() {
	while(start) {
	 if (String.valueOf(lauf).equals(this.getParameter("run")) {
		//Daten einlesen und verarbeiten
		lauf++; //auf nächsten Lauf warten
	 }
	 else {
		 try {
		 Thread.sleep(1000);
		 }
		 catch (InterruptedException ie) {}
	 }
	}
}
}
 
Zuletzt bearbeitet:
Ich meinte auch nicht die Parameter-Übergabe per JS an den <param>-Tag, sondern direkt an die Eigenschaft der Klasse, eigentlich so wie du es gemacht hast.

Meine Variante sah dann aber keinen Endlosdurchlauf sondern fongenden Ablauf vor:
1. Übergabe der Daten per JS an die Klasse.
2. Aufruf der Druck-Methode über JS.

Nur gab es irgendwie damit grössere Probleme, die ich eigentlich nicht nachvollziehen kann.
Ich poste mal meinen Code, damit man sich ein besseres Bild machen kann. Es handelt sich um eine gekürzte Version mit weniger Eigenschaften.

Code:
// das wäre mal PrintApplet.java
import java.applet.Applet;

public class PrintApplet extends Applet {

   public Print2DPrinterJob sp = new Print2DPrinterJob();

     public void init() {
         String azeile1;
         String azeile2;
         String azeile3;
         if((azeile1 = getParameter("azeile1")) == null)
             azeile1 = "";
         if((azeile2 = getParameter("azeile2")) == null)
             azeile2 = "";
         if((azeile3 = getParameter("azeile3")) == null)
             azeile3 = "";
         if((printer = getParameter("printer")) == null)
              printer = "";


         sp.azeile1 = azeile1;
         sp.azeile2 = azeile2;
         sp.azeile3 = azeile3;
         sp.printer = printer;
         sp.start();   // hier wird der Druckvorgang über das Applet selbst gestartet.
     }
}

Code:
// dann mal Print2DPrinterJob.java

import java.awt.*;
import java.awt.print.*;
import javax.print.*;
import javax.print.attribute.*;
import javax.print.attribute.standard.*;

public class Print2DPrinterJob implements Printable {

   String azeile1;
   String azeile2;
   String azeile3;
   String printer;

   public void start() {
      /* Construct the print request specification.
      * The print data is a Printable object.
      * the request additonally specifies a job name, 2 copies, and
      * landscape orientation of the media.
      */
      PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();
      aset.add(MediaSizeName.ISO_A4);
      aset.add(new Copies(1));
      aset.add(new JobName("ESR Druck", null));
      aset.add(MediaTray.TOP);
      aset.add(new MediaPrintableArea(0,0,210,297,1000));

      /* Create a print job */
      PrinterJob pj = PrinterJob.getPrinterJob();
      pj.setPrintable(this);
      /* locate a print service that can handle the request */
      PrintService[] services = PrinterJob.lookupPrintServices();
      if (services.length > 0) {
         System.out.println("PrinterJob.start");
         System.out.println("selected printer "
               + services[Integer.valueOf(printer).intValue()].getName());
         try {
            pj.setPrintService(services[Integer.valueOf(printer).intValue()]);
            pj.print(aset);
         } catch (PrinterException pe) {
            System.err.println(pe);
         }
      }
   }

   public int print(Graphics g,PageFormat pf,int pageIndex) {

      if (pageIndex == 0) {

         int nl = 12;
         int kundAdrRX = 350;
         int kundAdrRY = 665;
         int kundAdrLX = 15;
         int kundAdrLY = 730;

         Graphics2D g2d= (Graphics2D)g;
         g2d.translate(pf.getImageableX(), pf.getImageableY());
         g2d.setColor(Color.black);
         g2d.setFont(new Font("Arial", Font.PLAIN, 10));
         g2d.drawString(azeile1, kundAdrRX,kundAdrRY);
         g2d.drawString(azeile2, kundAdrRX,kundAdrRY+nl);
         g2d.drawString(azeile3, kundAdrRX,kundAdrRY+2*nl);
         g2d.setFont(new Font("Courier New", Font.BOLD, 12));

         return Printable.PAGE_EXISTS;
      } else {
         return Printable.NO_SUCH_PAGE;
      }
   }
}


Code:
// dann hätten wir den Aufruf in test_js2java.htm
<html><head><title>Test</title>

<applet code="PrintApplet.class" width="150" height="25" name="Hallo">
   <param name="azeile1" value="$azeile1">
   <param name="azeile2" value="$azeile2">
   <param name="azeile3" value="$azeile3">
   <param name="printer" value="0">
   <param name="mass" value="Y">
</applet>

<script language="JavaScript">
   function printit() {
      document.Hallo.sp.start();
      document.Hallo.sp.start();
   }
 //document.Hallo.sp.start();
 //document.Hallo.sp.start();
</script>

</head>

<body onLoad="printit()">
</body>
</html>

Der Aufruf funktioniert aber nicht richtig. Wenn die Methode start() des Objekts sp im Applet selbst aufgerufen wird, funktioniert der Ausdruck tadellos, aber ich kann per Javascript irgendwie diese Methode nicht erneut aufrufen. Javascript gibt zwar keine Fehlermeldung aus, aber es geschieht auch nicht irgendetwas.

Jemand eine Ahnung wieso?
 
Also erstmal machst Du was doppelt:

1. das Applet wird geladen, also es wird automatisch die "init()"-Methode aufgerufen und somit auch am Schluß Deiner Initialisierung "sp.start()"

2. Du gibst dem Applet den Name "Hallo" und versuchst dann direkt auf die Klassenvariable "sp" zuzugreifen - das kann nicht gehen.

Du müßtest also garnichts in der HTML-Seite tun, um den Job zu starten. Es fällt "onLoad" und die Javascript-Funktion an sich weg.

Dein Problem ist also nicht das Starten, sondern das Wiederstarten. Du könntest nach dem Ausdruck eine andere HTML-Seite aufrufen und danach wieder diese, dann erfolgt wieder der Ausdruck, wenn Du statt der "init()"- die "start()"-Methode verwendest.

Die vier Applet-Methoden werden je Browser-Implementierung und -einstellung aufgerufen:
1. Öffnen des Browsers, erster Seitenaufruf (bzw. Reload bei jedem Seitenaufruf) = "init()"
2. "start()" oder Neuanzeige/Refresh
3. "stop()" beim Verlassen der Seite
4. "destroy()" beim Schließen des Browsers oder wenn der Browser sich Speicherplatz verschafft

Du könntest also auch statt meinem Automatik-Beispiel die HTML-Seite einfach sooft aufrufen, wie Du Ausdrücke willst (wenn "start()"-Methode).
 
Also erstmal machst Du was doppelt:
Das weiss ich :)
ich rufe sp.start() zweimal auf, einmal in init(), einmal über javascript

1. das Applet wird geladen, also es wird automatisch die "init()"-Methode aufgerufen und somit auch am Schluß Deiner Initialisierung "sp.start()"
Das ist klar und da wird die Methode sp.start() direkt im Applet aufgerufen und der Audruck funktioniert.


2. Du gibst dem Applet den Name "Hallo" und versuchst dann direkt auf die Klassenvariable "sp" zuzugreifen - das kann nicht gehen.
Wieso nicht Habe ich auf diese Klasssen-Variablen keinen Zugriff (auch wenn sie public sind)?

Du müßtest also garnichts in der HTML-Seite tun, um den Job zu starten. Es fällt "onLoad" und die Javascript-Funktion an sich weg.
Das ist mir klar, aber ich will ja die Methode mehrmals starten und das wollte ich über js machen. Der Aufruf im Applet selbst ist nur zu Testzwecken noch drin.

Dein Problem ist also nicht das Starten, sondern das Wiederstarten. Du könntest nach dem Ausdruck eine andere HTML-Seite aufrufen und danach wieder diese, dann erfolgt wieder der Ausdruck, wenn Du statt der "init()"- die "start()"-Methode verwendest.
Was ist der Unterschied zwischen der init()- und start()-Methode (oder anderst gefragt, was ist der Unterschied zwischen "Neuanzeige/Refresh" und "Reload bei jedem Seitenaufruf")?
Das habe ich mir auch schon überlegt, aber wenn ich dann ev. mal 100 mal ausdrucken will geht das eine Weile... und wie weiss ich, wann das Applet fertig ist und ich auf die nächste Seite wechseln kann? Du meinst ja einen Refresh der ganzen Seite mit neuen <param>-Werten?
 
Zuletzt bearbeitet:
Z.B beim IE kann man wählen, ob die Seite bei jedem Aufruf neu geladen werden soll oder ob sie aus dem Cache kommt. Es könnte sogar sein, daß sich Microsoft auch an diese Einstellungen hält... :suspekt:

Die "start()"-Methode ist die sicherste Alternative, denn "start()" wird beim Laden der Seite aufgerufen und "stop()" beim Unload.

Ob Du per Javascript auf public-Variablen innerhalb der Appletklasse zugreifen kannst, weiß ich nicht. Richtig ist, sie müssen public sein, was aber kein guter Programmierstil ist!

Aus dem Applet heraus hast Du keine Möglichkeit, die HTML-Seite zu manipulieren. Möglich wäre, aus dem Applet heraus mit "showDocument(getDocumentBase().toString())" die gleiche Seite nochmal zu laden. ---> Achtung! Du mußt selbst dafür sorgen, in keine Endlosschleife zu gelangen
 

Neue Beiträge

Zurück