晚上好,堆栈溢出,
我正在尝试在“zebra gk420t”打印机上打印 Jpanel,但是当我给它下订单时,它只打印面板的一半,如图所示。
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import javax.print.attribute.*;
import javax.print.attribute.standard.*;
import javax.swing.*;
public class PrintView extends javax.swing.JFrame {
public PrintView() {
initComponents();
}
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
jPanel3 = new javax.swing.JPanel();
barcode_img1 = new javax.swing.JLabel();
ItemNum_result1 = new javax.swing.JLabel();
ItemPriceVat_resukt1 = new javax.swing.JLabel();
barcode_lbl1 = new javax.swing.JLabel();
ItemName_result1 = new javax.swing.JLabel();
jSeparator2 = new javax.swing.JSeparator();
exDate_result1 = new javax.swing.JLabel();
jButton2 = new javax.swing.JButton();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
jPanel3.setBackground(new java.awt.Color(255, 255, 255));
jPanel3.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(51, 51, 51)));
jPanel3.setForeground(new java.awt.Color(255, 255, 255));
barcode_img1.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
barcode_img1.setText("Barcode");
ItemNum_result1.setFont(new java.awt.Font("Segoe UI", 0, 36)); // NOI18N
ItemNum_result1.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
ItemNum_result1.setText("Item Name");
ItemNum_result1.setToolTipText("");
ItemNum_result1.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
ItemPriceVat_resukt1.setFont(new java.awt.Font("Segoe UI", 1, 36)); // NOI18N
ItemPriceVat_resukt1.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
ItemPriceVat_resukt1.setText("500");
ItemPriceVat_resukt1.setToolTipText("");
barcode_lbl1.setFont(new java.awt.Font("Segoe UI", 1, 24)); // NOI18N
barcode_lbl1.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
barcode_lbl1.setText("Baarcode number");
ItemName_result1.setFont(new java.awt.Font("Segoe UI", 0, 36)); // NOI18N
ItemName_result1.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
ItemName_result1.setText("123123123");
ItemName_result1.setToolTipText("");
ItemName_result1.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
jSeparator2.setBackground(new java.awt.Color(255, 255, 255));
jSeparator2.setPreferredSize(new java.awt.Dimension(420, 10));
exDate_result1.setFont(new java.awt.Font("Segoe UI", 0, 24)); // NOI18N
exDate_result1.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
exDate_result1.setText("Expire Date:");
javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3);
jPanel3.setLayout(jPanel3Layout);
jPanel3Layout.setHorizontalGroup(
jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel3Layout.createSequentialGroup()
.addGap(538, 538, 538)
.addComponent(jSeparator2, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE))
.addGroup(jPanel3Layout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(barcode_img1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(barcode_lbl1, javax.swing.GroupLayout.DEFAULT_SIZE, 481, Short.MAX_VALUE))
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addGroup(jPanel3Layout.createSequentialGroup()
.addGap(25, 25, 25)
.addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(ItemPriceVat_resukt1, javax.swing.GroupLayout.PREFERRED_SIZE, 445, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(exDate_result1, javax.swing.GroupLayout.PREFERRED_SIZE, 451, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(jPanel3Layout.createSequentialGroup()
.addComponent(ItemNum_result1, javax.swing.GroupLayout.PREFERRED_SIZE, 197, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(ItemName_result1, javax.swing.GroupLayout.PREFERRED_SIZE, 221, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(21, 21, 21))))
.addGap(0, 0, Short.MAX_VALUE))
);
jPanel3Layout.setVerticalGroup(
jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel3Layout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(ItemNum_result1, javax.swing.GroupLayout.PREFERRED_SIZE, 42, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(ItemName_result1, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(ItemPriceVat_resukt1, javax.swing.GroupLayout.PREFERRED_SIZE, 42, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(exDate_result1, javax.swing.GroupLayout.PREFERRED_SIZE, 28, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(barcode_img1, javax.swing.GroupLayout.PREFERRED_SIZE, 102, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(barcode_lbl1, javax.swing.GroupLayout.PREFERRED_SIZE, 45, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(91, 91, 91)
.addComponent(jSeparator2, javax.swing.GroupLayout.PREFERRED_SIZE, 0, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
jButton2.setText("Print");
jButton2.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButton2ActionPerformed(evt);
}
});
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap(28, Short.MAX_VALUE)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(jButton2, javax.swing.GroupLayout.PREFERRED_SIZE, 510, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jPanel3, javax.swing.GroupLayout.PREFERRED_SIZE, 493, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(41, 41, 41))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(39, 39, 39)
.addComponent(jPanel3, javax.swing.GroupLayout.PREFERRED_SIZE, 298, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 55, Short.MAX_VALUE)
.addComponent(jButton2, javax.swing.GroupLayout.PREFERRED_SIZE, 46, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(30, 30, 30))
);
pack();
}// </editor-fold>
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
PrinterJob job = PrinterJob.getPrinterJob();
job.setPrintable(new Printable() {
@Override
public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) {
if (pageIndex > 0) {
return Printable.NO_SUCH_PAGE;
}
Graphics2D g2 = (Graphics2D) graphics;
g2.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
double scaleFactor = calculateScaleFactor(pageFormat);
g2.scale(scaleFactor, scaleFactor);
jPanel3.printAll(g2);
return Printable.PAGE_EXISTS;
}
});
boolean ok = job.printDialog();
if (ok) {
try {
PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();
aset.add(OrientationRequested.PORTRAIT);
aset.add(MediaSize.findMedia(2, 1, Size2DSyntax.INCH));
job.print(aset);
dispose();
} catch (PrinterException ex) {
JOptionPane.showMessageDialog(null, ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
}
}
}
private double calculateScaleFactor(PageFormat pageFormat) {
// Calculate the scale factor to fit the panel to the paper size
double panelWidth = jPanel3.getWidth();
double panelHeight = jPanel3.getHeight();
double paperWidth = pageFormat.getImageableWidth();
double paperHeight = pageFormat.getImageableHeight();
double scaleX = paperWidth / panelWidth;
double scaleY = paperHeight / panelHeight;
return Math.min(scaleX, scaleY);
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new PrintView().setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JLabel ItemName_result1;
private javax.swing.JLabel ItemNum_result1;
private javax.swing.JLabel ItemPriceVat_resukt1;
private javax.swing.JLabel barcode_img1;
private javax.swing.JLabel barcode_lbl1;
private javax.swing.JLabel exDate_result1;
private javax.swing.JButton jButton2;
private javax.swing.JPanel jPanel3;
private javax.swing.JSeparator jSeparator2;
// End of variables declaration
}
这就是我添加获取图像并将其显示在barcode_img.setIcon()上的方式
public void displayData(int id) {
Item item = DB_connection.getSelectedRow(id);
ItemNum_result.setText(item.getItemNumber());
ItemName_result.setText(item.getItemName());
ItemPriceVat_resukt.setText("SR: " + item.getPrice() + "");
barcode_lbl.setText(item.getBarcode());
if (item.getExpireDate() != null) {
exDate_result.setText("EX Date: " + item.getExpireDate());
} else {
exDate_result.setVisible(false);
}
if (!item.getBarcode().isEmpty() && !item.getBarcodeImagePath().isEmpty()) {
Path path = Paths.get(item.getBarcodeImagePath());
if (Files.exists(path)) {
BufferedImage myPicture;
try {
myPicture = ImageIO.read(path.toFile());
barcode_lbl.setText(item.getBarcode());
barcode_img.setIcon(getImageScaled(myPicture, barcode_img));
//barcode_img.setIcon(new ImageIcon(myPicture));
} catch (IOException ex) {
JOptionPane.showMessageDialog(null, ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
}
}
}
}
private Icon getImageScaled(BufferedImage myPicture, JLabel barcode_img1) {
Image dimg = myPicture.getScaledInstance(barcode_img1.getWidth(), barcode_img1.getHeight(), Image.SCALE_SMOOTH);
ImageIcon scaledImage = new ImageIcon(dimg);
return scaledImage;
}
这一切都有点矫枉过正,但请记住,Swing 倾向于在屏幕和渲染的 72dpi 假设上运行,这一点很重要,否则它真的会让您感到困惑。
在某些情况下,您可能需要升级这些值以支持 300dpi(假设您的打印机能够做到这一点),但是,这完全是另一个问题。还要记住,自从我需要这样做以来已经很长一段时间了,并且通常会使用 JasperReports 之类的东西来代替。
让我们从解耦开始。您想要打印的信息应该由某种模型表示,这允许您将数据与输出(即屏幕或打印机)解耦。这还意味着您可以沿着轨道更改这些渲染管道,而不会对其他工作流程产生不利影响。
public interface ItemModel {
public String getName();
public String getNumber();
public double getPrice(); // Realsitically probably should be a long
public LocalDate getExpireDate();
public String getBarCodeValue();
}
public class DefaultItemModel implements ItemModel {
private String name;
private String number;
private double price;
private LocalDate expireDate;
private String barCodeValue;
public DefaultItemModel(String name, String number, double price, LocalDate expireDate, String barCodeValue) {
this.name = name;
this.number = number;
this.price = price;
this.expireDate = expireDate;
this.barCodeValue = barCodeValue;
}
public String getName() {
return name;
}
public String getNumber() {
return number;
}
public double getPrice() {
return price;
}
public LocalDate getExpireDate() {
return expireDate;
}
public String getBarCodeValue() {
return barCodeValue;
}
}
一个通用实用程序,主要用于根据所需的 DPI 从英寸转换为像素。
public class PrintUtilities {
// The number of CMs per Inch
public static final double CM_PER_INCH = 0.393700787d;
// The number of Inches per CMs
public static final double INCH_PER_CM = 2.545d;
// The number of Inches per mm's
public static final double INCH_PER_MM = 25.45d;
/**
* Converts the given pixels to cm's based on the supplied DPI
*
* @param pixels
* @param dpi
* @return
*/
public static double pixelsToCms(double pixels, double dpi) {
return inchesToCms(pixels / dpi);
}
/**
* Converts the given cm's to pixels based on the supplied DPI
*
* @param cms
* @param dpi
* @return
*/
public static double cmsToPixel(double cms, double dpi) {
return cmToInches(cms) * dpi;
}
public static double inchesToPixels(double inches, double dpi) {
return inches * dpi;
}
/**
* Converts the given cm's to inches
*
* @param cms
* @return
*/
public static double cmToInches(double cms) {
return cms * CM_PER_INCH;
}
/**
* Converts the given inches to cm's
*
* @param inch
* @return
*/
public static double inchesToCms(double inch) {
return inch * INCH_PER_CM;
}
}
项目视图...
public class ItemView extends JPanel {
private ItemModel itemModel;
private JLabel itemName;
private JLabel itemNumber;
private JLabel price;
private JLabel expireDate;
private JLabel barCode;
private JLabel barCodeNumber;
protected static final double ratio = 0.6;
public ItemView(ItemModel itemModel) throws IOException {
this.itemModel = itemModel;
setBackground(Color.WHITE);
Font font36 = new Font("Segoe UI", 0, 36);
Font font24 = new Font("Segoe UI", Font.BOLD, 24);
itemName = new JLabel(itemModel.getName());
itemName.setFont(font36);
itemNumber = new JLabel(itemModel.getNumber());
itemNumber.setFont(font36);
price = new JLabel(NumberFormat.getCurrencyInstance().format(itemModel.getPrice()));
price.setFont(font36);
expireDate = new JLabel(DateTimeFormatter.ISO_LOCAL_DATE.format(itemModel.getExpireDate()));
expireDate.setFont(font24);
// Generate the bar code image
barCode = new JLabel(new ImageIcon(generateBarCode(itemModel.getBarCodeValue())));
barCodeNumber = new JLabel(itemModel.getBarCodeValue());
barCodeNumber.setFont(font24);
barCodeNumber.setHorizontalAlignment(JLabel.LEADING);
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(4, 4, 4, 4);
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weightx = 0.5;
add(itemName, gbc);
gbc.gridx++;
add(itemNumber, gbc);
gbc.gridy++;
gbc.gridx = 0;
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.weightx = 1;
add(price, gbc);
gbc.gridy++;
add(expireDate, gbc);
gbc.gridy++;
gbc.weighty = 1;
add(barCode, gbc);
gbc.gridy++;
gbc.weighty = 0;
gbc.anchor = GridBagConstraints.LINE_START;
add(barCodeNumber, gbc);
}
protected static BufferedImage generateBarCode(String barcodeValue) throws IOException {
// Generate your bar code image
return ImageIO.read(ItemView.class.getResource("/resources/images/BarCode.png"));
}
@Override
public Dimension getPreferredSize() {
return new Dimension(
(int) PrintUtilities.inchesToPixels(6, 72),
(int) PrintUtilities.inchesToPixels(4, 72)
);
}
}
这是用于表示模型的视图。创建它然后尝试解耦现有代码要简单得多。附带说明一下,不要再依赖表单编辑器,它们对您没有帮助。
Printable
...出于多种原因,我将
Printable
从视图中分离出来。您确实不想打印屏幕上的组件,因为您需要更改它们的尺寸和位置进行打印,当组件在屏幕上显示时,这可能会产生不利的问题,并且它还表明了以下可能性:打印时使用不同的渲染方法。
public class PrinterAction implements Printable {
private ItemView itemView;
public PrinterAction(ItemModel itemModel) throws IOException {
this.itemView = new ItemView(itemModel);
}
@Override
public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) {
if (pageIndex > 0) {
return Printable.NO_SUCH_PAGE;
}
double targetWidth = pageFormat.getImageableWidth();
double targetHeight = pageFormat.getImageableHeight();
Graphics2D g2 = (Graphics2D) graphics;
g2.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
itemView.setSize((int) targetWidth, (int) targetHeight);
itemView.doLayout();
itemView.printAll(g2);
g2.setColor(Color.RED);
g2.drawRect(0, 0, (int)targetWidth - 1, (int)targetHeight - 1);
return Printable.PAGE_EXISTS;
}
}
这是一个简单的组件,向用户显示项目视图和打印操作。我修改了您的原始代码,以便能够在 Mac 上使用 PDF 渲染,因此您可以尝试一下,看看它是否按原样工作,然后也测试您的工作流程。
public class PrintView extends JPanel {
private ItemModel itemModel;
public PrintView(ItemModel itemModel) throws IOException {
this.itemModel = itemModel;
setLayout(new BorderLayout());
add(new ItemView(itemModel));
JButton print = new JButton("Print");
print.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
try {
// I've set up the Paper and PageFormat ahead of time
// as it's the only way I can get PDF rendering to work
// I'm assuming that's a 4"x6" varient, but you're
// printing in landscape - these are all assumptions
// based on some Googling.
// You may not need to do this, but it's the only way
// I was able to get PDF printing to work.
Paper paper = new Paper();
paper.setImageableArea(
0,
0,
PrintUtilities.inchesToPixels(4, 72),
PrintUtilities.inchesToPixels(6, 72)
);
PageFormat pf = new PageFormat();
pf.setPaper(paper);
pf.setOrientation(PageFormat.LANDSCAPE);
PrinterJob job = PrinterJob.getPrinterJob();
job.setPrintable(new PrinterAction(itemModel), pf);
// job.setPrintable(new PrinterAction(itemModel));
boolean ok = job.printDialog();
if (ok) {
// try {
// PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();
// aset.add(OrientationRequested.PORTRAIT);
// aset.add(MediaSize.findMedia(6, 4, Size2DSyntax.INCH));
// job.print(aset);
// } catch (PrinterException ex) {
// JOptionPane.showMessageDialog(null, ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
// }
try {
job.print();
} catch (PrinterException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
}
} catch (IOException ex) {
ex.printStackTrace();
JOptionPane.showMessageDialog(PrintView.this, "Failed to start print job", "Error", JOptionPane.ERROR_MESSAGE);
}
}
});
add(print, BorderLayout.SOUTH);
}
}
仅供参考,“打印”图像为 5.94"x3.93" / 1782x1179 像素 @ 300dpi
左边是屏幕,右边是“打印机”输出(我直接打印成PDF保存在纸上)。