Russian Qt Forum

Qt => Общие вопросы => Тема начата: phpCoder от Август 09, 2015, 21:55



Название: Создание накладной средствами Qt
Отправлено: phpCoder от Август 09, 2015, 21:55
Добрый вечер.
Получится ли создать накладную без костылей, бубной и прочего с помощью классов QText[....]? Может кто-то подобное делал. Сейчас у меня это делается через HTML+CSS. Вид накладной на картинке. Также интересует перенос части таблицы на другую страницу.
(http://www.cirota.ru/forum/images/104/104767.jpeg)


Название: Re: Создание накладной средствами Qt
Отправлено: PimenS от Август 09, 2015, 22:11
Добрый!

Просто не получится. Я рисую прямо на принтер. HTML+CSS не смог приручить.


Название: Re: Создание накладной средствами Qt
Отправлено: phpCoder от Август 09, 2015, 22:29
Ну да, создать QTextDocument. В нем произвести все действия, далее создать принтер - указать PDF формат и название файла. Далее печать.

С помошью классов QText[...] все-таки можно сделать? Такую вот табличку нарисовать, подчеркивания и т.д.?


Название: Re: Создание накладной средствами Qt
Отправлено: PimenS от Август 09, 2015, 22:34
Может и можно. Я делаю по другому, через QPainter рисую сразу на QPrinter (drawLine, drawText).


Название: Re: Создание накладной средствами Qt
Отправлено: gil9red от Август 09, 2015, 22:46
Ну да, создать QTextDocument. В нем произвести все действия, далее создать принтер - указать PDF формат и название файла. Далее печать.

С помошью классов QText[...] все-таки можно сделать? Такую вот табличку нарисовать, подчеркивания и т.д.?

QTextEdit ведь поддерживает html, вот и сделаете на html табличку


Название: Re: Создание накладной средствами Qt
Отправлено: phpCoder от Август 09, 2015, 23:08
Это свойство поддерживает: border-collapse: collapse;?


Название: Re: Создание накладной средствами Qt
Отправлено: gil9red от Август 10, 2015, 00:00
Это свойство поддерживает: border-collapse: collapse;?

думаю, да

но если QTextEdit не прокатит, есть QWebView -- он не только html+css покажет, но и js выполнит )


