Подтвердить что ты не робот

Печать с атрибутами (управление лотком, дуплекс и т.д.) С использованием библиотеки javax.print

Я пытался какое-то время определить способ использования стандартной стандартной библиотеки Java Print для печати файлов - в частности, документов PDF - с помощью определенных атрибутов - в частности, в определенные лотки или с использованием дуплекса.

Существует много документации о том, как это должно быть сделано, и действительно, я исследовал и пробовал эти методы. Типичный способ заключается в следующем:

public static void main (String [] args) {
    try {

        PrintService[] pservices = PrintServiceLookup.lookupPrintServices(null, null);

        //Acquire Printer
        PrintService printer = null;
        for (PrintService serv: pservices) {
            System.out.println(serv.toString());
            if (serv.getName().equals("PRINTER_NAME_BLAH")) {
                printer = serv;
            }
        }

        if (printer != null) {
            System.out.println("Found!");


            //Open File
            FileInputStream fis = new FileInputStream("FILENAME_BLAH_BLAH.pdf");

            //Create Doc out of file, autosense filetype
            Doc pdfDoc = new SimpleDoc(fis, DocFlavor.INPUT_STREAM.AUTOSENSE, null);

            //Create job for printer
            DocPrintJob printJob = printer.createPrintJob();

            //Create AttributeSet
            PrintRequestAttributeSet pset = new HashPrintRequestAttributeSet();

            //Add MediaTray to AttributeSet
            pset.add(MediaTray.TOP);

            //Add Duplex Option to AttributeSet
            pset.add(Sides.DUPLEX);

            //Print using Doc and Attributes
            printJob.print(pdfDoc, pset);

            //Close File
            fis.close();

        }

    }
    catch (Throwable t) {
        t.printStackTrace();
    }
}

Короче говоря, вы делаете следующее

  • Поиск принтера
  • Создайте PrinterJob
  • Создать атрибутный набор
  • Добавить атрибуты в AttributeSet, такие как Tray и Duplex
  • Вызов печати на задании принтера с помощью параметра AttributeSet

Проблема заключается в том, что, несмотря на то, что это документированный способ сделать это, а также то, что я нашел из нескольких учебников, этот метод... не работает. Теперь имейте в виду, я знаю, что это не звучит очень условно, но выслушайте меня. Я не говорю, что слегка...

Официальная документация для PrinterJob фактически упоминает, что AttributeSet игнорируется в реализации по умолчанию. Исходный код, показанный здесь, показывает, что это правда - атрибуты переданы и полностью игнорируются.

Похоже, вам нужна какая-то расширенная версия класса, которая, возможно, основана на конкретных принтерах и их возможностях? Я попытался написать некоторый тестовый код, который бы сказал мне такие возможности - у нас есть большое количество принтеров, созданных в офисе, больших или малых, простых или полных колоколов и свистков - не говоря уже о нескольких драйверах на моем компьютере только для псевдо -принтеры, которые просто создают документы и имитируют принтеры, не переходя на какое-либо оборудование. Код проверки выглядит следующим образом:

public static void main (String [] args) {

    PrintService[] pservices = PrintServiceLookup.lookupPrintServices(null, null);

    for (PrintService serv: pservices) {
        System.out.println(serv.toString());

        printFunctionality(serv, "Trays", MediaTray.class);
        printFunctionality(serv, "Copies", Copies.class);
        printFunctionality(serv, "Print Quality", PrintQuality.class);
        printFunctionality(serv, "Color", ColorSupported.class);
        printFunctionality(serv, "Media Size", MediaSize.class);
        printFunctionality(serv, "Accepting Jobs", PrinterIsAcceptingJobs.class);
    }
}

private static void printFunctionality(PrintService serv, String attrName, Class<? extends Attribute> attr) {
    boolean isSupported = serv.isAttributeCategorySupported(attr);
    System.out.println("    " + attrName + ": " + (isSupported ? "Y" : "N"));
}

Я обнаружил, что все принтеры, без исключения, вернули, что "копии" были поддержаны, а все остальные атрибуты не были. Кроме того, все возможности принтера были идентичны, независимо от того, насколько невероятно это выглядело.

Неизбежный вопрос - многоуровневый: как отправлять атрибуты таким образом, чтобы они регистрировались? Кроме того, как правильно определить возможности принтера? Действительно, действительно ли класс PrinterJob расширился в удобном для использования образом или всегда игнорируются атрибуты?

Примеры, которые я нашел повсюду В Интернете, кажется, предлагают мне, что ответ на последний вопрос: "Нет, они всегда игнорируются", что кажется мне смешным (но все более правдоподобным, поскольку я просеиваю сотни страниц). Является ли этот код, который Sun просто настроил, но никогда не работал в состоянии завершен? Если да, есть альтернативы?

4b9b3361

Ответ 1

Итак, мы неизбежно нашли способ печати в разные лотки и с разными настройками, но не напрямую. Мы не смогли отправить атрибуты с помощью метода printJob.print, и это многое не изменилось. Однако нам удалось установить имя задания печати, затем перехватить задание печати с помощью низкоуровневого Perl script, проанализировать имя и установить параметры лотка и дуплекса. Это экстремальный взлом, но он работает. По-прежнему остается верным, что Атрибуты принтера Java не работают, и вам нужно найти другой способ, если вы хотите их установить.

Ответ 2

