Probleme beim drucken

Seppel

Bekanntes Mitglied
Hallo, ich möchte den Inhalt eines JFrames drucken besser gesagt alles was im scrollpane ist. Menü und Rahmen sowie scrollbar sollen weggealassen werden.
Als erstes habe ich mich an einfache Beispiele gewagt--> Text ausdrucken und das ging problemlos
dann habe ich mich an mein fenster gemacht und ausgedruckt.
Folgendes läuft da aber ne so wie es soll:
1. Wie kann man automatisch auf Querformat stellen?
2. Der Rechner zeigt mir zig mal das Druckenfenster an --> wo liegt hier das Problem?
3. warum druckt er immer nur eine Seite und das was nicht darauf past auf die nächste?

richtig gedruckt habe ig nicht, nur an OneNote geschickt um Papier zusparen.

Da der Code zulang war wollte ich ihn kürzen, dabei scheint mir aber ein Fehler unterlaufen zu sein und jetzt geht der code nicht mehr, deshalb hier mal die langform.
Java:
import java.awt.*; 
import java.awt.event.*;
import java.awt.print.*;
import java.awt.Container;
import java.awt.Graphics;
import javax.swing.*;
import java.awt.Font;

public class Chronik2 extends JFrame   { //implements AdjustmentListener
 private static final long serialVersionUID = 1L;

  StammbaumFenster NeueCronik_stammbaum;
  //####################################################################################################################

  
  public static void main(String[] args) {
	Chronik2 fenster = new Chronik2 ("FamilienChronik2");	
    fenster.pack();
    fenster.setSize(965,900);
    fenster.setResizable(false);
    fenster.setVisible(true); 
  }
   
  Chronik2 (String titel) {
    super(titel);

    GridBagLayout gbl = new GridBagLayout();
    JPanel panel1 = new JPanel();
    panel1.setLayout(gbl);   
    
    class CMeinActionLauscher implements ActionListener {
      public void actionPerformed(ActionEvent e)  {
          String label;
          label = e.getActionCommand();
          if (label.equals("Stammbaum anzeigen")) {
        	  NeueCronik_stammbaum =new StammbaumFenster ("");          	  
        	  NeueCronik_stammbaum.pack();          	 
        	  NeueCronik_stammbaum.setSize(855,900);
        	  NeueCronik_stammbaum.setResizable(false);        	  
        	  NeueCronik_stammbaum.setVisible(true);         	  
          }	
      }        
    }  
    //Menü  #####################################################################################################
    JMenuBar menueleiste =new JMenuBar();
    JMenu menu3 =new JMenu("Datenbank");
    
    
    JMenuItem item = new JMenuItem("Stammbaum anzeigen");
    item.addActionListener(new CMeinActionLauscher());
    menu3.add(item);
    menueleiste.add(menu3);
    setJMenuBar(menueleiste);

    add(panel1);     
    setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 
  }
 
  
  public class StammbaumFenster extends JFrame implements Printable{
	  JButton Personen[] = new JButton[33];	 
	  
	  JScrollPane scrollpane;
	  JPanel panel1 = new JPanel();	
	  
	  private static final long serialVersionUID = 1L;
		
		public int print( Graphics g, PageFormat pageFormat, int pageIndex ) {
			Toolkit tk = Toolkit.getDefaultToolkit();
			PrintJob pj = tk.getPrintJob(NeueCronik_stammbaum, "", null );
		
			if ( pj == null ) 
		        return Printable.NO_SUCH_PAGE;
		        
			scrollpane.printComponents( g );
		    g.dispose();
		    pj.end();
		    return Printable.PAGE_EXISTS;
		 }
  
		void addComponent( Container cont, GridBagLayout gbl,Component c,int x, int y,int width, int height,double weightx, double weighty,int typ , int schriftgroese){
			 GridBagConstraints gbc = new GridBagConstraints();
			 gbc.fill = GridBagConstraints.BOTH;
			 gbc.gridx = x; gbc.gridy = y; gbc.gridwidth = width; gbc.gridheight = height; gbc.weightx = weightx; gbc.weighty = weighty;
			 
				 if (typ==1) {
					 ((JButton) c).setMargin(new Insets(0, 0, 0, 0));				 
					 ((JButton) c).setFont(new Font("Arial", Font.PLAIN,schriftgroese));				
				 }							 
				 gbl.setConstraints(c, gbc );	
				 cont.add( c );
		 }
		
