Вернуться наверх
aco.ifmo.ru photonic
вернуться в оглавление предыдущая глава предыдущий параграф следующий параграф следующая глава


Пример 2.
Печать отчета

Задание конструктивных параметов и отображение оптической системы

Реализация функций в диалоге (файл lens.cpp)

В реализацию диалога примера 1 надо добавить:

  • подключение необходимых файлов
  • создание связи между кнопками и функциями по их обработке
  • реализацию нескольких функций:
//-------------------------------------------------------------------------------------------------
// обработка печати отчета (кнопка PrintReport), вызывает функцию PrintReport
void 
DQtOpticalSystem::OnPrintReport()
{
#ifndef QT_NO_PRINTER
    // создаем принтер и задаем параметры по умолчанию
    QPrinter printer; 
    printer.setOrientation(QPrinter::Portrait);
    printer.setPaperSize(QPrinter::A4);
    printer.setPageMargins(20, 20, 20, 20, QPrinter::Millimeter);
    // создаем стандартный диалог для выбора принтера
    QPrintDialog qPrintDialog(&printer, this);
    // если OK - вызываем функцию для печати
    if(qPrintDialog.exec()) 
        PrintReport(&printer);   
#endif
}
//-------------------------------------------------------------------------------------------------
// обработка PrintPreview (кнопка PrintPreview), вызывает функцию PrintReport
void 
DQtOpticalSystem::OnPrintPreview()
{
#ifndef QT_NO_PRINTER
    // создаем принтер и задаем параметры по умолчанию
    QPrinter printer;
    printer.setOrientation(QPrinter::Portrait);
    printer.setPaperSize(QPrinter::A4);
    printer.setPageMargins(20, 20, 20, 20, QPrinter::Millimeter);
    // создаем стандартный диалог для PrintPreview
    QPrintPreviewDialog qPrintPreview(&printer, this, Qt::Window);
    // устанавливаем функцию PrintReport в качестве обработчика события печати для диалога qPrintPreview
    connect(&qPrintPreview, SIGNAL(paintRequested(QPrinter *)), SLOT(PrintReport(QPrinter *)));
    // вызываем диалог qPrintPreview
    qPrintPreview.exec();
#endif
}
//-------------------------------------------------------------------------------------------------
// печать отчета в принтер roPrinter_p
void 
DQtOpticalSystem::PrintReport(QPrinter* poPrinter_p)
{
    // устанавливем курсор - песочные часы
    QApplication::setOverrideCursor(Qt::WaitCursor);
    // параметры страницы принтера
    QRect &qPageRect=poPrinter_p->pageRect();
    // создаем QPainter, связанный с принтером
    QPainter qPainter(poPrinter_p);

    // документ html, в который будет записан отчет
    QTextDocument qTextDoc;
    qTextDoc.setTextWidth(qPageRect.width()); 
    qTextDoc.setDocumentMargin(0); 
    // текст для начала и конца документа html
    QString sHtmlHeader="<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"></head><body>";
    QString sHtmlFooter="</body></html>";
    //-----------------------------------------------------------------------
    // создание html-таблицы конструктивных параметров
    QString sTable=( "<h2>Конструктивные параметры</h2>");
    // заголовок таблицы
    sTable+="<table width=100% border=1 cellpadding=0 cellspacing=0><tr>";
    sTable+="<td width=\"10%\">№</td>";
    sTable+="<td width=\"23%\">Радиусы кривизны</td>";
    sTable+="<td width=\"23%\">Осевые расстояния</td>";
    sTable+="<td width=\"22%\">Световые высоты</td>";
    sTable+="<td width=\"22%\">Показатель преломления</td></tr>";
    // каждая строка таблицы - одна поверхность О.С.
    for(int i=0; i<m_oSystem.size(); ++i)
    {
        sTable+="<tr>";
        sTable+="<td width=\"4%\">" + QString::number(i) + "</td>";
        sTable+="<td width=\"24%\">" + QString::number(m_oSystem[i].r) + "</td>";
        sTable+="<td width=\"24%\">" + QString::number(m_oSystem[i].d) + "</td>";
        sTable+="<td width=\"24%\">" + QString::number(m_oSystem[i].h) + "</td>";
        sTable+="<td width=\"24%\">" + QString::number(m_oSystem[i].n) + "</td>";
        sTable+="</tr>";
    }
    sTable+="</table><br>";   

    // печатаем номер страницы и общие параметры документа
    PrintPageHeaderFooter(qPainter, qPageRect, 1);

    //-----------------------------------------------------------------------
    // создание html-заголовка для внешнего вида OC
    QString sDrawLens=( "<h2><br>Оптическая схема</h2>");
    // вычисляем размер изображения О.С. таким образом, чтобы изображение 
    // заняло 0.5 страницы в высоту и всю страницу в ширину
    int iPictHeight=qPageRect.height()/2;
    int iPictWidth =qPageRect.width();

    //-----------------------------------------------------------------------
    // проверяем, помещается ли все на одну страницу и печатаем html-документы
    // устанавливаем текст страницы в html в документ qTextDoc
    qTextDoc.setHtml(sHtmlHeader + sTable + sDrawLens + sHtmlFooter);
    // определяем высоту получившегося документа
    int iPrevHeight=qTextDoc.size().height();

    // проверяем, помещается ли все на одну страницу
    if((iPrevHeight + iPictHeight) <= qPageRect.height())
    {
        // если поместилось:
        // печатаем таблицу и заголовок рисунка в qPainter, в область страницы
        qTextDoc.drawContents(&qPainter, QRect(0,0, qPageRect.width(), qPageRect.height()));
    }
    else
    {
        // если не поместилось: 
        // печатаем только таблицу в qPainter, в область страницы
        qTextDoc.setHtml(sHtmlHeader + sTable + sHtmlFooter);
        qTextDoc.drawContents(&qPainter, QRect(0,0, qPageRect.width(), qPageRect.height()));
        
        // переходим на новую страницу 
        poPrinter_p->newPage(); 
        // печатаем номер страницы и общие параметры
        PrintPageHeaderFooter(qPainter, qPageRect, 2);

        // печатаем заголовок рисунка в qPainter, в область страницы
        qTextDoc.setHtml(sHtmlHeader + sDrawLens + sHtmlFooter);
        qTextDoc.drawContents(&qPainter, QRect(0,0, qPageRect.width(), qPageRect.height()));
        // пересчитываем высоту последней страницы
        iPrevHeight=qTextDoc.size().height();
    }

    //-----------------------------------------------------------------------
    // рисуем оптическую систему в qPainter
    // устанавливаем область рисования
    qPainter.setViewport(0, iPrevHeight, iPictWidth, iPictHeight);
    // рисуем О.С. в созданном qPainter
    DrawOs(qPainter);
    //-----------------------------------------------------------------------
    //  возвращаем обычный курсор
    QApplication::restoreOverrideCursor();  
}
//-------------------------------------------------------------------------------------------------
// печать параметров страницы в rqPainter_p
// rqPageRect_p - область рисования основной страницы, параметры страницы будут рисоваться над и под ней
// iPageNum_p - номер страницы
void 
DQtOpticalSystem::PrintPageHeaderFooter(QPainter& rqPainter_p, QRect &rqPageRect_p, int iPageNum_p)
{
    // печатаем верхнюю часть страницы (линия и текст над линией)
    rqPainter_p.drawLine(0, 0, rqPageRect_p.width(), 0); 
    rqPainter_p.drawText(0, -rqPainter_p.fontMetrics().ascent()+5, 
        "Кафедра Прикладной и компьютерной оптики, Университет ИТМО, http://aco.ifmo.ru");
    
    // печатаем нижнюю часть страницы (линия и номер страницы под линией)
    rqPainter_p.drawLine(0, rqPageRect_p.height(), rqPageRect_p.width(), rqPageRect_p.height()); 
    rqPainter_p.drawText(rqPageRect_p.width() - rqPainter_p.fontMetrics().width(QString::number(iPageNum_p)),
                         rqPageRect_p.height()+ rqPainter_p.fontMetrics().ascent()+5, 
                         QString::number(iPageNum_p));     
}
//-------------------------------------------------------------------------------------------------

