Printing from swing on Mac & Windows - Where is postscript support? - java

I'm printing a complicated swing application UI to a physical printer via an Airport. I've got Mac & windows machines both printing to the same printer. Printing from the Mac looks great. Printing from windows looks far from great - everything is very pixelated, including fonts and graph lines.
Some digging around reveals that the available PrintServices are different for the different platforms.
DocFlavor flavor = DocFlavor.INPUT_STREAM.POSTSCRIPT;
PrintRequestAttributeSet attrs = new HashPrintRequestAttributeSet();
PrintServiceLookup.lookupPrintServices(flavor, attrs);
When executed from the mac, the above returns a single-element array. From windows, it returns an empty array. This leads me to believe that windows is sending a 72 DPI image to the printer, instead of postscript data.
Is this a difference in the mac & windows JVM implementations? Is there any workaround to get printing on Windows working? I realize I could generate my own 350dpi rasterized image and send that to the printer, but these things go into the hundreds of pages, I really would like to avoid that route if possible.

Think I got an answer: The java.awt.printerjob system property was set to sun.awt.windows.WPrinterJob. Apparently this is a handy PrinterJob subclass if you like blocky pixelated output on your printer. Instead, I get an instance of sun.print.PSPrinterJob if it's available, like so:
PrinterJob printerJob = null;
try {
if (System.getProperty("java.awt.printerjob").equals("sun.awt.windows.WPrinterJob")) {
// WPrinterJob sends crappy GIF images to the printer, and everything looks all blocky
// try to get an instance of a PSPrinterJob instead
printerJob = (PrinterJob) Class.forName("sun.print.PSPrinterJob").newInstance();
}
} catch (Throwable e1) {
log.log(Level.SEVERE, "Could not instaniate sun.print.PSPrinterJob", e1);
}
if (printerJob == null) {
printerJob = PrinterJob.getPrinterJob();
}

Related

java PrinterDialog seemingly fails on Windows while working on Mac

I am writing a small java app to control the order process for a friend.
I am using the PrinterDialog construct to call the system printers and it seems to work pretty well on my Mac under development. However when I try the same code on a Windows machine the code will not open the system printer dialogue. There is no obvious "code failure", just nothing happens. I have tried copying the Jar file to windows and also re-compiling the project on NetBeans within Windows and neither seems to make any difference. There was a thread similar to this a year or two back but the writer seemed to imply simply re-building the project on a Windows machine had solved the problem when, for me, it seems to make no difference.
Any comments or pointers to get the app to work on Windows would be gratefully received.
The code in question is:-
private void actionPrint(ActionEvent event) {
try {
Stage printStage = new Stage();
FXMLLoader ploader = new FXMLLoader(getClass().getResource("OrderDocument.fxml"));
Node orderNode = (Node) ploader.load();
Group printerNode = new Group();
printerNode.getChildren().add(orderNode);
Scene printScene = new Scene(printerNode, 620, 875);
printStage.setScene(printScene);
Printer printer = Printer.getDefaultPrinter();
PageLayout pageLayout = printer.createPageLayout(Paper.A4, PageOrientation.PORTRAIT, Printer.MarginType.HARDWARE_MINIMUM);
PrinterJob job = PrinterJob.createPrinterJob();
job.showPrintDialog(printStage);
if (job != null) {
boolean success = job.printPage(pageLayout,printerNode);
if (success) {
job.endJob();
}
}
} catch (IOException ex) {
Logger.getLogger(OrderCreateController.class.getName()).log(Level.SEVERE, null, ex);
}
}
The line calling "showPrintDialog" has as its owner the stage on which I built the order document.
However re-reading the usage of "showPrintDialog" I now think it should refer to my main stage and when I effected this change the code worked on both Windows and Mac.
I am a little puzzled as to why the above code did work on Mac in the first place and this rather blinded me to finding it as a solution on Windows, so if anyone has any thoughts on that I will leave this open for a few days.

Simple printing in Java

