精华内容
下载资源
问答
  • 如题,怎么来设置打印机的输出格式,使其固定化,还有如何打印出条形码,
  • android连接打印机打印

    万次阅读 多人点赞 2017-03-08 11:38:55
    Android用户经常只在自己的设备上查看内容,但... 打印还允许他们创建不依赖于具有设备,足够的电池电量或无线网络连接的信息的快照。 在Android 4.4(API级别19)及更高版本中,框架提供了直接从Android应用程序

    Android用户经常只在自己的设备上查看内容,但有时显示某人的屏幕不是一种充分的方式来共享信息。 您可以从Android应用程式列印资讯,让使用者可以透过应用程式查看更大版本的内容,或与未使用您应用程式的使用者分享。 打印还允许他们创建不依赖于具有设备,足够的电池电量或无线网络连接的信息的快照。

    Android 4.4(API级别19)及更高版本中框架提供了直接从Android应用程序打印图像和文档的服务。 本培训介绍如何在应用程序中启用打印功能,包括打印图像,HTML页面和创建自定义文档以进行打印。

    一:打印照片

    拍摄和分享照片是移动设备最流行的用途之一。 如果应用程序拍摄照片,显示照片或允许用户共享图像,则应考虑在应用程序中启用打印这些图像。 Android Support Library 提供了一个方便的功能,使用最少的代码和简单的打印布局选项集启用图像打印。

    本节将向您介绍如何使用v4支持库PrintHelper 类打印图像:

    Android支持库PrintHelper类提供了一种打印图像的简单方法。 该类有一个单一的布局选项,setScaleMode(),它允许您打印两个选项之一:

    SCALE_MODE_FIT
    - 此选项调整图像大小,以便整个图像显示在页面的可打印区域内。
    SCALE_MODE_FILL
    - 此选项缩放图像,以便它填充页面的整个可打印区域。 选择此设置意味着不打印图像的顶部和底部,或左右边缘的某些部分。 如果未设置缩放模式,则此选项为默认值。
    setScaleMode()的缩放选项保持图像的现有宽高比不变。 以下代码示例显示如何创建PrintHelper类的实例,设置缩放选项,并开始打印过程:

    private void doPhotoPrint() {
        PrintHelper photoPrinter = new PrintHelper(getActivity());
        photoPrinter.setScaleMode(PrintHelper.SCALE_MODE_FIT);
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
                R.drawable.droids);
        photoPrinter.printBitmap("droids.jpg - test print", bitmap);
    }
    此方法可以称为菜单项的操作。 注意,不总是支持的操作(例如打印)的菜单项应该放在溢出菜单中。 有关更多信息,请参阅Action Bar设计指南。

    调用printBitmap()方法后,不需要从应用程序执行进一步的操作。 将显示Android打印用户界面,允许用户选择打印机和打印选项。 然后用户可以打印图像或取消操作。 如果用户选择打印图像,则会创建打印作业,并在系统栏中显示打印通知。

    如果要在打印输出中包括除图像之外的其他内容,则必须构建打印文档。 有关创建要打印的文档的信息,请往下看。

    二:打印HTML文档

    在Android上打印超出简单照片的内容需要在打印文档中合成文本和图形。 Android框架提供了一种使用HTML来编写文档并使用最少的代码打印文档的方法。


    Android 4.4(API级别19)中,WebView类已更新为启用打印HTML内容。 该类允许您加载本地HTML资源或从网络下载页面,创建打印作业并将其移交给Android的打印服务。

    本节将向您展示如何快速构建包含文本和图形的HTML文档,并使用WebView进行打印。

    1.加载HTML文档

    使用WebView打印HTML文档涉及加载HTML资源或将HTML文档构建为字符串。 本节介绍如何构建HTML字符串并将其加载到WebView以进行打印。

    此视图对象通常用作活动布局的一部分。 但是,如果您的应用程序没有使用WebView,您可以专门为打印目的创建类的实例。 创建此自定义打印视图的主要步骤如下:

    (1)创建在加载HTML资源后启动打印作业的
    WebViewClient
    (2)将HTML资源加载到
    WebView对象中。
    下面的代码示例演示了如何创建一个简单的WebViewClient并加载一个动态创建的HTML文档:

    private WebView mWebView;
    
    private void doWebViewPrint() {
        // Create a WebView object specifically for printing
        WebView webView = new WebView(getActivity());
        webView.setWebViewClient(new WebViewClient() {
    
                public boolean shouldOverrideUrlLoading(WebView view, String url) {
                    return false;
                }
    
                @Override
                public void onPageFinished(WebView view, String url) {
                    Log.i(TAG, "page finished loading " + url);
                    createWebPrintJob(view);
                    mWebView = null;
                }
        });
    
        // Generate an HTML document on the fly:
        String htmlDocument = "<html><body><h1>Test Content</h1><p>Testing, " +
                "testing, testing...</p></body></html>";
        webView.loadDataWithBaseURL(null, htmlDocument, "text/HTML", "UTF-8", null);
    
        // Keep a reference to WebView object until you pass the PrintDocumentAdapter
        // to the PrintManager
        mWebView = webView;
    }

    注意:确保生成打印作业的调用发生在您在上一节中创建的WebViewClient的onPageFinished()方法中。 如果不等到页面加载完成,打印输出可能不完整或空白,或可能完全失败。

    注意:上面的示例代码保存了一个WebView对象的实例,因此在创建打印作业之前不会对其进行垃圾回收。 确保您在自己的实现中执行相同操作,否则打印过程可能会失败。

    如果要在页面中包含图形,请将图形文件放在项目的
    assets /目录中,并在loadDataWithBaseURL()方法的第一个参数中指定基本URL,如以下代码示例所示:

    webView.loadDataWithBaseURL("file:///android_asset/images/", htmlBody,
            "text/HTML", "UTF-8", null);
    您还可以通过使用loadUrl()替换loadDataWithBaseURL()方法来加载要打印的网页,如下所示。

    // Print an existing web page (remember to request INTERNET permission!):
    webView.loadUrl("http://developer.android.com/about/index.html");        

    使用WebView创建打印文档时,应注意以下限制:

    (1)您无法向文档中添加页眉或页脚(包括页码)。
    (2)HTML文档的打印选项不包括打印页面范围的功能,例如:不支持打印10页HTML文档的第2页到第4页。
    (3)WebView的一个实例一次只能处理一个打印作业。
    (4)不支持包含CSS打印属性(如横向属性)的HTML文档。
    (5)您不能在HTML文档中使用JavaScript来触发打印。
    注意:包含在布局中的WebView对象的内容也可以在加载文档后打印。

    如果要创建更定制的打印输出并完全控制打印页上的内容,请看下一节:Printing a Custom Document

    2.创建打印作业

    在创建WebView并加载HTML内容后,您的应用程序几乎完成了它的打印过程的一部分。 接下来的步骤是访问PrintManager,创建打印适配器,最后创建打印作业。 以下示例说明如何执行这些步骤:

    private void createWebPrintJob(WebView webView) {
    
        // Get a PrintManager instance
        PrintManager printManager = (PrintManager) getActivity()
                .getSystemService(Context.PRINT_SERVICE);
    
        // Get a print adapter instance
        PrintDocumentAdapter printAdapter = webView.createPrintDocumentAdapter();
    
        // Create a print job with name and adapter instance
        String jobName = getString(R.string.app_name) + " Document";
        PrintJob printJob = printManager.print(jobName, printAdapter,
                new PrintAttributes.Builder().build());
    
        // Save the job object for later status checking
        mPrintJobs.add(printJob);
    }
    此示例保存PrintJob对象的实例以供应用程序使用,这不是必需的。 您的应用程序可能会使用此对象来跟踪打印作业正在处理时的进度。 当您希望在应用程序中监视打印作业的完成,失败或用户取消操作的状态时,此方法非常有用。 不需要创建应用程序内通知,因为打印框架会自动为打印作业创建系统通知。

    三:打印自定义文档

    对于一些应用程序,如绘图应用程序,页面布局应用程序和其他专注于图形输出的应用程序,创建漂亮的打印页面是一个关键特性。 在这种情况下,打印图像或HTML文档是不够的。 这些类型应用程序的打印输出需要精确控制进入页面的所有内容,包括字体,文本流,分页符,页眉,页脚和图形元素。

    为您的应用程序创建完全自定义的打印输出需要比前面讨论的方法更多的编程投资。 您必须构建与打印框架通信的组件,调整为打印机设置,绘制页面元素和管理多个页面上的打印。

    本节将向您介绍如何与打印管理器连接,创建打印适配器并构建打印内容

    1.连接到打印管理器

    当应用程序直接管理打印过程时,从用户收到打印请求后的第一步是连接到Android打印框架并获取PrintManager类的实例。 此类允许您初始化打印作业并开始打印生命周期。 以下代码示例显示如何获取打印管理器并开始打印过程。

    private void doPrint() {
        // Get a PrintManager instance
        PrintManager printManager = (PrintManager) getActivity()
                .getSystemService(Context.PRINT_SERVICE);
    
        // Set job name, which will be displayed in the print queue
        String jobName = getActivity().getString(R.string.app_name) + " Document";
    
        // Start a print job, passing in a PrintDocumentAdapter implementation
        // to handle the generation of a print document
        printManager.print(jobName, new MyPrintDocumentAdapter(getActivity()),
                null); //
    }

    上面的示例代码演示了如何命名打印作业并设置PrintDocumentAdapter类的实例,该类负责处理打印生命周期的步骤。 打印适配器类的实现将在下一节中讨论。

    注意:print()方法中的最后一个参数接受一个PrintAttributes对象。 您可以使用此参数向打印框架提供提示,并根据先前的打印周期提供预设选项,从而改善用户体验。 您还可以使用此参数设置更适合正在打印的内容的选项,例如在打印处于该方向的照片时将方向设置为横向

    2.创建打印适配器

    打印适配器与Android打印框架交互并处理打印过程的步骤。此过程要求用户在创建要打印的文档之前选择打印机和打印选项。这些选择可以影响最终输出,因为用户选择具有不同输出能力,不同页面大小或不同页面方向的打印机。当进行这些选择时,打印框架要求适配器布置并生成打印文档,以准备最终输出。一旦用户点击打印按钮,框架获取最终打印文档并将其传递给打印提供者用于输出。在打印过程中,用户可以选择取消打印操作,因此打印适配器还必须监听并对取消请求作出反应。

    PrintDocumentAdapter抽象类设计用于处理打印生命周期,它有四个主要的回调方法。您必须在打印适配器中实现这些方法,以便与打印框架正确交互:

    (1)onStart()
    - 在打印进程的开始调用一次。如果应用程序有任何一次性准备任务要执行,例如获取要打印的数据的快照,请在此处执行。不需要在适配器中实现此方法。
    (2)onLayout()
    - 每次用户更改影响输出的打印设置(例如不同的页面大小或页面方向)时调用,为应用程序提供计算要打印的页面布局的机会。至少,此方法必须返回打印文档中预期的页数。
    (3)onWrite()
    - 调用将打印的页面转换为要打印的文件。此方法可以在每次onLayout()调用后调用一次或多次。
    (4)onFinish()
    - 在打印过程结束时调用一次。如果您的应用程序有任何一次性拆卸任务要执行,请在此处执行。不需要在适配器中实现此方法。
    以下部分介绍如何实现布局和写入方法,这对于打印适配器的功能至关重要。

    注意:这些适配器方法在应用程序的主线程上调用。如果你期望这些方法在你的实现中的执行需要大量的时间,实现它们在一个单独的线程中执行。例如,您可以封装布局或在单独的
    AsyncTask对象中打印文档编写工作

    3.计算打印文档信息

    在PrintDocumentAdapter类的实现中,您的应用程序必须能够指定正在创建的文档类型,并计算打印作业的总页数,并提供有关打印页面大小的信息。 在适配器中实现onLayout()方法进行这些计算,并提供有关PrintDocumentInfo类中打印作业的预期输出的信息,包括页数和内容类型。 以下代码示例显示了PrintDocumentAdapter的onLayout()方法的基本实现:

    @Override
    public void onLayout(PrintAttributes oldAttributes,
                         PrintAttributes newAttributes,
                         CancellationSignal cancellationSignal,
                         LayoutResultCallback callback,
                         Bundle metadata) {
        // Create a new PdfDocument with the requested page attributes
        mPdfDocument = new PrintedPdfDocument(getActivity(), newAttributes);
    
        // Respond to cancellation request
        if (cancellationSignal.isCancelled() ) {
            callback.onLayoutCancelled();
            return;
        }
    
        // Compute the expected number of printed pages
        int pages = computePageCount(newAttributes);
    
        if (pages > 0) {
            // Return print information to print framework
            PrintDocumentInfo info = new PrintDocumentInfo
                    .Builder("print_output.pdf")
                    .setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT)
                    .setPageCount(pages);
                    .build();
            // Content layout reflow is complete
            callback.onLayoutFinished(info, true);
        } else {
            // Otherwise report an error to the print framework
            callback.onLayoutFailed("Page count calculation failed.");
        }
    }

    onLayout()方法的执行可以有三个结果:完成,取消或失败,在布局的计算无法完成的情况下。 您必须通过调用PrintDocumentAdapter.LayoutResultCallback对象的相应方法来指定其中一个结果。

    注意:onLayoutFinished()方法的boolean参数指示自上次请求以来布局内容是否实际已更改。 正确设置此参数允许打印框架避免不必要地调用onWrite()方法,基本上缓存先前写入的打印文档并提高性能。

    onLayout()的主要工作是计算给定打印机属性时预期为输出的页数。 如何计算此数字在很大程度上取决于应用程序如何布局打印页面。 下面的代码示例显示了一个实现,其中页数由打印方向决定:

    private int computePageCount(PrintAttributes printAttributes) {
        int itemsPerPage = 4; // default item count for portrait mode
    
        MediaSize pageSize = printAttributes.getMediaSize();
        if (!pageSize.isPortrait()) {
            // Six items per page in landscape orientation
            itemsPerPage = 6;
        }
    
        // Determine number of print items
        int printItemCount = getPrintItemCount();
    
        return (int) Math.ceil(printItemCount / itemsPerPage);
    }

    4.编写打印文档文件

    当需要将打印输出写入文件时,Android打印框架调用应用程序的PrintDocumentAdapter类的onWrite()方法。方法的参数指定应该写入哪些页面以及要使用的输出文件。然后,您的此方法的实现必须将每个请求的内容页面呈现为多页PDF文档文件。当此过程完成时,您调用回调对象的onWriteFinished()方法。

    注意:Android打印框架可以每次调用onLayout()时调用onWrite()方法一次或多次。为此,当打印内容布局未改变时,重要的是将onLayoutFinished()方法的布尔参数设置为false,以避免打印文档的不必要的重写。

    注意:onLayoutFinished()方法的布尔参数指示自上次请求以来布局内容是否实际已更改。正确设置此参数允许打印框架避免不必要地调用onLayout()方法,基本上缓存先前写入的打印文档并提高性能。

    以下示例演示了使用
    PrintedPdfDocument类创建PDF文件的此过程的基本机制:

    @Override
    public void onWrite(final PageRange[] pageRanges,
                        final ParcelFileDescriptor destination,
                        final CancellationSignal cancellationSignal,
                        final WriteResultCallback callback) {
        // Iterate over each page of the document,
        // check if it's in the output range.
        for (int i = 0; i < totalPages; i++) {
            // Check to see if this page is in the output range.
            if (containsPage(pageRanges, i)) {
                // If so, add it to writtenPagesArray. writtenPagesArray.size()
                // is used to compute the next output page index.
                writtenPagesArray.append(writtenPagesArray.size(), i);
                PdfDocument.Page page = mPdfDocument.startPage(i);
    
                // check for cancellation
                if (cancellationSignal.isCancelled()) {
                    callback.onWriteCancelled();
                    mPdfDocument.close();
                    mPdfDocument = null;
                    return;
                }
    
                // Draw page content for printing
                drawPage(page);
    
                // Rendering is complete, so page can be finalized.
                mPdfDocument.finishPage(page);
            }
        }
    
        // Write PDF document to file
        try {
            mPdfDocument.writeTo(new FileOutputStream(
                    destination.getFileDescriptor()));
        } catch (IOException e) {
            callback.onWriteFailed(e.toString());
            return;
        } finally {
            mPdfDocument.close();
            mPdfDocument = null;
        }
        PageRange[] writtenPages = computeWrittenPages();
        // Signal the print framework the document is complete
        callback.onWriteFinished(writtenPages);
    
        ...
    }

    此示例将PDF页面内容的呈现委派给drawPage()方法,这将在下一节中讨论。

    与布局一样,onWrite()方法的执行可以有三个结果:完成,取消或在内容不能写入的情况下失败。 您必须通过调用PrintDocumentAdapter.WriteResultCallback对象的相应方法指定其中一个结果。

    注意:渲染文档以进行打印可能是资源密集型操作。 为了避免阻塞应用程序的主用户界面线程,您应该考虑在单独的线程上执行页面呈现和写入操作,例如在AsyncTask中。 有关使用异步任务等执行线程的更多信息,请参阅 Processes and Threads

    5.绘图PDF页面内容

    当应用程序打印时,应用程序必须生成PDF文档并将其传递到Android打印框架进行打印。 您可以使用任何PDF生成库用于此目的。 本课将介绍如何使用PrintedPdfDocument类根据内容生成PDF页面。

    PrintedPdfDocument类使用Canvas对象在PDF页面上绘制元素,类似于在活动布局上绘图。 您可以使用Canvas绘制方法在打印页面上绘制元素。 以下示例代码演示了如何使用以下方法在PDF文档页面上绘制一些简单元素:

    private void drawPage(PdfDocument.Page page) {
        Canvas canvas = page.getCanvas();
    
        // units are in points (1/72 of an inch)
        int titleBaseLine = 72;
        int leftMargin = 54;
    
        Paint paint = new Paint();
        paint.setColor(Color.BLACK);
        paint.setTextSize(36);
        canvas.drawText("Test Title", leftMargin, titleBaseLine, paint);
    
        paint.setTextSize(11);
        canvas.drawText("Test paragraph", leftMargin, titleBaseLine + 25, paint);
    
        paint.setColor(Color.BLUE);
        canvas.drawRect(100, 100, 172, 172, paint);
    }

    当使用Canvas在PDF页面上绘制时,元素以点为单位指定,即1/72英寸。 请确保使用此度量单位来指定页面上元素的大小。 对于绘制元素的定位,坐标系从页面的左上角的0,0开始。

    提示:Canvas对象允许您将打印元素放置在PDF文档的边缘,但许多打印机不能打印到物理纸张的边缘。 在使用此类构建打印文档时,请确保考虑了页面的不可打印边缘。


    展开全文
  • python连接打印机打印文档、图片、pdf文件等

    万次阅读 多人点赞 2019-08-27 10:25:50
    引言 python连接打印机进行打印,可能根据需求的不同,使用不同的函数模块。 如果你只是简单的想打印文档,比如

    引言

    python连接打印机进行打印,可能根据需求的不同,使用不同的函数模块。

    1. 如果你只是简单的想打印文档,比如office文档,你可以使用ShellExecute方法,对于微软office的文档、pdf、txt等有用,你可以尝试下;
    2. 如果你输入某些数据,文字信息,就想直接把它发送给打印机打印,那么可以尝试使用win32print
    3. 如果你有一张图片,那么你可以结合python的Python Imaging Library(PIL)win32ui模块进行打印;

    普通打印

    ShellExecute

    • 首先确保你电脑中的应用可以打开你要打印的文件;
    • 是一些标准的文件类型
    • 不用管哪些打印机,也就是说和连接的打印机型号无关;
    • 你无控制设置打印属性的权限;
    import tempfile
    import win32api
    import win32print
    
    filename = tempfile.mktemp (".txt")
    open (filename, "w").write ("This is a test")
    win32api.ShellExecute (
      0,
      "print",
      filename,
      #
      # If this is None, the default printer will
      # be used anyway.
      #
      '/d:"%s"' % win32print.GetDefaultPrinter (),
      ".",
      0
    )
    

    另一个版本

    import tempfile
    import win32api
    import win32print
    
    filename = tempfile.mktemp (".txt")
    open (filename, "w").write ("This is a test")
    win32api.ShellExecute (
      0,
      "printto",
      filename,
      '"%s"' % win32print.GetDefaultPrinter (),
      ".",
      0
    )
    

    直接打印数据

    win32print

    • 直接将数据扔给打印机;
    • 快速而且容易;
    • 而且可以定义选择哪个打印机打印;
    • 但是要打印的数据必须是可打印的,例如字符串等;
    import os, sys
    import win32print
    printer_name = win32print.GetDefaultPrinter ()
    #
    # raw_data could equally be raw PCL/PS read from
    #  some print-to-file operation
    #
    if sys.version_info >= (3,):
      raw_data = bytes ("This is a test", "utf-8")
    else:
      raw_data = "This is a test"
    
    hPrinter = win32print.OpenPrinter (printer_name)
    try:
      hJob = win32print.StartDocPrinter (hPrinter, 1, ("test of raw data", None, "RAW"))
      try:
        win32print.StartPagePrinter (hPrinter)
        win32print.WritePrinter (hPrinter, raw_data)
        win32print.EndPagePrinter (hPrinter)
      finally:
        win32print.EndDocPrinter (hPrinter)
    finally:
      win32print.ClosePrinter (hPrinter)
    

    打印图片

    PIL win32ui

    不使用额外的工具,在windows电脑上打印一张图片是相当的困难,至少需要3种不同的且相关的设备环境才可以。
    还好,device-independent bitmap(DIB)PIL可以帮助我们快速打印。下面的代码可以将图片发送至打印机打印尽可能大的尺寸且不失比例。

    • 还可以选择使用哪个打印机
    • 选择加载的图片的格式等
    • 但是如果你电脑不是windows,那可能不是最好的方法;
    import win32print
    import win32ui
    from PIL import Image, ImageWin
    
    #
    # Constants for GetDeviceCaps
    #
    #
    # HORZRES / VERTRES = printable area
    #
    HORZRES = 8
    VERTRES = 10
    #
    # LOGPIXELS = dots per inch
    #
    LOGPIXELSX = 88
    LOGPIXELSY = 90
    #
    # PHYSICALWIDTH/HEIGHT = total area
    #
    PHYSICALWIDTH = 110
    PHYSICALHEIGHT = 111
    #
    # PHYSICALOFFSETX/Y = left / top margin
    #
    PHYSICALOFFSETX = 112
    PHYSICALOFFSETY = 113
    
    printer_name = win32print.GetDefaultPrinter ()
    file_name = "test.jpg"
    
    #
    # You can only write a Device-independent bitmap
    #  directly to a Windows device context; therefore
    #  we need (for ease) to use the Python Imaging
    #  Library to manipulate the image.
    #
    # Create a device context from a named printer
    #  and assess the printable size of the paper.
    #
    hDC = win32ui.CreateDC ()
    hDC.CreatePrinterDC (printer_name)
    printable_area = hDC.GetDeviceCaps (HORZRES), hDC.GetDeviceCaps (VERTRES)
    printer_size = hDC.GetDeviceCaps (PHYSICALWIDTH), hDC.GetDeviceCaps (PHYSICALHEIGHT)
    printer_margins = hDC.GetDeviceCaps (PHYSICALOFFSETX), hDC.GetDeviceCaps (PHYSICALOFFSETY)
    
    #
    # Open the image, rotate it if it's wider than
    #  it is high, and work out how much to multiply
    #  each pixel by to get it as big as possible on
    #  the page without distorting.
    #
    bmp = Image.open (file_name)
    if bmp.size[0] > bmp.size[1]:
      bmp = bmp.rotate (90)
    
    ratios = [1.0 * printable_area[0] / bmp.size[0], 1.0 * printable_area[1] / bmp.size[1]]
    scale = min (ratios)
    
    #
    # Start the print job, and draw the bitmap to
    #  the printer device at the scaled size.
    #
    hDC.StartDoc (file_name)
    hDC.StartPage ()
    
    dib = ImageWin.Dib (bmp)
    scaled_width, scaled_height = [int (scale * i) for i in bmp.size]
    x1 = int ((printer_size[0] - scaled_width) / 2)
    y1 = int ((printer_size[1] - scaled_height) / 2)
    x2 = x1 + scaled_width
    y2 = y1 + scaled_height
    dib.draw (hDC.GetHandleOutput (), (x1, y1, x2, y2))
    
    hDC.EndPage ()
    hDC.EndDoc ()
    hDC.DeleteDC ()
    

    实践

    从前台传来要打印的字符,后端生成二维码,并作出相应处理后,连接打印机打印图片。

    # 打印二维码
    def print_barcode(request):
        import pyqrcode
        import random,string
        from PIL import Image,ImageDraw,ImageFont
        import numpy as np
        if request.is_ajax() and request.method == 'POST':
            result = {}
            bar_string = 'NaN'
            type = request.POST['type']
    
            if type == 'box':
                # 生成箱子码
                # 格式:P190823-K91  [P][日期][-][A-Z][0-9][0-9]
                bar_string = 'P'+datetime.date.today().strftime('%y%m%d')+'-'+str(random.choice('ABCDEFGHIGKLMNOPQRSTUVWXYZ'))\
                             + str(random.choice(range(10)))+ str(random.choice(range(10)))
            elif type == 'kuwei':
                # 生成库位码
                bar_string = request.POST['string']
            else:
                pass
    
            try:
                big_code = pyqrcode.create(bar_string, error='L', version=2 , mode='binary')
                big_code.png('./code.png', scale=8)
                img_code = Image.open('code.png')
    
                size = img_code.size
                img_final = Image.new('RGB', (size[0], size[1]+35), color=(255, 255, 255))
                img_final.paste(img_code, (0, 0, size[0], size[1]))
    
                draw = ImageDraw.Draw(img_final)
                font = ImageFont.truetype('AdobeGothicStd-Bold.otf', size=35)
                width, height = draw.textsize(bar_string,font=font)
                draw.text(((size[0]-width)/2, size[1]-15), bar_string , fill=(0, 0, 0), font=font)
                img_final.save('./code.png')
    
                # 然后连接打印机将其打印出来即可
                is_ok =[]
                if type == 'box':
                    for i in range(4):
                        temp = print_img('./code.png')
                        is_ok.append(temp)
                else:
                    temp = print_img('./code.png')
                    is_ok.append(temp)
                # is_ok = True
                result['done'] = 'ok' if np.all(is_ok) else '连接打印机失败'
            except Exception as e:
                result['done'] = e
    
            return JsonResponse(result)
     
     def print_img(img):
        import win32print
        import win32ui
        from PIL import Image, ImageWin
        # 参考 http://timgolden.me.uk/python/win32_how_do_i/print.html#win32print
        try:
            printer_name = win32print.GetDefaultPrinter()
            hDC = win32ui.CreateDC()
            hDC.CreatePrinterDC(printer_name)
    
            #printable_area = (300, 270)  # 打印纸尺寸
            #printer_size = (300, 270)
    
            # 打开图片并缩放
            bmp = Image.open(img)
            if bmp.size[0] < bmp.size[1]:
                bmp = bmp.rotate(90)
    
            # ratios = [1.0 * printable_area[0] / bmp.size[1], 1.0 * printable_area[1] / bmp.size[0]]
            # scale = min(ratios)
            scale = 1
    
            hDC.StartDoc(img)
            hDC.StartPage()
    
            dib = ImageWin.Dib(bmp)
            scaled_width, scaled_height = [int(scale * i) for i in bmp.size]
    
            x1 = 20  # 控制位置
            y1 = -30
            x2 = x1 + scaled_width
            y2 = y1 + scaled_height
            dib.draw(hDC.GetHandleOutput(), (x1, y1, x2, y2))
    
            hDC.EndPage()
            hDC.EndDoc()
            hDC.DeleteDC()
    
            return True
        except:
            return False
    

    打印效果:
    在这里插入图片描述
    以上内容为二赛君整理发布,转载请注明出处,谢谢。

    参考

    http://timgolden.me.uk/python/win32_how_do_i/print.htm

    http://docs.activestate.com/activepython/2.5/pywin32/win32print.html

    展开全文
  • labview 连接斑马条码打印机如何连接,如何打印条码?是用USB还是串口?
  • h5+连接蓝牙打印机打印小票

    千次阅读 热门讨论 2019-11-13 16:50:17
    由于所在公司产品需要一个骑手端自动接单,接单后自动打印小票的功能,所以原有的公众号做成了app,调用蓝牙打印机打印小票。 运用框架:mui.js;jquery(不要吐槽,是原有基础上改。。~ 摊手手~) html: <div ...

    由于所在公司产品需要一个骑手端自动接单,接单后自动打印小票的功能,所以将原有的公众号做成了app,调用蓝牙打印机打印小票。
    运用框架:mui.js;jquery(不要吐槽,是原有基础上改。。~ 摊手手~)
    html:

    <div class="main-box mui-off-canvas-wrap">
        <!-- 菜单容器 -->
    	  <aside class="mui-off-canvas-left">	
    		<div class="mui-scroll-wrapper">
    		  <div class="mui-scroll" id="offCanvasSideScroll">
    			<!-- 菜单具体展示内容 -->
    			  <div class="mui-btn">
    				<input id="bt1" class="mui-icon mui-icon-search" type="button" value="点击搜索设备" onclick="searchDevices('a')">
    			  </div>
    			  <div class="title">未配对蓝牙设备</div>
    			  <ul class="mui-table-view" id="list1">
    				<li class="mui-table-view-cell"></li>
    			  </ul>
    			  <div class="title">已配对蓝牙设备</div>
    			  <ul class="mui-table-view" id="list2">
    				<li class="mui-table-view-cell"></li>
    			  </ul>
    		  </div>
    		</div>
    	  </aside>
    	  <div class="mui-inner-wrap">
    		<div id="backdrop" class="mui-off-canvas-backdrop"></div>
    		<div >主体内容省略。。。</div>
    	</div>
    </div>
    

    大概就是下面的样子:
    在这里插入图片描述
    js来了:

    var device = null,
    	BAdapter = null,
    	BluetoothAdapter = null,
    	uuid = null,
    	main = null,
    	bluetoothSocket = null;
    mui.plusReady(function(){
    //如果已经连接过,就自动连接
    	if(localStorage.getItem('macaddress')){
    		connectFun(localStorage.getItem('macaddress'));
    	}
    })
    //手动搜索蓝牙
    //address=""搜索蓝牙//address=设备mac地址,自动配对给出mac地址的设备  
    function searchDevices(address) {
    	//注册类  
    	var main = plus.android.runtimeMainActivity();
    	var IntentFilter = plus.android.importClass('android.content.IntentFilter');
    	var BluetoothAdapter = plus.android.importClass("android.bluetooth.BluetoothAdapter");
    	var BluetoothDevice = plus.android.importClass("android.bluetooth.BluetoothDevice");
    	var BAdapter = BluetoothAdapter.getDefaultAdapter();
    	if (!BAdapter.isEnabled()) {
    		plus.nativeUI.confirm("蓝牙处于关闭状态,是否打开?", function(e) {
    			console.log(e.index)
    			if (e.index == 0) {
    				BAdapter.enable();
    				searchDevices();
    			}else{
    				mui.toast('请打开蓝牙')
    			}
    		});
    		console.log(BAdapter.isEnabled())
    	} else{
    		
    	var filter = new IntentFilter();
    	var bdevice = new BluetoothDevice();
    	var on = null;
    	var un = null;
    	var vlist1 = document.getElementById('list1'); //注册容器用来显示未配对设备  
    	vlist1.innerHTML = ''; //清空容器  
    	var vlist2 = document.getElementById('list2'); //注册容器用来显示未配对设备  
    	vlist2.innerHTML = ''; //清空容器  
    	var button1 = document.getElementById('bt1');
    	button1.disabled = true;
    	button1.value = '正在搜索请稍候...';
    	BAdapter.startDiscovery(); //开启搜索  
    	var receiver;
    	receiver = plus.android.implements('io.dcloud.android.content.BroadcastReceiver', {
    		onReceive: function(context, intent) { //实现onReceiver回调函数  
    			plus.android.importClass(intent); //通过intent实例引入intent类,方便以后的‘.’操作  
    			console.log(intent.getAction()); //获取action  
    			if (intent.getAction() == "android.bluetooth.adapter.action.DISCOVERY_FINISHED") {
    				main.unregisterReceiver(receiver); //取消监听  
    				button1.disabled = false;
    				button1.value = '搜索设备';
    			} else {
    				BleDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
    				//判断是否配对  
    				if (BleDevice.getBondState() == bdevice.BOND_NONE) {
    					console.log("未配对蓝牙设备:" + BleDevice.getName() + '    ' + BleDevice.getAddress());
    					//参数如果跟取得的mac地址一样就配对  
    					if (address == BleDevice.getAddress()) {
    						if (BleDevice.createBond()) { //配对命令.createBond()  
    							var li2 = document.createElement('li'); //注册  
    							li2.setAttribute('id', BleDevice.getAddress()); //打印机mac地址  
    							li2.setAttribute('onclick', 'connectFun(id)'); //注册click点击列表进行打印  
    							li2.innerText = BleDevice.getName();
    							vlist2.appendChild(li2);
    						}
    
    					} else {
    						if (BleDevice.getName() != on) { //判断防止重复添加  
    							var li1 = document.createElement('li'); //注册  
    							li1.setAttribute('id', BleDevice.getAddress()); //打印机mac地址  
    							li1.setAttribute('onclick', 'searchDevices(id)'); //注册click点击列表进行配对  
    							on = BleDevice.getName();
    							li1.innerText = on;
    							vlist1.appendChild(li1);
    
    						}
    
    					}
    				} else {
    					if (BleDevice.getName() != un) { //判断防止重复添加  
    						console.log("已配对蓝牙设备:" + BleDevice.getName() + '    ' + BleDevice.getAddress());
    						var li2 = document.createElement('li'); //注册  
    						li2.setAttribute('id', BleDevice.getAddress()); //打印机mac地址  
    						li2.setAttribute('onclick', 'connectFun(id)'); //注册click点击列表进行打印  
    						un = BleDevice.getName();
    						li2.innerText = un;
    						vlist2.appendChild(li2);
    					}
    				}
    			}
    
    		}
    	});
    
    	filter.addAction(bdevice.ACTION_FOUND);
    	filter.addAction(BAdapter.ACTION_DISCOVERY_STARTED);
    	filter.addAction(BAdapter.ACTION_DISCOVERY_FINISHED);
    	filter.addAction(BAdapter.ACTION_STATE_CHANGED);
    
    	main.registerReceiver(receiver, filter); //注册监听  
    	}
    }
        function connectFun(macaddress){
          // var macaddress = localStorage.getItem("macaddress");
          if(!macaddress) {
            mui.toast('请选择蓝牙打印机');
            return;
          }
          localStorage.setItem("macaddress", macaddress);
          main = plus.android.runtimeMainActivity();
          BluetoothAdapter = plus.android.importClass("android.bluetooth.BluetoothAdapter");
          UUID = plus.android.importClass("java.util.UUID");
          uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
          BAdapter = BluetoothAdapter.getDefaultAdapter();
          device = BAdapter.getRemoteDevice(macaddress);
          plus.android.importClass(device);
          bluetoothSocket = device.createInsecureRfcommSocketToServiceRecord(uuid);
          plus.android.importClass(bluetoothSocket);
          
          if (!bluetoothSocket.isConnected()) {
            console.log('检测到设备未连接,尝试连接....');
            bluetoothSocket.connect();
          }
          mui.toast('打印机已就绪,可正常打印!');
         // $('#searchBluetooth').html('已连接设备');
         // if(autoReceipt == 1){
         //   timer = setInterval(() => {
         //     orderRefresh()//后台自动接单就打印,所以前端要做轮询~无奈~
        //    }, 20000);
       //   }
           device = null //这里关键
         bluetoothSocket.close(); //必须关闭蓝牙连接否则意外断开的话打印错误
    } 
    //打印函数差点忘了:公司使用的打印机指令集为ESC/POS,其它自行百度
    function printOrder(obj){
    	macaddress = localStorage.getItem('macaddress');
    	  var BAdapter = BluetoothAdapter.getDefaultAdapter();
    	  if(bluetoothSocket==null){
    		  mui.toast('请连接蓝牙')
    		  return false;
    		}else{
    		 if (bluetoothSocket.isConnected()) {
    			if(BAdapter.isEnabled()){
    				console.log('xxxxx ' + device);
    				outputStream = bluetoothSocket.getOutputStream();
    				plus.android.importClass(outputStream);
    			 	outputStream.write([0x1B,0x40]);//打印复位
    		 		outputStream.write([0x1B,0x24,0x00,0x00]);
    		 		outputStream.write([0x1D,0x4C,0x0A,0x0A]);//左边距0x0A
    		 		
    		 		outputStream.write([ 0x1D, 0x21, 0x00]);//字体[0x1D, 0X21, n]
    		 		var str1 = '\n订单号:' + obj.orderNo +'\n\r';
    		 		str1 += '下单时间:' + obj.createDate +'\n\r';
    		 		str1 += '联系人:' + obj.pickupPop +'\n\r';
    		 		str1 += '电话:' + obj.pickupPhone +'\n\r';
    		 		str1 += '收货地址:' + obj.userAddressee.addressee + '\n\r';
    		 		var bytes1 = plus.android.invoke(str1, 'getBytes', 'GBK');
    		 		outputStream.write(bytes1);
    		 		outputStream.flush();
    		 
    		 		outputStream.write([ 0x1D, 0x21, 0x11]);//字体[0x1D, 0X21, n]放大两倍
    		 		var str2 = '门牌号:' + obj.userAddressee.doorNumber + '\n\r';
    		 		var bytes2 = plus.android.invoke(str2, 'getBytes', 'GBK');
    		 		outputStream.write(bytes2);
    		 		outputStream.flush();
    		 		
    		 		for (let j = 0; j < obj.orderInfoCartList.length; j++) {
    		 		  const res = obj.orderInfoCartList[j];
    		 		  outputStream.write([ 0x1D, 0x21, 0x00]);//字体[0x1D, 0X21, n]
    		 		  var str3 = '物件'+ (j+1) +':\n\r';
    		 		  var bytes3 = plus.android.invoke(str3, 'getBytes', 'GBK');
    		 		  outputStream.write(bytes3);
    		 		  outputStream.flush();
    		 		  
    		 		  outputStream.write([ 0x1D, 0x21, 0x11]);//字体[0x1D, 0X21, n]放大两倍
    		 		  str4 = '取件码:' + res.pickupCode +'\n\r';
    		 		  var bytes4 = plus.android.invoke(str4, 'getBytes', 'GBK');
    		 		  outputStream.write(bytes4);
    		 		  outputStream.flush();
    		 		  
    		 		  outputStream.write([ 0x1D, 0x21, 0x00]);//字体[0x1D, 0X21, n]
    		 		  str5 = '物件重量:' + res.weightValue +'\n\r';
    		 		  str5 += '备注:' + res.remarks +'\n\r';
    		 		  var bytes5 = plus.android.invoke(str5, 'getBytes', 'GBK');
    		 		  outputStream.write(bytes5);
    		 		  outputStream.flush();
    		 		}
    			 		
    		 		outputStream.write([ 0x1D, 0x21, 0x00]);//字体[0x1D, 0X21, n]
    		 		var str6 ='取件地址:' + obj.pickupAddress +'\n\r';
    				var bytes6 = plus.android.invoke(str6, 'getBytes', 'GBK');
    				outputStream.write(bytes6);
    				outputStream.flush();
    				
    				outputStream.write([0x1b, 0x61, 0x01]);//居中
    				outputStream.write([ 0x1D, 0x21, 0x00]);//字体[0x1D, 0X21, n]
    				var endStr = '\n***END***\n'
    				outputStream.write(plus.android.invoke(endStr, 'getBytes', 'gbk'))
    				outputStream.write(plus.android.invoke('\n', 'getBytes', 'gbk'))
    				outputStream.flush();
    			}
    		}else{
    		 mui.toast('请连接蓝牙')
    		 return false;
    	 }	 
      }
    }
    

    如果需要全部的源码,可以评论留下你的邮件地址

    展开全文
  • 安卓开发中wifi连接打印机打印图片

    千次阅读 2018-11-07 11:07:06
    1.手机连接上打印机的wifi后 public void print(final IWebview iWebview, JSONArray array) {  this.mIWebview = iWebview;  this.activity = iWebview.getActivity();  this.mContext = iWebview.getC...

    1.手机连接上打印机的wifi后

    public void print(final IWebview iWebview, JSONArray array) {
            this.mIWebview = iWebview;
            this.activity = iWebview.getActivity();
            this.mContext = iWebview.getContext();
            this.mCallBackID = array.optString(0);
            path = array.optString(1);
           
            //申请sd卡权限  

            ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, 
                    Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS},4);  
            PrintHelper photoPrinter = new PrintHelper(activity);
            photoPrinter.setScaleMode(PrintHelper.SCALE_MODE_FIT);//设置填充的类型,填充的类型指的是在A4纸上打印时的填充类型,两种模式  
            //           public static final int SCALE_MODE_FILL = 2;  (默认)
            //解释下:Fit模式下,你所打印的图片会缩放至A4纸能够显示所有的图片内容;Fill模式下,
            //你所打印的图片会把打印的图片拉伸直到某条边能够和对应的A4纸的边长度一致。
            //打印    // data:image/png;base64,转为图片的时候需要去掉
            Bitmap bitmap = BitmapFactory.decodeFile(GenerateImage(path));  
            photoPrinter.printBitmap("jpgTestPrint", bitmap);//这里的第一个参数是打印的jobName  
        }
        

    展开全文
  • 最近公司给商户做的App 允许App把卖出的商品信息通过打印机 打印标签 所以了解了一下iOS 和 打印机 之间的交互 (Ps:用的不是UIPrinter 那个扫面打印机 发送信息打印的那个框架) 主要功能 打印 .中文. 数字. 二维码...
  • Labview连接bartender自动打印条码

    千次阅读 2019-11-13 20:31:43
    工作中用到标签打印的问题,因为标签中含有流水号、二维码等实时变化的信息,自己通过labview生成的二维码客户无法识别,所以就想到了用labview调用bartender自动打印条码。 调试的过程很简单,因为不熟悉bartender...
  • 与官方技术人员联系说 Mac不支持打印彩色的内容,只能打印黑白;Windows是可以打印彩色的…(只能默默说句fuck the printer) 连接方式如下: 第一步:进入系统偏好设置,点击打印机与扫描仪 第二步:...
  • //将打印状态修改为已打印 if(null!=data&&data.success==true){ $("#printContent").jqprint(); }else{ alert("连接超时或发生错误,请联系管理员!"); } }; ``` 我需要在打印之前或同时保存一份pdf作为版本...
  • java实现连接打印机打印PDF文件

    千次阅读 2019-12-25 09:57:25
    // 下面一行代码,解决了打印内容为空的问题 paper.setImageableArea(marginLeft, marginRight, width - (marginLeft + marginRight), height - (marginTop + marginBottom)); return paper; } public static ...
  • app连接蓝牙打印机实现打印并排版

    千次阅读 2015-12-31 14:05:47
    因为从未接触过这方面的东西,就在网上下载了一个demo,demo地址:http://blog.csdn.net/reality_jie_blog/article/details/11895843,demo中是可以实现百分百连接打印的,但是我在移植过程中发现每次都只能在手机开...
  • 我想要再ipad程序里面,用代码给打印机发送一段字符串,然后打印。 各位,我的问题没有说清楚,不好意思。...打印机和ipad在同一个局域网下,想用socket通过打印机的ip地址进行传送要打印内容
  • printshare连接打印机 ,打印word

    千次阅读 2019-04-12 11:15:00
    最近我们公司在做人脸识别技术,识别完之后需要打印word(printShare实现).下面就看一下怎么实现吧. 首先在我们的项目里需要word文档,放在raw下或者是res下面,我这里是在raw下面写的. 然后还需要下载poi包,,当然下载...
  • 友情帮助朋友做一个小程序打印自定义内容模块,本以为只是简单的文本、条形码、二维码等内容,实际拿到需求后发现是打印图片,瞬间傻眼。每天零点到四点,研究一周,最终才在小程序上直接实现,特此Mark。 打印机:...
  • JAVA连接打印机打印小票、产品信息。标签打印机

    万次阅读 热门讨论 2016-04-12 21:01:00
    2018年写了一个标签打印机(TSC TX600),标签打印程序,实现功能是通过串口读出设备ID生成二维码和设备信息,用于esp8266 smart config配网。源码和资料:https://download.csdn.net/download/u012854263/12080191 ...
  • 通常情况下,用户都会选择用NiceLabel这款标签打印软件,用它来连接数据库表格进行标签打印,省力省时。但是,NiceLabel连接数据库有时会出一些小问题,比如:NiceLabel错误消息10014,这要怎么解决呢?下面就一起来...
  • 为了开发android无线点餐系统,需要用到打印小票任务,根据网上查找资料所得,学习了两种方法,一种为通过tomcat服务连接服务器所连接的打印机打印,一种为直接连接网络打印机打印 一、通过tomcat服务连接...
  • uni-app H5+ 连接蓝牙打印机打印文字及二维码

    千次阅读 热门讨论 2020-10-21 15:49:45
    基于Native.js 实现的连接蓝牙打印机蓝牙打印效果图核心代码测试代码运行设备及环境PS: 蓝牙打印效果图 核心代码 /** * @Description: 蓝牙打印类 基于h5+ Native.js * @Author: EricLee * @Date: 2020-10-14 ...
  • sdk下载地址:https://www.poscom.cn/down-show-82.html 代码下载:... 一、打印机通过蓝牙连接手机设备 新建蓝牙管理类:LMBluetoothManeger LMBluetoothManeger.h文件 LMBluetoothManeger.m文...
  • Android Android pad 连接蓝牙打印机Gprinter---实现蓝牙打印功能
  • python连接pymysql建库、建表和打印

    万次阅读 2018-02-03 04:05:42
    本文章代码是根据疯狂的蚂蚁的博客中的MySQLdb连接python代码改编过来的,属于原创代码。 一、使用pycharm连接python和pymysql(实际上用不着import sys这语句) import pymysql import sys con=pymysql....
  • 在批量打印商品标签时一般都要加上条码或图片,而这类应用大多是使用斑马打印机,所以我也遇到了怎么打印的问题。 一种办法是用标签设计软件做好模板,在标签设计软件中打印,这种办法不用写代码,但对我来说觉得不...
  • 问题描述:我想要再ipad程序里面,用代码给打印机发送一段字符串,然后...其中打印机和ipad在同一个局域网下,想用socket通过打印机的ip地址进行传送要打印内容。 更多解决方法见:http://ask.csdn.net/questions
  • 原文地址:http://android.xsoftlab.net/training/printing/custom-docs.html对于一些应用,比如绘图类APP,版面设计类APP以及其它APP,...这些程序对于这种类型的打印需要对页面中每样事物的控制都特别的精细,包括字
  • 目前网上教程与Demo介绍的都是蓝牙连接热敏打印机(pos机大小的打印机),如果想通过蓝牙连接日常所见到的打印机,进行打印,这些教程或Demo是做不到的。  目前Android的蓝牙并不支持BPP(Basic Printing Profile),...
  • 打印

    千次阅读 2020-10-23 09:15:00
    在这章中,我们会着手用于打印文件和控制打印选项的命令行工具。通常不同发行版的打印配置各有不同且都会在其安装时自动完成,因此这里我们不讨论打印的配置过程。本章的练习需要一台正确配置的打印机来完成。 ...
  • spring boot 集成druid数据库连接池,并打印sql pom文件配置 <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-s...
  • PHP连接数据库并读取数据打印

    千次阅读 2016-01-22 14:57:12
    $link = mysqli_connect("localhost","root","root") or die("Connect error"); if($link){ echo "Connect success "; mysqli_select_db($link, "world"); $sql = "select * from city"; ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 324,600
精华内容 129,840
关键字:

怎么将链接内容打印