		StammbaumFenster(String titel){
			  super(titel); 	
			  class CMeinActionLauscher implements ActionListener {
			      public void actionPerformed(ActionEvent e)  {
			          String label;					  
			          label = e.getActionCommand();            
			          if (label.equals("Drucken")) {  
			        	  PrinterJob pjob = PrinterJob.getPrinterJob();
			        	    if ( pjob.printDialog() == false )
			        	      return;			        	   
			        	    try {
			        	    	pjob.setPrintable(NeueCronik_stammbaum );
								pjob.print();
							} catch (PrinterException e1) {e1.printStackTrace();}
				      }        
			      }        
			    }  
			  
			  JMenuBar menueleiste =new JMenuBar();
			  JMenu menu1 =new JMenu("Drucken");	
			  JMenuItem item = new JMenuItem("Drucken");
		      item.addActionListener(new CMeinActionLauscher());
		      menu1.add(item);		
			  menueleiste.add(menu1);
			  setJMenuBar(menueleiste);
			    
			  GridBagLayout gbl = new GridBagLayout();
			  		  			  			  	
			  panel1.setLayout(gbl);	  

			  int i=0;
	          for ( i=0;i<32;i++){  Personen[i]=new JButton("<html>Max<br> Muster</html>");}    
	          for ( i=1;i<34;i++){  addComponent( panel1, gbl, new JLabel("<--->"), i , 0, 1, 1, 0 , 0 ,0,8);}   
	          for (i=0 ;i<8 ;i++){ 
	              addComponent( panel1, gbl, Personen[i*2]   , 4*i+2 , 1+i*2, 3, 1, 0 , 0 ,1  ,9 );
	              addComponent( panel1, gbl, Personen[i*2+1] , 4*i+2 , 2+i*2, 3, 1, 0 , 0 ,1  ,9 );               
	          }     
	          scrollpane = new JScrollPane(panel1);   
	          add(scrollpane);  	  
		  }	  	
  }
}

Das meiste ist ja nur für das Erstellen des Fensters. Das Drucken ist erst im zweiten Fenster möglich. Wenn ich über one Note ausgebe muss ich min 3-4 ja klicken und dann erst paar mal auf nein damit überhaupt was angezeigt wird.
Leider konnte ich kein Beispie finden was mir helfen konnte.
 
Das Drucken unter Java ist m.M. eine Sache für sich.
Dein Code ist ja ganz schön wagemutig - um's mal vorsichtig auszudrücken.
Dass bei Dir andauernd der Druckdialog hochkommt liegt daran, dass Du in dauernd aufrufst.
Nämlich in der print(...) der Klasse StammbaumFenster - und da hat das gar nichts verloren.
Schon mal ein Tutorial dazu angeschaut?
Etwas komplizierter wird es bei mehrseitigen Ausdrucken, da muss man ein bisschen selbst rechnen.
Hier mal eine Demo - ohne Gewähr, da ich mich selbst nie wirklich mit dem Drucken auseinandergesetzt habe:
Java:
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;

import javax.swing.JComponent;

public class PrintingDemo {
	
	class PrintableComponent extends JComponent implements Printable {
		BufferedImage img;
		
		public PrintableComponent() {
			img = new BufferedImage(1300, 1000, BufferedImage.TYPE_INT_ARGB);
			Graphics2D g = img.createGraphics();
			g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
			g.setColor(Color.BLUE);
			g.setStroke(new BasicStroke(50));
			g.drawLine(0, 0, img.getWidth(), img.getHeight());
			g.setColor(Color.RED);
			g.drawLine(0, img.getHeight(), img.getWidth(), 0);
			g.setColor(Color.GREEN);
			g.drawRect(0, 0, img.getWidth(), img.getHeight());
			g.drawRect(img.getWidth()/4, img.getHeight()/4, img.getWidth()/2, img.getHeight()/2);
			g.setColor(Color.BLACK);
			g.rotate(Math.PI/6);
			g.setFont(new Font("Arial", Font.BOLD, 170));
			g.drawString("PRINTDEMO", 250, 250);
			g.dispose();
			this.setSize(img.getWidth(), img.getHeight());
		}
		
		public void paintComponent(Graphics g) {
			super.paintComponent(g);
			if(img!=null)
				g.drawImage(img, 0, 0, null);
		}
		
		public int print(Graphics g, PageFormat pf, int page)
				throws PrinterException {
			int w = (int)pf.getImageableWidth();
			int h = (int)pf.getImageableHeight();
			int maxRow = this.getHeight()/h +1;
			int maxColumn = this.getWidth()/w +1;
			int row = page%maxRow;
			int col = page/maxRow;
			
			if (page >= maxRow*maxColumn)
				return NO_SUCH_PAGE;
			
			Graphics2D g2 = (Graphics2D) g;
			g2.translate(pf.getImageableX(), pf.getImageableY());
			g2.translate(-col*w, -row*h);
			g2.setClip(col*w, row*h, w, h);
			this.paintComponent(g2);
			
			return PAGE_EXISTS;
		}
	}

