Announcement

Collapse
No announcement yet.

JPanel ausdrucken

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • JPanel ausdrucken

    Ich habe einen Kritzelblock entwickelt, den man nun auch ausdrucken können soll (für eine Studienarbeit).
    Mein Drucker bewegt sich schon, aber druckt nur eine leere Seite. Ich hoffe jemand findet meinen Denkfehler:

    Code:
    public class Zeichnung extends JFrame implements ActionListener, MouseMotionListener{
    	private static final long serialVersionUID = 1L;
    	private Color farbe = Color.black;
    	public static JPanel block;
    	
    	public static void main(String[] args) {
    		new Zeichnung();
    	}
    
    	private Zeichnung() {
    		setSize(400,400);
    		setDefaultCloseOperation(EXIT_ON_CLOSE);
    		Container window = getContentPane();
    		window.setLayout(new BorderLayout());
    		
    		JButton button = new JButton("Grafik drucken");
    		window.add(button, BorderLayout.SOUTH);
    		button.addActionListener(this);
    		
    		block = new DrawPanel();
    		window.add(block, BorderLayout.CENTER);
    		block.addMouseMotionListener(this);
    		block.repaint();
    		
    		setVisible(true);
    	}
    	
    	public void actionPerformed(ActionEvent e) {
    		try {
    	    	PrinterJob pj = PrinterJob.getPrinterJob();
    	    	pj.setPrintable(new TextPrintable() );
    			pj.print();
    		} catch (PrinterException e1) {
    			System.out.println("Fehler beim Drucken. " + e1.getMessage());
    		}
    
    	}
    DrawPanel erweitert JPanel nur um einige Linien.

    Code:
    import java.awt.Graphics;
    import java.awt.print.PageFormat;
    import java.awt.print.Printable;
    
     class TextPrintable implements Printable {
        public int print( Graphics g, PageFormat pageFormat, int pageIndex )
        {
        	if ( pageIndex < 1 ){
        		g = Zeichnung.block.getGraphics();
        		System.out.println("Block gedruckt");
        		return Printable.PAGE_EXISTS;
        		} else {
        			return Printable.NO_SUCH_PAGE;
        		}
      }
    }
    hier greife ich auf das DrawPanel/JPanel "block" zurück, das im Frame angezeigt wird und inzwischen evtl noch weiter bemalt wurde.
    Die Ausgabe "Block gedruckt" sehe ich wie gesagt und der Drucker bewegt sich auch.
    Sieht jemand den Fehler?

  • #2
    Wo ist die Klasse DrawPanel??

    Ursache könnte sein, dass in dieser Klasse paintComponent nicht überschrieben wurde.

    Weitere Möglichkeit ist, das der Bildschirm mit 96 DPI arbeitet und der Drucker mit einer wesentlich höheren Auflösung. Insofern müsste die Grafik angepasst werden
    Zuletzt editiert von Christian Marquardt; 16.11.2010, 19:31. Reason: Rechtschreibung
    Christian

    Comment


    • #3
      Mein DrawPanel:

      Code:
      import java.awt.Color;
      import java.awt.Graphics;
      import javax.swing.*;
      
      class DrawPanel extends JPanel {
      	private static final long serialVersionUID = 1L;
      
          protected void paintComponent( Graphics g )
          {
          super.paintComponent( g );
      	g.setColor(Color.black);
      	g.drawLine(5,50,395,50);
      	g.drawLine(5,90,395,90);
      	g.drawLine(5,130,395,130);
      	g.drawLine(5,170,395,170);
      	g.drawLine(5,210,395,210);
        }
      }
      Druckerauflösung 9600x2400 kann mein Drucker. Wie passe ich die Grafik überhaupt an?
      Kann es was ausmachen, dass der Drucker im Netzwerk hängt?

      Gibts bei Java auch so ein Fensterchen, wie es zB bei Word beim Drucken kommt?
      Zuletzt editiert von CLL; 17.11.2010, 14:42.

      Comment


      • #4
        Wie passe ich die Grafik überhaupt an?
        Hochskalieren.

        http://www.apl.jhu.edu/~hall/java/Swing-Tutorial/Swing-Tutorial-Printing.html

        Rendering Graphics on the Printer

        Gibts bei Java auch so ein Fensterchen, wie es zB bei Word beim Drucken kommt?
        Das hat nichts mit Java oder Word zu tun!Sondern wird vom Druckertreiber geliefert

        PrinterJob

        http://download.oracle.com/javase/1....rinterJob.html

        ->printDialog()
        Christian

        Comment


        • #5
          den PrintDialog hab ich jetzt drin
          Auch das Hochskalieren. Danke! Dadurch werden jetzt die vorgezeichneten Linien ausgedruckt.

          Einziger Haken:
          Sobald ich auf den Button für Drucken klicke, verschwinden die danach individuellen Krixeleien!
          Müsste ich da evtl im MouseDragged noch irgendwas abschließendes aufrufen? Oder wo könnte das dran liegen?

          mir ist im Debugger aufgefallen, dass TextPrintable 3x durchläuft, obwohl print() ja nur einmal aufgerufen wird und spätestens beim zweiten Mal Printable.NO_SUCH_PAGE zurück bekommt. "Block wird gedruckt" wird auch 2x ausgegeben (aber nur 1 Blatt kommt aus dem Drucker)

          Code:
          import java.awt.BorderLayout;
          import java.awt.Color;
          import java.awt.Container;
          import java.awt.Graphics;
          import java.awt.print.PrinterException;
          import java.awt.print.PrinterJob;
          import java.awt.event.*;
          
          import javax.swing.JButton;
          import javax.swing.JFrame;
          import javax.swing.JPanel;
          
          public class Zeichnung extends JFrame implements ActionListener, MouseMotionListener{
          	private static final long serialVersionUID = 1L;
          	private Color farbe = Color.black;
          	public static JPanel block;
          	
          	public static void main(String[] args) {
          		new Zeichnung();
          	}
          
          	private Zeichnung() {
          		setSize(400,400);
          		setDefaultCloseOperation(EXIT_ON_CLOSE);
          		Container window = getContentPane();
          		window.setLayout(new BorderLayout());
          		
          		JButton button = new JButton("Grafik drucken");
          		window.add(button, BorderLayout.SOUTH);
          		button.addActionListener(this);
          		
          		block = new DrawPanel();
          		window.add(block, BorderLayout.CENTER);
          		block.addMouseMotionListener(this);
          		block.repaint();
          		
          		setVisible(true);
          	}
          	
          	public void actionPerformed(ActionEvent e) {
          		try {
          	    	PrinterJob pj = PrinterJob.getPrinterJob();
          	    	if ( pj.printDialog() == false )
          	    	      return;
          
          	    	pj.setPrintable(new TextPrintable() );
          			pj.print();
          		} catch (PrinterException e1) {
          			System.out.println("Fehler beim Drucken. " + e1.getMessage());
          		}
          
          	}
          
          	public void mouseDragged(MouseEvent e) {
          		Graphics g = block.getGraphics();
          		int x = e.getX(), y = e.getY();
          		g.setColor(farbe);
          		g.drawLine(x,y,x,y);
          	}
          	public void mouseMoved(MouseEvent e) {
          	}
          }
          Code:
          import java.awt.Graphics;
          import java.awt.Graphics2D;
          import java.awt.print.PageFormat;
          import java.awt.print.Printable;
          
           class TextPrintable implements Printable {
              public int print( Graphics g, PageFormat pageFormat, int pageIndex )
              {
              	if ( pageIndex < 1 ){
              		//g = Zeichnung.block.getGraphics();
              		System.out.println("Block wird gedruckt");
              		
              		Graphics2D g2d = (Graphics2D)g;
                      g2d.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
                      // Turn off double buffering
                      Zeichnung.block.paint(g2d);
                      // Turn double buffering back on
                      return(PAGE_EXISTS);
          
              		} else {
              			return Printable.NO_SUCH_PAGE;
              		}
            }
          }

          Comment


          • #6
            verschwinden die danach individuellen Krixeleien!
            Müsste ich da evtl im MouseDragged noch irgendwas abschließendes aufrufen? Oder wo könnte das dran liegen?
            Da du diese nicht irgendwo speicherst, werden sie wohl immer verloren sein, wenn das Fenster neu gezeichnet wird. Also beim verschieben in den Bildschirmrand oder wenn andere Fenster das Panel verdeckt haben

            Deine individuellen Zeichnungen müssen im paintComponent der Klasse DrawPanel gezeichnet werden.

            Bei Fensterprogrammierung ist folgendes Gesetz zu beachten:

            Jedes Fenster (hier Panel) muss zu jedem Zeitpunkt selbst wissen, wie es sich mit dem aktuellen Inhalt darstellt.

            Diese Regel verletzt du, in dem du nur die neuen Striche auf dem Panel machst, dir diese jedoch nicht merkst und im paintComponent nachvollziehst. Diese Regel gilt übrigens unabhängig von der Programmiersprache. Sie gilt auch in NET. Schließlich weiss das System nur bei Standardkomponenten (Buttons, Comoboxen u.a.) wie diese darzustellen sind

            Eine Möglichkeit das einfach zu implementieren ist, nach dem Zeichnen der Linie eine Kopie des Image des Panels zu machen und diese Kopie im paintComponent in das Panel zu kopieren. Damm müssen deine "Ausgangsstriche" allerdings auch schon als Image vorliegen

            Auch ist deine Programmierung mit der Trennung des Panels von der Zeichnung (DragMouse) nicht zielführend.
            Christian

            Comment


            • #7
              Eine funktionierende Lösung in VB .NET ohne zusätzliche Klassen und onPaint-Event kann ich dir gerne geben Die habe ich bereits fertig. War wesentlich einfacher als mit Java. Da setzt man einfach ein Bild in die Picturebox und kann das von überall bemalen. Dieser Weg ist mir in Java bisher auch nicht gelungen.


              ich habe versucht deine Ratschläge umzusetzen, aber so ganz gelingt es mir noch nicht.
              public void mouseDragged(MouseEvent e) {
              x = e.getX();
              y = e.getY();
              block.repaint();
              }
              Code:
              import java.awt.Color;
              import java.awt.Graphics;
              import javax.swing.*;
              
              class DrawPanel extends JPanel {
              	int gemalt = 0;
              	private static final long serialVersionUID = 1L;
              
                  protected void paintComponent( Graphics g ) {
                  if(gemalt==1){
              		g.setColor(Zeichnung.farbe);
              		g.drawLine(Zeichnung.x, Zeichnung.y, Zeichnung.x, Zeichnung.y);
                  }
                  else {
                  super.paintComponent( g );
              	g.setColor(Color.black);
              	g.drawLine(5,50,395,50);
              	g.drawLine(5,90,395,90);
              	g.drawLine(5,130,395,130);
              	g.drawLine(5,170,395,170);
              	g.drawLine(5,210,395,210); 
              	gemalt=1;
              	}
                }
              }
              Im Debugger zeigt sich, dass paintComponent schon beim Starten des Programms 2x durchläuft - aber Linien erscheinen keine, obwohl er beim ersten Mal korrekt durch läuft!

              Das Malen danach funktioniert aber normal.

              Comment


              • #8
                Eine funktionierende Lösung in VB .NET ohne zusätzliche Klassen und onPaint-Event kann ich dir gerne geben
                Was sollte ich damit? Ich habe damit weniger Probleme...

                War wesentlich einfacher als mit Java.
                Dann programmiere in VB weiter...

                In VB übermit die PictureBox das, was du in Java noch programmieren musst -> die Änderung des Inhaltes "aufbewahren"


                ich habe versucht deine Ratschläge umzusetzen
                Irgendwie kann ich ein Image nirgends sehen....

                und

                super.paintComponent( g );


                ist entweder die erste Zeile in der Methode oder die letzte..je nachdem was man erreichen will
                Zuletzt editiert von Christian Marquardt; 18.11.2010, 18:41.
                Christian

                Comment


                • #9
                  Leider muss ich es aber in Java programmieren.

                  Irgendwie kann ich ein Image nirgends sehen....
                  Das war doch auch nicht, wozu du mir geraten hast?! Die Version hab ich wieder gelöscht, weil ich sie ebenfalls nicht hinbekommen hab.

                  Danke für den Hinweis mit super.paintComponent( g );
                  Ich weiß jetzt, dass es das alte Bild löscht. Also will ich es ja gar nicht drin haben. Leider ändert das nichts am Verhalten meiner Anwendung.

                  Im Kontruktor habe ich außerdem noch repaint() rausgeschmissen, da es dort wohl auch nicht gebraucht wird (im MouseDrag anscheinend aber schon).
                  Code:
                  		block = new DrawPanel();
                  		window.add(block, BorderLayout.CENTER);
                  		block.addMouseMotionListener(this);
                  		//block.repaint();
                  Damit das zweimalige Aufrufen von paintComponent (woher auch immer, ich hab im Debugger den Auslöser nicht finden können, anstatt dessen hat sich alles aufgehängt) nicht der Grund ist, habe ich dort auch etwas rumprobiert:
                  Code:
                      protected void paintComponent( Graphics g ) {
                      if(gemalt==2){ gemalt=1; }
                      else if(gemalt==1){
                  		g.setColor(Zeichnung.farbe);
                  		g.drawLine(Zeichnung.x, Zeichnung.y, Zeichnung.x, Zeichnung.y);
                      }
                      else {
                  	g.setColor(Color.black);
                  	g.drawLine(5,50,395,50);
                  	g.drawLine(5,90,395,90);
                  	g.drawLine(5,130,395,130);
                  	g.drawLine(5,170,395,170);
                  	g.drawLine(5,210,395,210); 
                  	gemalt=2;
                  	}
                    }
                  Aber wieder erscheinen nach dem ersten Durchlauf die Zeilen und nach dem zweiten Durchlauf sind sie wieder weg! Ich verstehe aber nicht warum! die Zeichnung müsste doch beständig sein, und löschen tue ich auch nichts!

                  Comment


                  • #10
                    Das war doch auch nicht, wozu du mir geraten hast?!
                    Nun, ich würde das so verstehen:

                    Eine Möglichkeit das einfach zu implementieren ist, nach dem Zeichnen der Linie eine Kopie des Image des Panels zu machen und diese Kopie im paintComponent in das Panel zu kopieren. Damm müssen deine "Ausgangsstriche" allerdings auch schon als Image vorliegen

                    Ich weiß jetzt, dass es das alte Bild löscht.
                    Nein, er zeichnet die Komponente. Wenn du einen bsp. einen Button dauf dem Panel hast, wird er dann gezeichnet. Der Aufruf richtet sich dann danach, ob das was du selbst zeichnest davor oder danach gezeichnet werden soll

                    Aber wieder erscheinen nach dem ersten Durchlauf die Zeilen und nach dem zweiten Durchlauf sind sie wieder weg! Ich verstehe aber nicht warum! die Zeichnung müsste doch beständig sein, und löschen tue ich auch nichts!
                    Wird wohl daran liegen, das gemalt nur beim erstenmal !=1 ist. Dann wird es auf 1 gesetzt und verbleibt offenbar so
                    Christian

                    Comment


                    • #11
                      wenn es beständig sein sollte, wenns im paintComponent() gemalt wird, dann wäre das mit dem Bild darin doch irgendwie doppelte Arbeit

                      Ich habe es gerade hinbekommen. Wenn ich das Zeichnen der Linien jedes Mal ausführe, dann funktioniert es. Finde ich zwar etwas unlogisch, dass ich die Blocklinien jedes Mal zeichnen muss, die Krixeleien aber erhalten bleiben, aber ich bin ja froh, dass es überhaupt funktioniert

                      Comment

                      Working...
                      X