I'm working on some invoice software. So far, I managed to create an excel file (XLSX) with all the info I need (customer info, VAT, pricing etc.)
Now, I want to save this file to PDF so that it can be mailed directly to the customer. Seems kinda hard in Java. To make it easier, I just want to print my source file using the Windows Printing Dialog, and then select a PDF printer.
This little piece of code works, but it starts the printing job immediately using the default printer, without showing any dialog whatsoever. Not what I want.
desktop.print(new File("Docfile.pdf"));
This piece of code displays the printing dialog, but it's not clear to me (looking at the documentation) how I can tell a PrintJob to print a File or FileInputStream...
PrinterJob pj = PrinterJob.getPrinterJob();
pj.print();
Either the first code should display the dialog box, or the second one should give me the ability to select a file. Can't seem to fix it. Anyone got any ideas?
Start by taking a look at the Printing Trail and in particular Using Print Setup Dialogs
From the linked tutorials....
PrinterJob pj = PrinterJob.getPrinterJob();
...
if (pj.printDialog()) {
try {pj.print();}
catch (PrinterException exc) {
System.out.println(exc);
}
}
...

Java Clipboard on Linux (text only), some programs can read it, others can't, why

When my Java-based application (not a browser-based applet) copies plain text to the system clipboard on Linux, many programs are not able to access the clipboard data, but some are.
Here's the simplest test I could make:
import java.awt.datatransfer.*;
import java.awt.Toolkit;
import java.io.*;
public final class PasteTest {
public static void main (String... args) {
String mytext = "This is a test message, testing, 1, 2, 3....";
StringSelection sel = new StringSelection(mytext);
Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();
clip.setContents(sel, null);
try {
Thread.sleep(1000);
} catch (Exception e) {
}
}
}
While this program is running, File > Paste in OpenOffice (LibreOffice 3.5.7.2) is able to access the text it placed on the system clipboard. But using File > Paste in Gnome Terminal, Mozilla Thunderbird & Firefox, and many other programs can not. The Paste option is gray, as if the clipboard is empty.
How can I make my Java program publish plain text to the system clipboard on Linux (testing on Ubuntu 12.04) so all programs can access it?
Your code is fine. Its problem is that it terminates too soon.
Under X window system, the process that puts something on 'clipboard' (that is, the selection named 'clipboard') must stay alive for the copied data to survive. (Read about active and passive buffers, and notice that selections are of the active kind).
While your process runs, that is, sleep()s, you can paste the data anywhere. Once it terminates, clipboard goes empty.
This is not special behavior of Java; you can easily reproduce it with charmap or any other program you don't mind closing.
I don't know how LibreOffice scored a point in your test. Possibly it was first on your alt+tab list. In my tests, LibreOffice behaved like any other app: 'paste' worked as long as the Java process was alive, and stopped working as the process terminated.
I don't know how to fix it in general case. Running a clipboard manager (that remembers multiple copied items and thus probably owns all of them) might help.

How to convert english font to telugu font in desktop application using swings