Название: Re: Создание накладной средствами Qt
Отправлено: kai666_73 от Август 10, 2015, 15:34
А вот с границами таблицы облом выйдет. Невозможно средствами QTextEdit задать разную толщину для разных ячеек ((


Название: Re: Создание накладной средствами Qt
Отправлено: Nidxogg от Август 10, 2015, 16:59
QActiveX как вариант и запилить форму в Word
P.S. Саму форму можно как создавать самому, так и сделать в форме шаблона. Создавать документ на основе этого шаблона и программно вбивать значение полей , добавлять строки и т.д


Название: Re: Создание накладной средствами Qt
Отправлено: phpCoder от Август 10, 2015, 22:58
Я сейчас через QWebPage делаю. Вставляю в нею html-код и на печать в ПДФ файл. Только вот вопрос: а тут тогда изображение вставить? У меня все изображения в ресурсах хранятся. Может можно как-нибудь в тег IMG записать путь к изображению как-то так - :/images/myimage.png? Что QWebPage его отобразил.


Название: Re: Создание накладной средствами Qt
Отправлено: LisandreL от Август 11, 2015, 08:39
Я сейчас через QWebPage делаю. Вставляю в нею html-код и на печать в ПДФ файл. Только вот вопрос: а тут тогда изображение вставить? У меня все изображения в ресурсах хранятся. Может можно как-нибудь в тег IMG записать путь к изображению как-то так - :/images/myimage.png? Что QWebPage его отобразил.
Попробуйте встраивать картинки через data (http://"https://ru.wikipedia.org/wiki/Data:_URL").
В base64 Qt перегонять умеет.


Название: Re: Создание накладной средствами Qt
Отправлено: phpCoder от Август 11, 2015, 10:37
Ура, добил изображения.
Значит действовать можно двумя путями:
1. Использоваться встроенное изображение (embedded image), кодированное базой. Пример:
Код
C++ (Qt)
out << "<img src=\"data:image/png;base64," << QByteArray(imagePngBin).toBase64() << "\" />"
2. Использовать изображения из ресурсов:
Код
C++ (Qt)
out << "<img src=\"qrc:/путь к изображению\" />"


Название: Re: Создание накладной средствами Qt
Отправлено: phpCoder от Август 11, 2015, 10:40
И главное. В QWebPage при использовании метода setHtml() необходимо использовать сигнал loadFinished, иначе изображения в результирующем файле не появится - не успеет загрузиться.


Название: Re: Создание накладной средствами Qt
Отправлено: phpCoder от Август 11, 2015, 22:33
Сейчас столкнулся с проблемой:
Код
C++ (Qt)
QWebPage page; QEventLoop loop;
connect(&page, &QWebPage::loadFinished, &loop, &QEventLoop::quit);
page.mainFrame()->setHtml(html);
loop.exec();
page.mainFrame()->print(&printer);

Когда этот кусок выполняется в первый раз, то печать идет. Когда я нажимаю на кнопку второй раз, то приложение начинает бесконечно долго думать и печати нет. Приходится закрывать приложение и включать его заново.
Как показывает отладочная печать тупить оно начинает на строке
Код:
loop.exec();
Вопрос: какая принципиальная разница между первым проходом и вторым? Почему при первом проходе все хорошо, а при втором нет? Объекты все временные, после окончания работы функции, где записан этот кусок кода, они уничтожаются.


Название: Re: Создание накладной средствами Qt
Отправлено: Bepec от Август 11, 2015, 22:47
Как вариант происходит кеширование, оно там есть и автоматом вроде включено. Так что установив во второй раз тот же html вы вполне можете получить loadFinished ДО connect :)

PS это конечно догадка, но проблема в том что loadFinished уже пришел до коннекта.


Название: Re: Создание накладной средствами Qt
Отправлено: phpCoder от Август 11, 2015, 22:54
Чудно получается, как может что-то кешироваться, если объект, который кеширует - уже уничтожен?


Название: Re: Создание накладной средствами Qt
Отправлено: Bepec от Август 12, 2015, 02:03
Сетевые настройки глобальные как бы... Вы наверно в курсе, что динамические объекты могут обращаться к глобальным настройкам и уж скорее всего хранилище всей этой лабуды если и не глобально, то как минимум находится в каком то стандартном месте. (версия что всё держится в памяти мне не импонирует, скорее уж темповский каталог)

PS тем более как я уже и отписал это лишь предположение, полученное методом дедукции и основанное на опыте :D


Название: Re: Создание накладной средствами Qt
Отправлено: phpCoder от Август 12, 2015, 08:13
Да, Вы были правы.
Использовал стат. метод:
Код:
QWebSettings::clearMemoryCaches();
и печать повторная появилась. Но, т.к. это дело глобальное, то может можно очищать не весь кеш целиком, а только то, что было создано для печати? Не знаете? Т.е. указать путь к временным данным и удалить их.


Название: Re: Создание накладной средствами Qt
Отправлено: Bepec от Август 12, 2015, 12:02
Проще отключить кеширование, там настроечка вроде есть. Да и на мой взгляд разницы в очищении кеша и в очищении одной накладной не будет. Хотя тут уже  зависит от того, используется ли у вас webView и так далее.

PS как вариант сделайте асинхронную печать, тогда проблема кеша не будет стоять. (не используйте QEventLoop в функции, а просто сделайте класс, который не будет зависеть от скорости подачи сигнала)


Название: Re: Создание накладной средствами Qt
Отправлено: phpCoder от Август 12, 2015, 20:10
Т.е. в этом мини классе создать приватный слот печати, и соединить его через loadFinished?

Хм, может тогда сделать анонима, и его подсоединить? Тогда никаких классов делать не надо.


Название: Re: Создание накладной средствами Qt
Отправлено: phpCoder от Август 12, 2015, 23:12
Код
C++ (Qt)
...
QPrinter *printer = new QPrinter;
printer->setColorMode(QPrinter::GrayScale);
printer->setOutputFormat(QPrinter::PdfFormat);
printer->setOutputFileName(this->_invoiceFilepath());
QWebPage *page = new QWebPage(this);
connect(page, &QWebPage::loadFinished, this, [&] ()
{
    page->
             mainFrame()->
             print(
                   printer); // СИГа
});
page->mainFrame()->setHtml(html);
Там где комментарий он предъявляет SIGSEGV. Почему? Страница существует, т.к. указатель. Принтер существует, т.к. указатель. Указатели после завершения функции намеренно не стираю.

Если всю эту лабуду переписать не с анонимом, а с обычным слотом, то все нормально.


Название: Re: Создание накладной средствами Qt
Отправлено: phpCoder от Август 12, 2015, 23:34
Все, добил.
Код
C++ (Qt)
QWebPage *page = new QWebPage(this);
connect(page, &QWebPage::loadFinished, this, [this] ()
{
QPrinter printer;
printer.setColorMode(QPrinter::GrayScale);
printer.setOutputFormat(QPrinter::PdfFormat);
printer.setOutputFileName(this->_invoiceFilepath());
qobject_cast<QWebPage*>(this->sender())->mainFrame()->print(&printer);
this->sender()->deleteLater();
});
page->mainFrame()->setHtml(html);

Указатель на страницу нужен, чтобы распечаталась картинка. Если его не будет, то вместо картинки будет иконка битого изображения.
Указатель ловить не надо. Надо использовать sender(). Иначе программа убъется.