Problems with Open-Source Downloads read https://www.qt.io/blog/problem-with-open-source-downloads and https://forum.qt.io/post/638946

Printing date and time on Zebra label printer GK420t via USB on a Raspberry pi 4



  • Hello everyone. First of all happy new year!
    I'm struggling to print directly from QT application to Zebra label printer. I read many topics and found that this may be impossible as QT does not support ZPL. So what other options are available? My goal is to have a pushbotton on my app that once it is pressed, a label with the current date and time gets printed on the Zebra label printer. Im open to any idea or suggestion on how to make this thing work. All project (QT) and printer are meant to be on a Raspberry pi 4. I installed CUPS and worked and printed just fine from a notepad file. Hope you guys can help me.

    Thanks in advanced!


  • Lifetime Qt Champion

    Hi and welcome to devnet,

    It looks like your printer can be used like a classic printer, correct ?

    If so you should be able to use Qt's printing facilities.

    Otherwise, how are you printing to it ?



  • @GARUCHIRAZUMAN said in Printing date and time on Zebra label printer GK420t via USB on a Raspberry pi 4:

    I installed CUPS and worked and printed just fine from a notepad file

    Have you tried to print from Qt via CUPS to such Zebra printer?

    You can see from documentation that using a QPrinter object

    On X11, QPrinter uses the Common Unix Printing System (CUPS) to send PDF output to the printer.

    I haven't used it myself, but it's an approach I'd take.

    On the other hand, I guess (again, not having used it) that you could drive the Zebra printer directly via ZPL commands. Have you seen this C++ example?
    Although it's a parallel connection (lpt:) under Windows, I think you can grab the overall idea:

    1. open the QIODevice (i.e. something like /dev/ttyUSB0)
    2. write the ZPL commands to the device from #1
    3. close the device from #1

    Happy printing!



  • Good afternoon @GARUCHIRAZUMAN
    I used Zebra printers to print pdf documents (address labels) on Linux, Windows and macOS - not on raspi though, however it is my understanding that there should not be any difference.
    It never required any magic, using Qt PrintSupport and standard QPrinter. That means I relied on the printer to be properly configured in the system.
    I used the approach to have default settings right in the system, then just pulled those from the QPrinter/QPrinterInfo to set dimension right. No digging in ZPL, no low level approach. It just worked and as far as I can tell (I no longer work in the place where they use this software) still works.



  • @SGaist Hello and thanks for the quick reply.
    "It looks like your printer can be used like a classic printer, correct ?"
    Yes, I can print using any text editor such libre office on my Raspberry pi and prints correctly, as I already installed CUPS. But once I try to use my QT application to print using the internal QT resources such Qprinter, QPrintDialog or even Qpainter , only PDF format can be printed, but not the Navite Format.
    QT's documentation about Qprinter said: "QPrinter will print output using a method defined by the platform it is running on. This mode is the default when printing directly to a printer." but nothing happen on my printer and when I check at CUPS jobs list, there is nothing. Hope I was clear enough.

    Thank you!



  • @GARUCHIRAZUMAN
    If you do QPrinterInfo::availablePrinterNames() (can be sent to qDebug()) - do you see the name of your Zebra? You should initialise the printer with exactly that name (I always copy it from relevant position in QStringList returned by availablePrinterNames()).

    Having checked that, let's assume that your printer is listed as the first one. Code that should work:

    QStringList printers = QPrinterInfo::availablePrinterNames()
    QPrinterInfo printerInfo = QPrinterInfo::printerInfo(printers.at(0));
    QPrinter *printer = new QPrinter(printerInfo,QPrinter::HighResolution);
    QPainter painter;
    painter.begin(printer);
    painter.drawText([insert your tekst here, etc]);
    painter.end();
    delete printer;
    

    You also might need to setup page size before calling painter.begin() but I think default should work. Default and all page size are in the relevant QPrinterInfo object.
    But first thing to try is to check if Qt sees your printer by checking return values from availablePrinterNames(). If your printer is not there it means the system can't see it properly and usual Qt routines will fail.



  • @artwaw Awesome help from your side. I now can see Zebra printer and QT's application can communicate to printer as well.
    Also CUPS jobs list can see and record all print jobs coming from QT. However I see nothing printed on the labels. I believe by adjusting page size first needs to be done. This is going to be a bit complex as this specific Zebra model (420t) needs to print 4.00'' Length by 0.5'' Width, so is not standard A4 paper size. Any help on how to setup this paper size please ? I'm not familiar with this features yet. Many thanks in advanced.



  • @GARUCHIRAZUMAN my approach was to setup Zebra in the system for using correct paper size, then in Qt just poll the driver for default size and use that.
    Default page size and other (all) printer properties can be taken from QPrinterInfo object and setup via QPrinter instance. Knowing Zebra printers a bit it will require some experimentation I am afraid.



  • @GARUCHIRAZUMAN
    I managed to find a copy of the routines I used years ago to deal with Zebra. This code is ancient but the principles are there.
    The case, as I mentioned, was different (I used Poppler library to render PDF files to bitmap, later on on Mac I switched to QtPDF but that is not relevant here). You want to print text, so instead of my drawImage() it would be drawText() for you (I find this part really tricky to implement as one needs to be careful about positioning the data for drawing - I printed mostly 4"x6" and 4"x2.5").
    The UI had a combo box (named pListSizeBox) that had available paper sizes listed, user had to select the file, paper size (for many reasons this could not be the actual dimensions of the PDF file) and click on [Print] button.
    Actual image was in a handy QImage named label.
    I removed all error checking and nonessential code. Hope this helps.

    Getting the page sizes to UI:

    QPrinterInfo printer = QPrinterInfo::printerInfo([QString with printer name, as per my post higher up]);
    for (auto x=0;x<printer.supportedPageSizes().size();++x) {
        ui->plistSizeBox->addItem(printer.supportedPageSizes().at(x).name(),x);
      }
    

    Rendering:

    QImage MainWindow::Render(const QByteArray &retdata) const {
    #ifdef Q_OS_WIN
        Poppler::Document* pdf = Poppler::Document::loadFromData(retdata);
        QImage image = pdf->page(0)->renderToImage(300,300); //for some reason it looked better on the printout when image dpi was 300
    #endif
    #ifdef Q_OS_MAC
        QPdfDocument *pdf = new QPdfDocument();
        QBuffer *indev = new QBuffer();
        indev->setData(retdata);
        indev->open(QIODevice::ReadOnly);
        pdf->load(indev);
        QPrinter print(printer,QPrinter::HighResolution);
        print.setPageSize(printer.supportedPageSizes().at(ui->plistSizeBox->currentData().toInt()));
        print.setFullPage(true);
        QImage image = pdf->render(0,QSize(print.pageRect(QPrinter::DevicePixel).height(),print.pageRect(QPrinter::DevicePixel).width()));
        delete indev;
    #endif
        delete pdf;
        return image;
    }
    

    Printing:

        QPrinterInfo printer = QPrinterInfo::printerInfo([QString with printer name, as per my post higher up]);
        QPrinter *print = new QPrinter(printer,QPrinter::HighResolution);
    #ifdef Q_OS_WIN
        print->setFullPage(true); // this and next line are needed for windows only. Due to bug in the Qt on windows printout is shifted right and down
        print->setPageMargins(QMarginsF());
    #endif
        print->setDuplex(QPrinter::DuplexNone);
        print->setResolution(201); //that was default DPI for my Zebra, yours might differ!
        QPainter painter;
        print->setPageSize(printer.supportedPageSizes().at(ui->plistSizeBox->currentData().toInt()));
        painter.begin(print);
        painter.drawImage(print->pageRect(QPrinter::DevicePixel),label);
        painter.end();
        delete print;
    


  • @artwaw Thank you so much Arthur!, Let me spend the day working on this very useful information and I'll let you know how it comes. Thanks again! and have a great day !
    I believe this post is solved at least on QT side, the rest I believe is not QT related.



  • @Pablo-J-Rogina Thak you for your kind help !



  • @GARUCHIRAZUMAN

    Hey,
    I just started to print labels for the exact printer 2 days ago and also struggled with the USB.
    So I just switched to a network request and digged a little into the ZPL language.

    If you are interested just check this little Program:
    https://sourceforge.net/projects/zpldesigner/

    Alternativeley there you can use the preiview directly on this website:

    http://labelary.com/viewer.html

    I prefer the program, because it has a command-selector which describes the parameters and has a description for what it is used.

    Somehting like this could do the trick:

    bool  printLabelTCPSync(const QString ipAddress, quint16 port, QByteArray data)
    {
    
        QString errorText = "";
        QAbstractSocket *socket;
        socket = new QAbstractSocket(QAbstractSocket::TcpSocket, this);
        socket->setProxy(QNetworkProxy::NoProxy);
        socket->setSocketOption(QAbstractSocket::SendBufferSizeSocketOption, 1024);
            errorText = "";
            socket->connectToHost(ipAddress, port, QAbstractSocket::ReadWrite);
            if (socket->waitForConnected(1000))
            {
                if (socket->write(data) != -1)
                {
                    while (socket->bytesToWrite() > 0)
                    {
                        socket->flush();
                    }
    
                    if (socket->error() != QAbstractSocket::SocketError::UnknownSocketError)
                    {
                        errorText = "" //todo error;
                    }
                }
                else
                {
                    errorText = //todo diff error
                }
            }
            else
            {
                errorText = ""//todo communication failure
            }
            socket->disconnectFromHost();
    
            if (errorText != "")
            {
                //handle error
            }
    
        
    
        socket->deleteLater();
    
    
        if (errorText != "")
        {
           //handle error
           return false;
        }
    
        return true;
    }
    

    the label-code could be:

    ^XA
    ^FO0,0^FD%DATE%^FS
    ^FO0,20^FD%TIME%^FS
    ^XZ
    

    this would print date and time in seperate rows

    default is 8dots per mm
    standard-char height is 10

    Happy Printing


Log in to reply