Альтернативным вариантом рисования картинки может быть рисование ее в Pixmap и добавление в html в виде картинки. Такой вариант может быть удобен, если есть много мелких картинок, которые необходимо расположить в тексте или таблице:


    //-----------------------------------------------------------------------
    // создание изображения для внешнего вида OC
    QString sDrawLens=( "<h2>Оптическая схема</h2>");
    // вычисляем размер изображения О.С. таким образом, чтобы изображение 
    // заняло 0.5 страницы в высоту и всю страницу в ширину
    int lHeight=qPageRect.height()/2;
    int lWidth =qPageRect.width();
    // создаем QPixmap, в который будет записано изображение
    QPixmap qPixmap( lWidth, lHeight );
    qPixmap.fill();  
    // создаем QPainter на основе pixmap
    QPainter qPaintLens(&qPixmap); 
    // рисуем О.С. в созданном qPainter
    DrawOs(qPaintLens);
    // создаем в qTextDoc ресурс, связанный с созданным qPixmap
    QString sPict="mydata://image_01.png";
    qTextDoc.addResource(QTextDocument::ImageResource, QUrl(sPict), QVariant(qPixmap));
    // создаем html для отображения картинки
    sDrawLens+=("<p><img src=\"" + sPict + "\" width=" + QString::number(lWidth) + 
                                             " height="+ QString::number(lHeight) + "/></p>");   

    //-----------------------------------------------------------------------