I'm trying to make a Java class in which a JFrame that contains JLabels will be printed on a full A5 page (The JFrame is set to be the size of an A5 page)
in order to do so I've used this class
http://docs.oracle.com/javase/tutorial/displayCode.html?code=http://docs.oracle.com/javase/tutorial/2d/printing/examples/PrintUIWindow.java
with this class that I've written
public class test2 extends PrintUIWindow {
public test2(JFrame f) {
super(f);
// TODO Auto-generated constructor stub
}
/**
* #param args
*/
public static void main(String[] args)
{
UIManager.put("swing.boldMetal", Boolean.FALSE);
JFrame f=new JFrame ("hello");
f.setLayout(null);
f.setSize(420,595);
JLabel test=new JLabel ("issuer");
f.add(test);
test.setBounds(new Rectangle(new Point(310, 50), test.getPreferredSize()));
f.setBackground(Color.white);
f.setVisible(true);
PrintUIWindow p=new PrintUIWindow (f);
p.actionPerformed(null);
}
}
the problem is that instead of printing the whole JFrame onto the page, it prints just a part of it and the rest is off the borders of the page
what could fix this problem?
Have a look at this
I also found this:
public static class Printer implements Printable {
final Component comp;
public Printer(Component comp) {
this.comp = comp;
}
#
Override
public int print(Graphics g, PageFormat format, int page_index)
throws PrinterException {
if (page_index > 0) {
return Printable.NO_SUCH_PAGE;
}
// get the bounds of the component
Dimension dim = comp.getSize();
double cHeight = dim.getHeight();
double cWidth = dim.getWidth();
// get the bounds of the printable area
double pHeight = format.getImageableHeight();
double pWidth = format.getImageableWidth();
double pXStart = format.getImageableX();
double pYStart = format.getImageableY();
double xRatio = pWidth / cWidth;
double yRatio = pHeight / cHeight;
Graphics2D g2 = (Graphics2D) g;
g2.translate(pXStart, pYStart);
g2.scale(xRatio, yRatio);
comp.paint(g2);
return Printable.PAGE_EXISTS;
}
}
To Print the frame using Printer class try this:
JFrame yourComponent = new JFrame();
PrinterJob pjob = PrinterJob.getPrinterJob();
PageFormat preformat = pjob.defaultPage();
preformat.setOrientation(PageFormat.LANDSCAPE);
PageFormat postformat = pjob.pageDialog(preformat);
if (preformat != postformat) {
pjob.setPrintable(new Printer(yourComponent), postformat);
if (pjob.printDialog()) {
pjob.print();
}
}
Related
The program draws completely fine if the border layout is Center, but not for any other direction. Here is the code below.
public class MainVisualizer {
public static void main(String[] args) {
int windowWidth = 1000;
int windowHeight = 850;
JFrame mainFrame = new JFrame("Plotter and Integration Visualizer ");
mainFrame.setSize(windowWidth, windowHeight);
mainFrame.add(new GraphComponent(windowWidth, windowHeight), BorderLayout.EAST);
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.setVisible(true);
}
}
public class GraphComponent extends JComponent {
private ArrayList<String> textFunctions;
private int frameWidth;
private int frameHeight;
public GraphComponent(int width, int height) {
this.textFunctions = new ArrayList<>();
this.frameHeight = height;
this.frameWidth = width;
}
#Override
protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D)g;
g2.drawLine(0, frameHeight/2, frameWidth, frameHeight/2);//X axis
g2.drawLine(frameWidth/2, 0, frameWidth/2, frameHeight);//Y axis
System.out.println( this.getX()+" "+ this.getY());
g2.drawString("X", frameWidth/2, frameHeight/2);
}
}
I believe what you are seeing is because you haIven't set preferred size. The default is 0, and so that's what you get when you add not to the center
public class GraphComponent extends JComponent {
private ArrayList<String> textFunctions;
private int frameWidth;
private int frameHeight;
public GraphComponent(int width, int height) {
this.textFunctions = new ArrayList<>();
this.frameHeight = height;
this.frameWidth = width;
//Set preferredSize right here
setPreferredSize(new Dimension(width, height));
///////////////
}
#Override
protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D)g;
g2.drawLine(0, frameHeight/2, frameWidth, frameHeight/2);//X axis
g2.drawLine(frameWidth/2, 0, frameWidth/2, frameHeight);//Y axis
System.out.println( this.getX()+" "+ this.getY());
g2.drawString("X", frameWidth/2, frameHeight/2);
}
}
I'm nervous about asking this because I'm scared I'll get told off. I am trying to print a JPanel that is about 4 pages long. It could be more, the data is from a JDBC MySql query, that could end up being many more that 4. The JPanel I am trying to print is full of other JPanels (with competitors race details on them) that I have added via a ListArray..
Anyway, I have scoured all day through stackoverflow and have found may examples of code that I have tried to implement. The printable class only prints the first page, so I have tried to implement the pageable class, but I just can't seem to get it right. I have tried to implement the Book class but don't know how to add my JPanel to the book. I have looked here, here and many more (I'm only allowed to post 2 links).
Here is my current code (that I got off one of the answers that #madprogrammer gave) -
int printButton = JOptionPane.showOptionDialog(null, scrollPane, "Race Winners", JOptionPane.YES_NO_OPTION,
JOptionPane.PLAIN_MESSAGE, // no Icon
null, //do not use a custom Icon
options, //the titles of buttons
options[0]); //default button title
if (printButton == 0) {
try {
printComponent(pane, true);
//printComponentToFile(pane, false);
} catch (PrinterException exp) {
exp.printStackTrace();
}
public static void printComponent(JComponent comp, boolean fill) throws PrinterException {
PrinterJob pjob = PrinterJob.getPrinterJob();
//pjob.setPageable(comp);
PageFormat pf = pjob.defaultPage();
pf.setOrientation(PageFormat.PORTRAIT);
PageFormat postformat = pjob.pageDialog(pf);
if (pf != postformat) {
//Set print component
//pjob.setPageable(comp);
pjob.setPrintable(new ComponentPrinter(comp, fill), postformat);
if (pjob.printDialog()) {
pjob.print();
}
}
}
public static void printComponentToFile(Component comp, boolean fill) throws PrinterException {
Paper paper = new Paper();
paper.setSize(8.3 * 72, 11.7 * 72);
paper.setImageableArea(18, 18, 559, 783);
PageFormat pf = new PageFormat();
pf.setPaper(paper);
pf.setOrientation(PageFormat.PORTRAIT);
BufferedImage img = new BufferedImage(
(int) Math.round(pf.getWidth()), (int) Math.round(pf.getHeight()),
BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = img.createGraphics();
g2d.setColor(Color.WHITE);
g2d.fill(new Rectangle(0, 0, img.getWidth(), img.getHeight()));
ComponentPrinter cp = new ComponentPrinter(comp, fill);
try {
cp.print(g2d, pf, 0);
} finally {
g2d.dispose();
}
try {
ImageIO.write(img, "png", new File("Page-" + (fill ? "Filled" : "") + ".png"));
} catch (IOException ex) {
ex.printStackTrace();
}
}
public static class ComponentPrinter implements Printable, Pageable {
private Component comp;
private boolean fill;
int numPages;
PageFormat format;
public ComponentPrinter(Component comp, boolean fill) {
this.comp = comp;
this.fill = fill;
}
#Override
public int print(Graphics g, PageFormat format, int page_index) throws PrinterException {
numPages = (int) Math.ceil(comp.getHeight() / format.getImageableY());
System.out.print(numPages);
if (page_index > 0) {
return Printable.NO_SUCH_PAGE;
}
Graphics2D g2 = (Graphics2D) g;
g2.translate(format.getImageableX(), format.getImageableY());
//g2.translate(format.getImageableX(), format.getImageableY()- page_index*comp.getPreferredSize().height);
double width = (int) Math.floor(format.getImageableWidth());
double height = (int) Math.floor(format.getImageableHeight());
if (!fill) {
width = Math.min(width, comp.getPreferredSize().width);
height = Math.min(height, comp.getPreferredSize().height);
}
comp.setBounds(0, 0, (int) Math.floor(width), (int) Math.floor(height));
if (comp.getParent() == null) {
comp.addNotify();
}
comp.validate();
comp.doLayout();
comp.printAll(g2);
if (comp.getParent() != null) {
comp.removeNotify();
}
return Printable.PAGE_EXISTS;
}
#Override
public int getNumberOfPages() {
// TODO Auto-generated method stub
return numPages;
}
#Override
public PageFormat getPageFormat(int arg0) throws IndexOutOfBoundsException {
return format;
}
#Override
public Printable getPrintable(int arg0) throws IndexOutOfBoundsException {
// TODO Auto-generated method stub
return this;
}
}
This all works, but only prints the first page. I would REALLY appreciate a nudge in the right direction with this as I'm stumped. TIA :-)
This is how you print a Component (JPanel) on multiple pages:
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.print.*;
import javax.swing.RepaintManager;
public class PrintMultiPageUtil implements Printable, Pageable {
private Component componentToBePrinted;
private PageFormat format;
private int numPages;
public PrintMultiPageUtil(Component componentToBePrinted) {
this.componentToBePrinted = componentToBePrinted;
// get total space from component
Dimension totalSpace = this.componentToBePrinted.getPreferredSize();
// calculate for DIN A4
format = PrinterJob.getPrinterJob().defaultPage();
numPages = (int) Math.ceil(totalSpace .height/format.getImageableHeight());
}
public void print() {
PrinterJob printJob = PrinterJob.getPrinterJob();
// show page-dialog with default DIN A4
format = printJob.pageDialog(printJob.defaultPage());
printJob.setPrintable(this);
printJob.setPageable(this);
if (printJob.printDialog())
try {
printJob.print();
} catch(PrinterException pe) {
System.out.println("Error printing: " + pe);
}
}
public int print(Graphics g, PageFormat pageFormat, int pageIndex) {
if ((pageIndex < 0) | (pageIndex >= numPages)) {
return(NO_SUCH_PAGE);
} else {
Graphics2D g2d = (Graphics2D)g;
g2d.translate(pageFormat.getImageableX(), pageFormat.getImageableY() - pageIndex * pageFormat.getImageableHeight());
disableDoubleBuffering(componentToBePrinted);
componentToBePrinted.paint(g2d);
enableDoubleBuffering(componentToBePrinted);
return(PAGE_EXISTS);
}
}
public static void disableDoubleBuffering(Component c) {
RepaintManager currentManager = RepaintManager.currentManager(c);
currentManager.setDoubleBufferingEnabled(false);
}
public static void enableDoubleBuffering(Component c) {
RepaintManager currentManager = RepaintManager.currentManager(c);
currentManager.setDoubleBufferingEnabled(true);
}
#Override
public int getNumberOfPages() {
// TODO Auto-generated method stub
return numPages;
}
#Override
public PageFormat getPageFormat(int arg0) throws IndexOutOfBoundsException {
return format;
}
#Override
public Printable getPrintable(int arg0) throws IndexOutOfBoundsException {
// TODO Auto-generated method stub
return this;
}
}
numPages
I changed the expression for numPages to:
(int) Math.ceil(page.height/format.getImageableHeight())
This divides the total height (height of the jpanel) through the height of one page, thus calculating the number of all pages.
g2d.translate
I did the following change: In this line:
g2d.translate(pageFormat.getImageableX(), pageFormat.getImageableY() - pageIndex * pageFormat.getImageableHeight());
Changed componentToBePrinted.getPreferredSize().height to pageFormat.getImageableHeight(). A positive value for the first or the second parameter of g2d.translate moves the graphic to the right or down respectively.
.getImageableX() and .getImageableY() help position the graphic so that it doesn't overlap with the padding.
For pageIndex greater than 0, - pageIndex * pageFormat.getImageableHeight() moves the image pageIndex-times the page-height to the top. So the area, that the pageIndex refers to is printed.
original broken source:: https://community.oracle.com
Here is my original answer.
I would like to print a jframe when clicking a button.
So i tried this code. If I click the print button, I get a printer dialog and when I tell it to print, it just prints a blank document, i don't know why. Any help?
public static class Printer implements Printable {
final Component comp;
public Printer(Component comp){
this.comp = comp;
}
#Override
public int print(Graphics g, PageFormat format, int page_index)
throws PrinterException {
if (page_index > 0) {
return Printable.NO_SUCH_PAGE;
}
// get the bounds of the component
Dimension dim = comp.getSize();
double cHeight = dim.getHeight();
double cWidth = dim.getWidth();
// get the bounds of the printable area
double pHeight = format.getImageableHeight();
double pWidth = format.getImageableWidth();
double pXStart = format.getImageableX();
double pYStart = format.getImageableY();
double xRatio = pWidth / cWidth;
double yRatio = pHeight / cHeight;
Graphics2D g2 = (Graphics2D) g;
g2.translate(pXStart, pYStart);
g2.scale(xRatio, yRatio);
comp.paint(g2);
return Printable.PAGE_EXISTS;
}
}
and in the button action performed
JFrame yourComponent = new ODietListJFrame();
PrinterJob pjob = PrinterJob.getPrinterJob();
PageFormat preformat = pjob.defaultPage();
preformat.setOrientation(PageFormat.LANDSCAPE);
PageFormat postformat = pjob.pageDialog(preformat);
//If user does not hit cancel then print.
if (preformat != postformat) {
//Set print component
pjob.setPrintable(new Printer(yourComponent), postformat);
if (pjob.printDialog()) {
try {
pjob.print();
} catch (PrinterException ex) {
Logger.getLogger(ODietListJFrame.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
Thanks for help.
I'm trying to make a simle java program that draws a circle at the mouse localization, it gets the mouse X and Y coordinates but it doesn't draw anything, i tried to draw a String, a circle and a line but nothing worked, i changed the code a bit but it still doesn't works
class Test4 {
public static String a;
public static JFrame frame = new JFrame();
public static Point Gett(){
PointerInfo h = MouseInfo.getPointerInfo();
Point b = h.getLocation();
return b;
}
public void paintComponent(int x, int y, Graphics g) {
g.drawOval(x, y, 10, 10);
}
public static void main(String[] args) throws InterruptedException {
int h = 250;
int f = 200;
frame.setVisible(true);
frame.setSize(h, f);
frame.setLocationRelativeTo(null);
while(true){
Point b = Gett();
int x = (int) b.getX();
int y = (int) b.getY();
System.out.println(x);
System.out.println(y);
frame.repaint();}}}
Don't perform custom painting directly on a JFrame. Always do it on a JComponent overriding the paintComponent method if you can.
Don't use an infinite loop for this purpose. There is the MouseMotionListener for Mouse Motion listening
public class Test4 {
public static String a;
public static CustomDrawingPanel content;
public static JFrame frame = new JFrame();
final static int OVAL_WIDTH = 10;
final static int OVAL_HEIGHT = 10;
static int x = -20, y = -20;
public static MouseMotionListener listener = new ContentListener();
public static void main(String[] args) throws InterruptedException {
int h = 250;
int f = 200;
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
content = new CustomDrawingPanel();
content.addMouseMotionListener(listener);
frame.add(content);
frame.getContentPane().setPreferredSize(new Dimension(h, f));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
//class that performs custom drawing
static class CustomDrawingPanel extends JPanel {
public void paintComponent(Graphics g) {
super.paintComponent(g); //Always call this
g.drawOval(x, y, 10, 10);
}
}
//listener to the mouse motion
static class ContentListener implements MouseMotionListener {
#Override
public void mouseDragged(MouseEvent e) {
mouseMoved(e); //if you delete this line, when you drag your circle will hang
}
#Override
public void mouseMoved(MouseEvent e) {
x = e.getX() - OVAL_WIDTH / 2;
y = e.getY() - OVAL_HEIGHT / 2;
content.repaint();
}
}
}
I have a problem in my application using line primitives and JLables. I try to explain it:
I have to draw a vehicle route using lines to represent roads and JLabels to represent cities. I need the use of JLabels because each JLabel has a Listener that shows a dialog with information about the city.
I redefine paint() method of my main JPanel. In that method I first in invoke the super.paint(), then I draw the lines and finally I add the Labels to the JPanel.
The problem is that the lines overlap the labels regardless the matter the order of painting them. Is there any suggestion?
You can also override paintComponent() or paintChildren() methods of the JPanel.
In the paintChildren() call your lines drawing and then super to draw JLabels.
anothe way should be
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Ellipse2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
public class AddVertexDemo {
public AddVertexDemo() {
}
private static void createAndShowUI() {
JFrame frame = new JFrame("AddVertexDemo");
frame.getContentPane().add(new Gui().getMainPanel());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
createAndShowUI();
}
});
}
}
class DrawingPanel extends JPanel {
private static final int RADIUS = 6;
private static final long serialVersionUID = 1L;
private List<Shape> vertexList = new ArrayList<Shape>();
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
if (vertexList.size() > 1) {
Shape s0 = vertexList.get(0);
Shape s1 = null;
for (int i = 0; i < vertexList.size(); i++) {
s1 = vertexList.get(i);
drawConnectingLine(g, s0, s1);
s0 = s1;
}
s1 = vertexList.get(0);
//drawConnectingLine(g2, s0, s1);
}
for (Shape shape : vertexList) {
g2.setColor(Color.blue);
g2.fill(shape);
g2.setColor(Color.blue.darker().darker());
g2.draw(shape);
}
}
private void drawConnectingLine(Graphics g, Shape s0, Shape s1) {
Rectangle r0 = s0.getBounds();
Rectangle r1 = s1.getBounds();
int x0 = r0.x + r0.width / 2;
int y0 = r0.y + r0.height / 2;
int x1 = r1.x + r1.width / 2;
int y1 = r1.y + r1.height / 2;
g.drawLine(x0, y0, x1, y1);
}
public void addVertex(Point p) {
int x = p.x - RADIUS;
int y = p.y - RADIUS;
int w = 2 * RADIUS;
int h = w;
vertexList.add(new Ellipse2D.Double(x, y, w, h));
repaint();
}
public void removeVertex(Point p) {
if (vertexList.size() > 0) {
for (int i = vertexList.size() - 1; i >= 0; i--) {
if (vertexList.get(i).contains(p)) {
vertexList.remove(i);
repaint();
return;
}
}
}
}
}
class Gui {
private static final Dimension DRAWING_PANEL_SIZE = new Dimension(600, 500);
private JPanel mainPanel = new JPanel(new BorderLayout());
private DrawingPanel drawingPanel = new DrawingPanel();
private JToggleButton addVertexBtn = new JToggleButton("Add Vertex");
private JToggleButton removeVertexBtn = new JToggleButton("Remove Vertex");
Gui() {
JPanel buttonPanel = new JPanel();
buttonPanel.add(addVertexBtn);
buttonPanel.add(removeVertexBtn);
DrawPanelMouseListener mouseListener = new DrawPanelMouseListener();
mouseListener.setDrawingPanel(drawingPanel);
mouseListener.setGui(this);
drawingPanel.addMouseListener(mouseListener);
drawingPanel.setPreferredSize(DRAWING_PANEL_SIZE);
drawingPanel.setBorder(BorderFactory.createLineBorder(Color.black));
mainPanel.add(drawingPanel, BorderLayout.CENTER);
mainPanel.add(buttonPanel, BorderLayout.SOUTH);
}
public JPanel getMainPanel() {
return mainPanel;
}
public boolean isAddingVertex() {
return addVertexBtn.isSelected();
}
public boolean isRemovingVertex() {
return removeVertexBtn.isSelected();
}
public void setAddingVertex(boolean addingVertex) {
addVertexBtn.setSelected(addingVertex);
}
public void setRemovingVertex(boolean removingVertex) {
removeVertexBtn.setSelected(removingVertex);
}
}
class DrawPanelMouseListener extends MouseAdapter {
private DrawingPanel drawingPanel;
private Gui gui;
public DrawPanelMouseListener() {
}
public void setGui(Gui gui) {
this.gui = gui;
}
public void setDrawingPanel(DrawingPanel drawingPanel) {
this.drawingPanel = drawingPanel;
}
#Override
public void mousePressed(MouseEvent me) {
if (gui.isAddingVertex() && gui.isRemovingVertex()) {
gui.setAddingVertex(false);
gui.setRemovingVertex(false);
return;
}
if (gui.isAddingVertex()) {
drawingPanel.addVertex(me.getPoint());
gui.setAddingVertex(false);
}
if (gui.isRemovingVertex()) {
drawingPanel.removeVertex(me.getPoint());
gui.setRemovingVertex(false);
}
}
}
I'm not sure that this is the right way to do this but you can try this:
Create 2 panels. One for drawing lines and another for drawing buildings(labels).
Add both panels in LayeredPane of JFrame. Add panel with line in lower layer then panel with labels.
You can use LayeredPanes in other ways also to solve your problem. Learn more here: How to use Layered Panes in java