	public void printDemo() {
		PrintableComponent comp = new PrintableComponent();
		PrinterJob pj = PrinterJob.getPrinterJob();
		if (pj.printDialog()) {
			try {
				pj.setPrintable(comp);
				pj.print();
			} catch (PrinterException exc) {
				System.out.println(exc);
			}
		}

	}

	public static void main(String[] s) {
		new PrintingDemo().printDemo();
	}
}
 
Erst mal vielen vielen Dank.
Dein Beispiel hat das gemacht was ich brauchte. Das mit dem Berechnen war mir in dem Umfang unbewusst. Nach dem ich den inhalt deiner Print() übernohmen und angepasst habe lief es wie geschmiert.

Lediglich zwei Dinge sind es jetzt noch.
Das mit dem Querformat, aber da werde ich heute noch mal suchen gehen.
Und dann "nur" das ungescrollte Fenster gedruckt wird. also das was nicht ohne Scollen zusehen ist wird nicht ausgedruckt.
Wie könnte man das in den Griff bekommen.

Bin garade dabei ein umfangreiches Druck tutorial dazu zulesen, wollte aber nicht deswegen das ganze Projekt zum stillstand kommen lassen.

In wie fern wagemutig? meist du damit das mit dem Drucken oder gibts beim Rest was zu optimieren, wäe für Tipps immer erfreut.

Noch mal danke
 
Zuletzt bearbeitet:
In wie fern wagemutig? meist du damit das mit dem Drucken oder gibts beim Rest was zu optimieren, wäe für Tipps immer erfreut.
Naja, es sind da so ein paar Kleinigkeiten:
- das mit dem getPrintJob in der print habe ich ja schon erläutert
- warum implementiert
Code:
StammbaumFenster
das Interface
Code:
Printable
, obwohl eigentlich doch nur ein ganz bestimmter Teil (die Komponente im Viewport der JScrollpane) daraus gedruckt werden soll.
besser eine eigene Komponente schreiben, da kommt man auch besser an die notwendigen Informationen ran.
- in
Code:
StammbaumFenster
wird des Öfteren die Instanzvariable
Code:
NeueCronik_stammbaum
aus der Klasse Chronik2 genutzt, um an die Referenz auf sich selbst zu kommen. Hier wäre
Code:
this
oder
Code:
StammbaumFenster.this
besser - zumal es zu Problemen kommen könnte, wenn
Code:
NeueCronik_stammbaum
plötzlich - aus welchen Gründen auch immer - auf ein anderes Objekt referenziert.
- bei der Darstellung des Stammbaums mit GridLayout und Buttons, würde ich mir überlegen sowas eventuell selbst zu zeichnen oder eine externe Lib einzubinden. Je nach dem wie komplex das ganze noch wird.

Noch ein Hinweis auf die Java Code Conventions: in Java ist es üblich variablenNamen mit einem kleinBuchstaben beginnen zu lassen.
 
- in
Code:
StammbaumFenster
wird des Öfteren die Instanzvariable
Code:
NeueCronik_stammbaum
aus der Klasse Chronik2 genutzt, um an die Referenz auf sich selbst zu kommen. Hier wäre
Code:
this
oder
Code:
StammbaumFenster.this
besser - zumal es zu Problemen kommen könnte, wenn
Code:
NeueCronik_stammbaum
plötzlich - aus welchen Gründen auch immer - auf ein anderes Objekt referenziert.
stimmt muss ich eindeutig noch mal bissel mehr drauf achten

- bei der Darstellung des Stammbaums mit GridLayout und Buttons, würde ich mir überlegen sowas eventuell selbst zu zeichnen oder eine externe Lib einzubinden. Je nach dem wie komplex das ganze noch wird.

ist schon sehr umfangreich, habe dir nur eine sehr kurze version gegeben
mit selber zeichnen meist du sicherlich die exakten Koordinaten angeben oder?
Noch ein Hinweis auf die Java Code Conventions: in Java ist es üblich variablenNamen mit einem kleinBuchstaben beginnen zu lassen.

ich weis, hat man mir bereits schon gesagt, aber ich fang damit erst im nächsten Projekt an, zum einen will ich nicht alles hier ändern und zum zweiten ließt sich es sich schlecht wenn ich in einem projekt zwei methoden anwende.

und die zwei Probleme die ich noch hatte, habe bs jetzt heute noch nichts zum zweiten Problem gefunden, das mit dem Querformat habe ich noch nicht gesucht
 