Recently I have developed a desktop application "hotel management system" using Swing and that's working great!
But now the newest requirement is that the application should be in telugu font! That means the GUI of the application should be in telugu and the bills and the reports and everything in the application should be in telugu...
So my question is, is this possible? If so, then what technology should be used along with swings to make that happen?
If anything new should be applied along with the Swing then I'm keen to learn it and use it in my application!
Please help me out. I don't know how this can be done.
Changing the default font isn't particularly difficult, so long as you are prepared.
Take a look at Custom Fonts for Jasper Reports on how to bundle your fonts with Jasper Reports. It would also be advisable to check with the offical docs and forums for more up-to-date info.
There are plenty of examples on the web, simply do a Google for "Jasper Reports custom fonts"
Setting the required font for Swing isn't difficult, but a lot will come down to how the look and feel you use stores it's properties.
Now depending on whether the font is installed on the system or if you are supplying the font as an embedded resource, you may or may not need to do the following.
If you're not relying on the font been installed on the system, but are providing it yourself, then you need to load it.
// Load the font, for example "Telugu.ttf"
String fName = "/fonts/" + name;
InputStream is = null;
try {
InputStream is = DemoFonts.class.getResourceAsStream(fName);
font = Font.createFont(Font.TRUETYPE_FONT, is);
} finally {
try {
is.close();
} catch (Exception exp) {
}
}
Otherwise you should be able to simply create Font object using the requied Telugu font family name.
Next you want to change the default fonts used by the current look and feel to that which you want to use. This must be AFTER you install the look and feel and BEFORE you create ANY UI elements.
Object[] keys = keySet.toArray(new Object[keySet.size()]);
for (Object key : keys) {
if (key != null && key.toString().toLowerCase().contains("font")) {
Object oValue = UIManager.getDefaults().get(key);
if (oValue != null) {
String value = oValue == null ? null : UIManager.getDefaults().get(key).toString();
UIManager.put(key, font);
}
}
}
Now, you need to be aware that Swing tends to use fixed width fonts by default in it's look and feels, changing the font to a variable width font WILL change your layouts.
It is also possible without using fonts. Use Telugu Unicode to display telugu language and even for JASPER reports. I developed English to Telugu Transliterator using telugu unicode without using any font system. Just configure all label names in telugu, kannada, hindi and load with transliterator.

How to give focus to default program of shell-opened file, from Java?

From within Java, I am opening an Excel file with the default file handler (MS Excel, in this case :-) ) using the method described in this stackoverflow question:
Desktop dt = Desktop.getDesktop();
dt.open(new File(filename));
However, the Excel program doesn't get the focus. Is there any easy way to do so?
Edit: There is a related stackoverflow question for C#, but I didn't find any similar Java method.
Edit 2: I've did some simple tests, and discovered that Excel starts and gets the focus whenever no instance of Excel is running. When Excel is already open en NOT minimized, the application doesn't get the focus. If instead the Excel Windows was minimized, the above code will trigger a maximization of the window and Excel getting the focus (or vice versa :-) ).
If you only care about Windows (implied in the question), you can change the way you invoke Excel: use "cmd start...".
I have been using this piece of code to launch Windows applications for some time now. Works every time. It relies on the file association in Windows to find the application. The launched application becomes the focused window on the desktop.
In your case, Excel should be associated with .xls, .csv and other typical extensions. If it is, Windows will launch Excel, passing your file to it.
Usage:
MyUtilClass.startApplication( "c:\\mydir\\myfile.csv", "my window title" );
file is the full path to the input file for Excel and title is the window title (the application may or may not take it - Excel changes the window title).
public static void startApplication( String file, String title )
{
try
{
Runtime.getRuntime().exec( new String[] { "cmd", "/c", "start", title, file } );
}
catch( Exception e )
{
System.out.println( e.getMessage() );
}
}
From a scala-program, which runs in the JVM too, I can open an application, and that get's the focus by default. (Tested with xUbuntu, which is a kind of Linux).
import java.awt.Desktop
val dt = Desktop.getDesktop ();
dt.open (new java.io.File ("euler166.svg"));
I can't say, whether this is specific for Linux, or maybe something else - however starting Inkscape in my example, excel in yours, may take a few seconds, while the user impatiently clicks in the javaprogram again, thereby claiming the cursor back. Did you check for that?
You could then change to the last application, at least on Linux and Windows with ALT-Tab aka Meta-Tab (again shown in scala code, which you can easily transform to javacode, I'm sure):
import java.awt.Robot
import java.awt.event._
val rob = new Robot ()
rob.keyPress (KeyEvent.VK_META)
rob.keyPress (KeyEvent.VK_TAB)
rob.keyRelease (KeyEvent.VK_TAB)
rob.keyRelease (KeyEvent.VK_META)
but unfortunately the unknown source off more trouble, also known as user, might do nothing, so switching would be the false thing to do. Maybe with a thread, which checks for a certain amount of time, whether the java-program has the focus, but it keeps a form of roulette, in an interactional environment, because the user may have a fast or slow machine, or change to a third application meanwhile, and so on. Maybe a hint before triggering the new app is the best you can do?

Categories

Resources