Проблема заключается в том, что API печати Java является мостом между мирами. Производители принтеров не выпускают драйверы для JVM. Они выпускают драйверы для Windows, Macintosh и, возможно, у кого-то есть драйвер для данного принтера, который работает на одной или нескольких платформах * nix.

Наряду с некоторыми Java-кодом, запущенными внутри JVM на некоторой хост-системе. Когда вы начинаете запрашивать функции принтера, вы не разговариваете с принтерами - вы говорите с классом моста в java.awt.print, который подключается к JVM, который подключается к операционной системе хоста, которая подключается к любой конкретной драйвер был установлен для данного принтера. Таким образом, есть несколько мест, где это может развалиться... Конкретный JVM, на котором вы находитесь, может или не может полностью реализовать API для запроса функций принтера, не говоря уже о передаче этих параметров для заданного задания.

Несколько предложений:

  • загляните в классы javax.print в качестве альтернативы java.awt.print - У меня было больше удачной печати оттуда.
  • попробуйте использовать альтернативные драйверы печати для ваших принтеров - вы можете определить несколько именованных соединений с данным принтером, каждый с другим Водитель. Если у вас есть драйвер, предоставленный производителем, попробуйте более общий драйвер, если у вас есть общий драйвер, попробуйте установить более конкретный.
  • запустите свой код под альтернативными реализациями JVM для вашей платформы.

Ответ 3

У нас было аналогичное требование для печати PDF файла и вы хотели отправить некоторые страницы в специальный лоток, а также хотели, чтобы документ был сшито. Мы использовали комбинацию Java code + ghost script Сначала конвертируйте PDF в призрак script, а затем добавьте команды PJL (язык задания печати) в файл призрака script, чтобы выбрать лотки и скопировать документы. Затем отправьте отредактированный файл призрака script на принтер.

Вот полный пример, написанный на Java

http://reddymails.blogspot.com/2014/07/how-to-print-documents-using-java-how.html

-RAM

Ответ 4

Здесь, как это выглядит в javafx Tray, может отличаться, и он также распечатает все доступные лотки, просто изменив имя лотка

private void printImage(Node node) {
    PrinterJob job = PrinterJob.createPrinterJob();
    if (job != null) {
        JobSettings js = job.getJobSettings();
        PaperSource papersource = js.getPaperSource();
        System.out.println("PaperSource=" + papersource);
        PrinterAttributes pa = printer.getPrinterAttributes();
        Set<PaperSource> s = pa.getSupportedPaperSources();
        System.out.println("# of papersources=" + s.size());
        if (s != null) {
            for (PaperSource newPaperSource : s) {
                System.out.println("newpapersource= " + newPaperSource);
                //Here is where you would put the tray name that is appropriate
                //in the contains section
                if(newPaperSource.toString().contains("Tray 2"))
                    js.setPaperSource(newPaperSource);
            }
        }
        job.getJobSettings().setJobName("Whatever");
        ObjectProperty<PaperSource> sources = job.getJobSettings().paperSourceProperty();
        System.out.println(sources.toString());
        boolean success = job.printPage(node);
        if (success) {
            System.out.println("PRINTING FINISHED");
            job.endJob();
            //Stage mainStage = (Stage) root.getScene().getWindow();
            //mainStage.close();
        }
    }
}

Здесь мой вывод:

PaperSource=Paper source : Automatic
# of papersources=6
newpapersource= Paper source :
newpapersource= Paper source :  Manual Feed in Tray 1
newpapersource= Paper source :  Printer auto select
newpapersource= Paper source :  Tray 1
newpapersource= Paper source :  Tray 2
newpapersource= Paper source : Form-Source
ObjectProperty [bean:  Collation = UNCOLLATED
 Copies = 1
 Sides = ONE_SIDED
 JobName = Whatever
 Page ranges = null
 Print color = COLOR
 Print quality = NORMAL
 Print resolution = Feed res=600dpi. Cross Feed res=600dpi.
 Paper source = Paper source :  Tray 2
 Page layout = Paper=Paper: Letter size=8.5x11.0 INCH Orient=PORTRAIT leftMargin=54.0 rightMargin=54.0 topMargin=54.0 bottomMargin=54.0, name: paperSource, value: Paper source :  Tray 2]
PRINTING FINISHED

Ответ 5

Я обнаружил, что хитрость для лотков принтера состоит в том, чтобы перебирать Media.class с помощью getSupportedAttributeValues(...), сопоставлять удобочитаемое имя и выбирать это конкретное значение. Протестировано на Windows, MacOS с несколькими конфигурациями лотка.

String tray = "1";

// Handle human-readable names, see PRINTER_TRAY_ALIASES usage below for context.  Adjust as needed.
List<String> PRINTER_TRAY_ALIASES = Arrays.asList("", "Tray ", "Paper Cassette ");

// Get default printer
PrintService printService = PrintServiceLookup.lookupDefaultPrintService();

// Attributes to be provided at print time
PrintRequestAttributeSet pset = new HashPrintRequestAttributeSet();

Media[] supported = printService.getSupportedAttributeValues(Media.class, null, null);
for(Media m : supported) {           
    for(String pta : PRINTER_TRAY_ALIASES) {
        // Matches "1", "Tray 1", or "Paper Cassette 1"
        if (m.toString().trim().equalsIgnoreCase(pta + tray)) {
            attributes.add(m);
            break;
        }
    }
}

// Print, etc
// printJob.print(pdfDoc, pset);