Althougt我努力尽力而为,无法应对我的问题。问题是这样的:我想从我的框架中打印JComponent
,确切地说是JPanel
,但它太大了,无法以纵向或横向方式放入标准A4页面。为了完成这项工作,我在这里实现了代码Fit/Scale JComponent to page being printed,因此我的ComponentPrintable
类看起来像这样:
public class ComponentPrintable extends JPanel implements Printable {
private Component comp;
public ComponentPrintable(Component comp)
{
this.comp = comp;
}
@Override
public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException
{
if (pageIndex > 0) {
return Printable.NO_SUCH_PAGE;
}
Dimension componentSize = comp.getPreferredSize();
comp.setSize(componentSize);
Dimension printSize = new Dimension();
printSize.setSize(pageFormat.getImageableWidth(), pageFormat.getImageableHeight());
double scaleFactor = getScaleFactorToFit(componentSize, printSize);
if (scaleFactor > 1d) {
scaleFactor = 1d;
}
double scaleWidth = componentSize.width * scaleFactor;
double scaleHeight = componentSize.height * scaleFactor;
Graphics2D g2 = (Graphics2D)graphics;
double x = ((pageFormat.getImageableWidth() - scaleWidth)/2d) + pageFormat.getImageableX();
double y = ((pageFormat.getImageableHeight() - scaleHeight)/2d) + pageFormat.getImageableY();
AffineTransform at = new AffineTransform();
at.translate(x, y);
at.scale(scaleFactor, scaleFactor);
g2.transform(at);
comp.printAll(g2);
g2.dispose();
comp.revalidate();
return PAGE_EXISTS;
}
private double getScaleFactorToFit(Dimension original, Dimension toFit) {
double dScale = 1d;
if (original != null && toFit != null) {
double dScaleWidth = getScaleFactor(original.width, toFit.width);
double dScaleHeight = getScaleFactor(original.height, toFit.height);
dScale = Math.min(dScaleHeight, dScaleWidth);
}
return dScale;
}
private double getScaleFactor(int iMasterSize, int iTargetSize) {
double dScale = 1;
if (iMasterSize > iTargetSize) {
dScale = (double) iTargetSize / (double) iMasterSize;
}
else {
dScale = (double) iTargetSize / (double) iMasterSize;
}
return dScale;
}
}
现在我在IntelliJ GUI设计器中创建了两个GUI表单:MainWindow
和TmpPanel
(也是在设计器中创建的,所以它是正式的JFrame )。
这两个看起来像这样(两个XML文件在下面的链接中提供) https://www.dropbox.com/sh/lmg8xcj2cghgqzn/AADHgX6Esm30iS7r6GeVA4_0a?dl=0
Binded classes:
public class TmpPanel extends JFrame
{
private JPanel panel1;
private JPanel checkBoxPanel;
private JCheckBox fee;
private JCheckBox administration;
private JCheckBox water;
private JCheckBox booking;
private JCheckBox electricity;
private JCheckBox toilet;
private JPanel printPanel;
private JPanel dataPanel;
private JPanel generalTablePanel;
private JPanel summaryPanel;
private JLabel fakturaNr;
private JLabel CopyOriginal;
private JPanel SalePanel;
private JPanel SposobZaplatyPanel;
private JPanel NabywcaPanel;
private JPanel SprzedawcaPanel;
private JPanel servicesTablePanel;
private JPanel summaryTablePanel;
private JPanel[] panels = {panel1, checkBoxPanel, printPanel, dataPanel, generalTablePanel, summaryTablePanel, summaryPanel,
SalePanel, SposobZaplatyPanel, NabywcaPanel, SprzedawcaPanel, servicesTablePanel};
public TmpPanel()
{
for(JPanel x: panels)
{
x.repaint();
x.validate();
System.out.println(x.isValid());
}
setContentPane(panel1);
System.out.println(getContentPane().isValid());
System.out.println(printPanel.isValid());
}
public Component getPrintablePanel()
{
return printPanel;
}
}
和
public class MainWindow extends JFrame implements ActionListener
{
private JTabbedPane tabbedPane1;
private JPanel rootPanel;
private JButton printButton;
private JButton newClientButton;
private JButton removeClientButton;
public MainWindow()
{
super("Fakturowanie");
setContentPane(rootPanel);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
tabbedPane1.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
newClientButton.addActionListener(this);
removeClientButton.addActionListener(this);
printButton.addActionListener(this);
pack();
setVisible(true);
}
@Override
public void actionPerformed(ActionEvent e)
{
Object button = e.getSource();
TmpPanel tmp = new TmpPanel();
if(button == newClientButton)
{
String name = JOptionPane.showInputDialog(this, "Nazwa sprzedawcy:\n", "Nowy sprzedawca",
JOptionPane.PLAIN_MESSAGE);
if((name != null) && (name.length() > 0))
{
tabbedPane1.addTab(name, tmp.getContentPane());
pack();
}
}
if(button == removeClientButton)
{
tabbedPane1.remove(tabbedPane1.getSelectedComponent());
}
if(button == printButton)
{
System.out.println(tabbedPane1.isValid());
printComponent(tmp.getPrintablePanel());
}
}
public void printComponent(Component comp)
{
PrinterJob printerJob = PrinterJob.getPrinterJob();
PageFormat pf = printerJob.pageDialog(printerJob.defaultPage());
printerJob.setPrintable(new ComponentPrintable(comp), pf);
if(printerJob.printDialog())
{
try
{
printerJob.print();
}
catch (PrinterException e1)
{
JOptionPane.showMessageDialog(this, "Błąd drukowania", "Błąd", JOptionPane.OK_OPTION);
}
}
}
}
现在我的问题如下:我想从printPanel
打印TmpPanel
以便它适合页面。以前在printButton
听众中我有
printComponent(tabbedPane1.getSelectedComponent());
它完美无缺。但是当我输入
printComponent(tmp.getPrintablePanel());
我只获得printPanel
的背景色(我将其设为黑色以使其在空白页面上可见)。我尝试了extend JPanel, extend JFrame, add, setContentPane, getContentPane
等所有组合,但没有任何效果。我只是设法找到了这个小东西:当我输入
System.out.println(tabbedPane1.getSelectedComponent().isValid());
它返回true。当我尝试在TmpPanel
中验证或重新绘制每个组件时,isValid
方法会为每个组件返回false
。
我想这就是为什么在按下“打印”按钮后我只能看到printPanel
背景的黑色矩形。
为什么即使两个表单都是在设计器中创建的,以及如何使其工作?
答案 0 :(得分:1)
因此,正如我所看到的,问题的一部分是一些组件在它们被附加到本地对等体(或实现的窗口)之前不想呈现。
有两种选择,您只需打印已在屏幕上的实时组件即可。这是一个问题,因为ComponentPrintable
会改变组件的大小,这将影响实时组件,使用户感到有点不愉快。
第二个选项是创建组件的新实例并将其放在另一个JFrame
上。棘手的部分是让框架自我实现并创建一个本地同伴。
幸运的是,我们知道有几种方法可以做到这一点,pack
就是其中之一。
以下示例取自Using Text Components示例,因为它是一个实际复杂的组件。
当您点击打印时,它会生成此组件的新实例,将其添加到JFrame
,打包框架然后打印该组件。
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.AffineTransform;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import static java.awt.print.Printable.PAGE_EXISTS;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.io.IOException;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JEditorPane;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JTextPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.text.BadLocationException;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;
import javax.swing.text.StyledDocument;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JButton print = new JButton("Print");
print.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
TextSamplerDemo demo = new TextSamplerDemo();
JFrame test = new JFrame();
test.add(demo);
test.pack();
ComponentPrintable printable = new ComponentPrintable(demo);
PrinterJob printerJob = PrinterJob.getPrinterJob();
PageFormat pf = printerJob.pageDialog(printerJob.defaultPage());
printerJob.setPrintable(printable, pf);
if (printerJob.printDialog()) {
try {
printerJob.print();
} catch (PrinterException e1) {
JOptionPane.showMessageDialog(null, "Printing failed", "Print", JOptionPane.OK_OPTION);
}
}
}
});
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
TextSamplerDemo demo = new TextSamplerDemo();
frame.add(demo);
frame.add(print, BorderLayout.SOUTH);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class ComponentPrintable extends JPanel implements Printable {
private Component comp;
public ComponentPrintable(Component comp) {
this.comp = comp;
}
@Override
public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
if (pageIndex > 0) {
return Printable.NO_SUCH_PAGE;
}
Dimension componentSize = comp.getPreferredSize();
comp.setSize(componentSize);
Dimension printSize = new Dimension();
printSize.setSize(pageFormat.getImageableWidth(), pageFormat.getImageableHeight());
double scaleFactor = getScaleFactorToFit(componentSize, printSize);
if (scaleFactor > 1d) {
scaleFactor = 1d;
}
double scaleWidth = componentSize.width * scaleFactor;
double scaleHeight = componentSize.height * scaleFactor;
Graphics2D g2 = (Graphics2D) graphics;
double x = ((pageFormat.getImageableWidth() - scaleWidth) / 2d) + pageFormat.getImageableX();
double y = ((pageFormat.getImageableHeight() - scaleHeight) / 2d) + pageFormat.getImageableY();
AffineTransform at = new AffineTransform();
at.translate(x, y);
at.scale(scaleFactor, scaleFactor);
g2.transform(at);
comp.printAll(g2);
g2.dispose();
comp.revalidate();
return PAGE_EXISTS;
}
private double getScaleFactorToFit(Dimension original, Dimension toFit) {
double dScale = 1d;
if (original != null && toFit != null) {
double dScaleWidth = getScaleFactor(original.width, toFit.width);
double dScaleHeight = getScaleFactor(original.height, toFit.height);
dScale = Math.min(dScaleHeight, dScaleWidth);
}
return dScale;
}
private double getScaleFactor(int iMasterSize, int iTargetSize) {
double dScale = 1;
if (iMasterSize > iTargetSize) {
dScale = (double) iTargetSize / (double) iMasterSize;
} else {
dScale = (double) iTargetSize / (double) iMasterSize;
}
return dScale;
}
}
public class TextSamplerDemo extends JPanel
implements ActionListener {
private String newline = "\n";
protected static final String textFieldString = "JTextField";
protected static final String passwordFieldString = "JPasswordField";
protected static final String ftfString = "JFormattedTextField";
protected static final String buttonString = "JButton";
protected JLabel actionLabel;
public TextSamplerDemo() {
setLayout(new BorderLayout());
//Create a regular text field.
JTextField textField = new JTextField(10);
textField.setActionCommand(textFieldString);
textField.addActionListener(this);
//Create a password field.
JPasswordField passwordField = new JPasswordField(10);
passwordField.setActionCommand(passwordFieldString);
passwordField.addActionListener(this);
//Create a formatted text field.
JFormattedTextField ftf = new JFormattedTextField(
java.util.Calendar.getInstance().getTime());
ftf.setActionCommand(textFieldString);
ftf.addActionListener(this);
//Create some labels for the fields.
JLabel textFieldLabel = new JLabel(textFieldString + ": ");
textFieldLabel.setLabelFor(textField);
JLabel passwordFieldLabel = new JLabel(passwordFieldString + ": ");
passwordFieldLabel.setLabelFor(passwordField);
JLabel ftfLabel = new JLabel(ftfString + ": ");
ftfLabel.setLabelFor(ftf);
//Create a label to put messages during an action event.
actionLabel = new JLabel("Type text in a field and press Enter.");
actionLabel.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0));
//Lay out the text controls and the labels.
JPanel textControlsPane = new JPanel();
GridBagLayout gridbag = new GridBagLayout();
GridBagConstraints c = new GridBagConstraints();
textControlsPane.setLayout(gridbag);
JLabel[] labels = {textFieldLabel, passwordFieldLabel, ftfLabel};
JTextField[] textFields = {textField, passwordField, ftf};
addLabelTextRows(labels, textFields, gridbag, textControlsPane);
c.gridwidth = GridBagConstraints.REMAINDER; //last
c.anchor = GridBagConstraints.WEST;
c.weightx = 1.0;
textControlsPane.add(actionLabel, c);
textControlsPane.setBorder(
BorderFactory.createCompoundBorder(
BorderFactory.createTitledBorder("Text Fields"),
BorderFactory.createEmptyBorder(5, 5, 5, 5)));
//Create a text area.
JTextArea textArea = new JTextArea(
"This is an editable JTextArea. "
+ "A text area is a \"plain\" text component, "
+ "which means that although it can display text "
+ "in any font, all of the text is in the same font."
);
textArea.setFont(new Font("Serif", Font.ITALIC, 16));
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
JScrollPane areaScrollPane = new JScrollPane(textArea);
areaScrollPane.setVerticalScrollBarPolicy(
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
areaScrollPane.setPreferredSize(new Dimension(250, 250));
areaScrollPane.setBorder(
BorderFactory.createCompoundBorder(
BorderFactory.createCompoundBorder(
BorderFactory.createTitledBorder("Plain Text"),
BorderFactory.createEmptyBorder(5, 5, 5, 5)),
areaScrollPane.getBorder()));
//Create an editor pane.
JEditorPane editorPane = createEditorPane();
JScrollPane editorScrollPane = new JScrollPane(editorPane);
editorScrollPane.setVerticalScrollBarPolicy(
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
editorScrollPane.setPreferredSize(new Dimension(250, 145));
editorScrollPane.setMinimumSize(new Dimension(10, 10));
//Create a text pane.
JTextPane textPane = createTextPane();
JScrollPane paneScrollPane = new JScrollPane(textPane);
paneScrollPane.setVerticalScrollBarPolicy(
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
paneScrollPane.setPreferredSize(new Dimension(250, 155));
paneScrollPane.setMinimumSize(new Dimension(10, 10));
//Put the editor pane and the text pane in a split pane.
JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
editorScrollPane,
paneScrollPane);
splitPane.setOneTouchExpandable(true);
splitPane.setResizeWeight(0.5);
JPanel rightPane = new JPanel(new GridLayout(1, 0));
rightPane.add(splitPane);
rightPane.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createTitledBorder("Styled Text"),
BorderFactory.createEmptyBorder(5, 5, 5, 5)));
//Put everything together.
JPanel leftPane = new JPanel(new BorderLayout());
leftPane.add(textControlsPane,
BorderLayout.PAGE_START);
leftPane.add(areaScrollPane,
BorderLayout.CENTER);
add(leftPane, BorderLayout.LINE_START);
add(rightPane, BorderLayout.LINE_END);
}
private void addLabelTextRows(JLabel[] labels,
JTextField[] textFields,
GridBagLayout gridbag,
Container container) {
GridBagConstraints c = new GridBagConstraints();
c.anchor = GridBagConstraints.EAST;
int numLabels = labels.length;
for (int i = 0; i < numLabels; i++) {
c.gridwidth = GridBagConstraints.RELATIVE; //next-to-last
c.fill = GridBagConstraints.NONE; //reset to default
c.weightx = 0.0; //reset to default
container.add(labels[i], c);
c.gridwidth = GridBagConstraints.REMAINDER; //end row
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 1.0;
container.add(textFields[i], c);
}
}
public void actionPerformed(ActionEvent e) {
String prefix = "You typed \"";
if (textFieldString.equals(e.getActionCommand())) {
JTextField source = (JTextField) e.getSource();
actionLabel.setText(prefix + source.getText() + "\"");
} else if (passwordFieldString.equals(e.getActionCommand())) {
JPasswordField source = (JPasswordField) e.getSource();
actionLabel.setText(prefix + new String(source.getPassword())
+ "\"");
} else if (buttonString.equals(e.getActionCommand())) {
Toolkit.getDefaultToolkit().beep();
}
}
private JEditorPane createEditorPane() {
JEditorPane editorPane = new JEditorPane();
editorPane.setEditable(false);
java.net.URL helpURL = TextSamplerDemo.class.getResource(
"TextSamplerDemoHelp.html");
if (helpURL != null) {
try {
editorPane.setPage(helpURL);
} catch (IOException e) {
System.err.println("Attempted to read a bad URL: " + helpURL);
}
} else {
System.err.println("Couldn't find file: TextSampleDemoHelp.html");
}
return editorPane;
}
private JTextPane createTextPane() {
String[] initString
= {"This is an editable JTextPane, ", //regular
"another ", //italic
"styled ", //bold
"text ", //small
"component, ", //large
"which supports embedded components..." + newline,//regular
" " + newline, //button
"...and embedded icons..." + newline, //regular
" ", //icon
newline + "JTextPane is a subclass of JEditorPane that "
+ "uses a StyledEditorKit and StyledDocument, and provides "
+ "cover methods for interacting with those objects."
};
String[] initStyles
= {"regular", "italic", "bold", "small", "large",
"regular", "button", "regular", "icon",
"regular"
};
JTextPane textPane = new JTextPane();
StyledDocument doc = textPane.getStyledDocument();
addStylesToDocument(doc);
try {
for (int i = 0; i < initString.length; i++) {
doc.insertString(doc.getLength(), initString[i],
doc.getStyle(initStyles[i]));
}
} catch (BadLocationException ble) {
System.err.println("Couldn't insert initial text into text pane.");
}
return textPane;
}
protected void addStylesToDocument(StyledDocument doc) {
//Initialize some styles.
Style def = StyleContext.getDefaultStyleContext().
getStyle(StyleContext.DEFAULT_STYLE);
Style regular = doc.addStyle("regular", def);
StyleConstants.setFontFamily(def, "SansSerif");
Style s = doc.addStyle("italic", regular);
StyleConstants.setItalic(s, true);
s = doc.addStyle("bold", regular);
StyleConstants.setBold(s, true);
s = doc.addStyle("small", regular);
StyleConstants.setFontSize(s, 10);
s = doc.addStyle("large", regular);
StyleConstants.setFontSize(s, 16);
s = doc.addStyle("icon", regular);
StyleConstants.setAlignment(s, StyleConstants.ALIGN_CENTER);
ImageIcon pigIcon = createImageIcon("images/Pig.gif",
"a cute pig");
if (pigIcon != null) {
StyleConstants.setIcon(s, pigIcon);
}
s = doc.addStyle("button", regular);
StyleConstants.setAlignment(s, StyleConstants.ALIGN_CENTER);
ImageIcon soundIcon = createImageIcon("images/sound.gif",
"sound icon");
JButton button = new JButton();
if (soundIcon != null) {
button.setIcon(soundIcon);
} else {
button.setText("BEEP");
}
button.setCursor(Cursor.getDefaultCursor());
button.setMargin(new Insets(0, 0, 0, 0));
button.setActionCommand(buttonString);
button.addActionListener(this);
StyleConstants.setComponent(s, button);
}
protected ImageIcon createImageIcon(String path,
String description) {
java.net.URL imgURL = TextSamplerDemo.class.getResource(path);
if (imgURL != null) {
return new ImageIcon(imgURL, description);
} else {
System.err.println("Couldn't find file: " + path);
return null;
}
}
}
}
为了实现这一点,您需要复制面板最初包含的所有数据,否则它就会毫无意义
答案 1 :(得分:0)
我设法通过使用
modyfyingTmpPanel
构造函数来解决它
public TmpPanel()
{
setContentPane(panel1);
pack();
dispose();
}
现在isValid
已为所有组件返回true
。每次按下printButton
时,都会创建一个带有printPanel
的新的不可见JFrame,但我dispose
它会立即生成,因此没有桌面空间也不会使用额外的内存。我现在可以轻松打印
printComponent(tmp.getPrintablePanel());