Habs grad so gelöst:
Java:
if (label.equals("Drucken")) {  
			        	  PrinterJob pjob = PrinterJob.getPrinterJob();
			        	  HashPrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();
			  			  aset.add(MediaSizeName.ISO_A4);
			  			  //170, 257
			  	          aset.add(new MediaPrintableArea(10, 10, 200, 290, MediaPrintableArea.MM));
			      	      aset.add(OrientationRequested.LANDSCAPE);
			  	          aset.add(PrintQuality.NORMAL);
			  	          aset.add(Chromaticity.MONOCHROME);
			  	          pjob.setPrintable(NeueCronik_stammbaum);
			        	  boolean ok = pjob.printDialog(aset);
			                if(ok) {
			                	try{pjob.print(aset);}
			                    catch(Exception ex){ex.printStackTrace();}
			                }
				      }

Damit hätte ich mein Querformat, allerdings wüsste ich gern wie viel Platz ein Drucker so als Rand braucht, da jetzt nicht mehr viel Platz da ist
Das andere Problem war, das er nicht alles gedruckt hat, ist aber nun Geschichte.
dennoch danke für deine letzte Nachricht

Edit: Das Gridbag niehmt einen aber doch dennoch einiges ab, was die Breite von Objekten angeht zb
 
Zuletzt bearbeitet:
Hallo, nochmal.
ich habe festgestellt das das Ausgedruckte immer größer ist als das Fenster auf dem Bildschirm.
Ich denke das das sicherlich an der Uaflösung liegt das ein Drucker nicht die selbe hat wie ein Bildschirm.
Könnte noch mal hierbei Hilfe gebrauchen da ich das Problem ne recht in den Griff bekomme. danke

Java:
public int print( Graphics g, PageFormat pageFormat, int pageIndex ) {
			int w = (int)pageFormat.getImageableWidth();
            int h = (int)pageFormat.getImageableHeight();
            int maxRow = this.getHeight()/h +1;
            int maxColumn = this.getWidth()/w +1;
            int row = pageIndex%maxRow;
            int col = pageIndex/maxRow;
            
            if (pageIndex >= maxRow*maxColumn)
                return NO_SUCH_PAGE;
            
            Graphics2D g2 = (Graphics2D) g;
            g2.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
            g2.translate(-col*w, -row*h);
            g2.setClip(col*w, row*h, w, h);
            panel1.printComponents(g2);
            return PAGE_EXISTS;
		 }

Java:
public void actionPerformed(ActionEvent e)  {
			          String label;					  
			          label = e.getActionCommand();            
			          if (label.equals("Drucken")) {  
			        	  PrinterJob pjob = PrinterJob.getPrinterJob();
			        	  
			        	  HashPrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();
			  			  aset.add(MediaSizeName.ISO_A4);//oben rand;rechts rand;Senkrecht;wagerecht
			  	          aset.add(new MediaPrintableArea(25, 20, 160, 257, MediaPrintableArea.MM));
			      	      aset.add(OrientationRequested.LANDSCAPE);
			  	          aset.add(PrintQuality.NORMAL);
			  	          aset.add(Chromaticity.MONOCHROME);
			  	          pjob.setPrintable(NeueCronik_stammbaum);
			        	  boolean ok = pjob.printDialog(aset);
			                if(ok) {
			                	try{pjob.print(aset);}
			                    catch(Exception ex){ex.printStackTrace();}
			                }
				      }
 
ich habe festgestellt das das Ausgedruckte immer größer ist als das Fenster auf dem Bildschirm.
Größen auf dem Bildschirm sind relativ. Auf anderen Monitoren schaut Dein Fenster auch "größer/kleiner" aus ;-)
Ich denke das das sicherlich an der Uaflösung liegt das ein Drucker nicht die selbe hat wie ein Bildschirm.
Korrekt - zumindest teilweise. Siehe:
API Doku hat gesagt.:
public double getImageableHeight()Return the height, in 1/72nds of an inch, of the imageable area of the page. This method takes into account the orientation of the page.

Returns:
the height of the page.
PageFormat (Java Platform SE 6)
Hier wir von einer Auflösung von 72 dpi ausgegangen. Dein Monitor hat vermutlich eine höhere Auflösung, dadurch erscheint das Fenster kleiner.

Wenn Du den Ausdruck kleiner haben willst musst Du skalieren.
Entweder die Größe der Komponente vor dem Drucken ändern. Oder die Komponente erst auf ein BufferedImage malen, dieses skalieren und dann Drucken.

Aber wie gesagt die Größe auf einem Monitor ist relativ und Dein Fenster schaut auf Monitoren mit einer anderen Auflösung anders aus.
 
Die Methode "scale" kann man natürlich auch benutzen. Damit wird üblicherweise der Maßstab des Grafik-Objekts so angepasst, dass die gesamte Breite des Dokuments auf eine Seite passt ("fit to width"). Der Skalierungsfaktor ist in dem Fall die verfügbare Breite geteilt durch die Dokumentbreite.

Gruß,
André
 

Zurück
Oben