I have been trying to get the QWebView printed. Initially it looked simple.
class myView:public QWebView
{
...
}
In one of the public Member Function of myView
QPrinter printer;
printer.setPageSize(QPrinter::A4);
printer.setOrientation(QPrinter::Portrait);
QPrintDialog *dlog = new QPrintDialog (&printer, this);
qDebug () <<" HoHoooo.. Going to print ";
if ( dlog->exec () != QDialog::Accepted)
{
qDebug () <<"Printing Not accepted.. :( ";
}
else
{
print(&printer);
}
The output for the print is not getting properly. Kindly suggest, if i miss something?
Check the HTML code you want to print if it conforms to the HTML specification (use a HTML-checking tool!), even though your code renders fine to the screen, print-rendering is totally different code and thus can behave differently in case your HTML page does not conform to the standard.
In case it conforms, you can check printing in Safari or any other WebKit based browser to see, if it prints correctly there.
Related
I have a label (called display) set up in javaFX, and I am trying to fill it with a char[]. For some reason, the display.setText() method is updating the contents, but not displaying in the window (it still has the filler text "label"). If anyone could help, that would be great. Here is my code:
public void display()
{
System.out.println("display");
String toPrint="";
for(int r=0;r<grid.length;r++)
{
for(int c=0;c<grid.length;c++)
toPrint+=grid[r][c];
toPrint+="\n";
}
System.out.println("");
display.setText(toPrint);
System.out.println(display.getText());
}
I assume the last line of your code prints out the expected result. The reason for your problem is probably outside the code you have shown here. There may also be a misunderstanding on your side. Calling display.setText does not immediately render the new text. This will be done with the next pulse. So if there is something else in your code which prevents the next pulse (blocks the UI-thread) then the new text will never be shown. This is of course just a guess because you do not provide enough code to confirm this guess.
I am working on an application which has quite a bit of field-validation in it. The validation works great and I am 1000000% sure the validation message popups were appearing earlier. Now I did quite a bit of work and refactoring. One of the things I changed was the way I open up Popups/Dialog. In order to have these centered over the entire application instead of the opening component I refactored the way I open dialogs. I used the source of the Alert as a base for this but extended it quite a bit as I was having other issues (Focus Manager etc.) (I am just mentioning this as I am assuming that my missing popups are related to this).
Here comes the code responsible for opening popups in my application:
public function show(realParent:Sprite,
displayParent:Sprite = null,
closeHandler:Function = null,
moduleFactory:IFlexModuleFactory = null):Dialog {
// Get the parent ...
// If none is set, use the top-level-application.
if (!displayParent) {
var sm:ISystemManager = ISystemManager(FlexGlobals.topLevelApplication.systemManager);
// no types so no dependencies
var mp:Object = sm.getImplementation("mx.managers.IMarshallPlanSystemManager");
if (mp && mp.useSWFBridge())
displayParent = Sprite(sm.getSandboxRoot());
else
displayParent = Sprite(FlexGlobals.topLevelApplication);
}
// Register for close-events, making sure the pop-up is closed.
if (closeHandler != null) {
this.addEventListener(CloseEvent.CLOSE, closeHandler);
}
// Setting a module factory allows the correct embedded font to be found.
if (moduleFactory) {
this.moduleFactory = moduleFactory;
} else if (realParent is IFlexModule) {
this.moduleFactory = IFlexModule(realParent).moduleFactory;
} else {
if (realParent is IFlexModuleFactory) {
this.moduleFactory = IFlexModuleFactory(realParent);
} else {
this.moduleFactory = FlexGlobals.topLevelApplication.moduleFactory;
}
// also set document if parent isn't a UIComponent
if (!parent is UIComponent) {
this.document = FlexGlobals.topLevelApplication.document;
}
}
// Make the dialog center itself relative to the parent.
PopUpManager.addPopUp(this, displayParent, true);
PopUpManager.centerPopUp(this);
return this;
}
What could be responsible for the Validation popups not showing up any more? Where should I look?
Chris
Ok ... so I figgured this out by myself again. I coould bang my head at the wall for taking so long for finding it though.
If I use the Spart forms, the FormItems and Forms themselves can define error text areas in order to output error messages. So as soon as the FormItem posesses a skin part with the id "errorTextDisplay" the error messages go there. I was now expecting that if there was no such part, the old notifications would be used ... nope.
After about 2-3 Hours of messing around with the code of FormItem and it's skins, I noticed that the "contentGroup" explicitly defined an attribute to suppress error tooltyips by setting showErrorTip to false. Simply removing the "errorTextDisplay" from the skin and changing the showErrorTip to true made my popups appear nicely :-)
Hopefully this post might help someone with the same problems.
my QComboBox-derived class lives in a QGraphicsScene at the bottom end of the (visible) screen - but it pops up downwards, thus out of view.
(How) is it possible to force the popup to open above the widget?
I've tried re-implementing showPopup like this:
void MyComboBox::showPopup()
{
QAbstractItemView *popupView = view();
popupView->move(0,-100);
//popupView->window->move(0,-100);
QComboBox::showPopup();
}
The result is, that the content seems to be shifted, but not the underlying popup object.
I think it might be possible to find a solution with styles as indicated in
this article, but I can't find any Styles control that might be helpful here. I am rather new to C++ as well as Qt, so I might be missing something obvious.
I'd appreciate any help on this matter!
Best regards,
Sebastian
With the information found here, I was able to get it done this way:
void SteuerQComboBox::showPopup() {
QComboBox::showPopup();
QWidget *popup = this->findChild<QFrame*>();
popup->move(popup->x(),popup->y()-this->height()-popup->height());
}
Note that it's crucially important to call the base classes "showPopup" first.
Thanks to everybody who was reading my question and thinking about it!
user1319422's solution isn't bad, but it has two problems.
If your platform has GUI animation, the listbox will animate opening downwards, then is moved above the text box.
If you disable combobox animation (or you don't have it), the call to QComboBox::showPopup() still makes the GUI element start to appear on the screen already. So, moving it there would cause it to flicker as it appears in the first place and moves to the next.
So, to address the first problem, I just switched off animation:
void MyComboBox::showPopup()
{
bool oldAnimationEffects = qApp->isEffectEnabled(Qt::UI_AnimateCombo);
qApp->setEffectEnabled(Qt::UI_AnimateCombo, false);
QComboBox::showPopup();
qApp->setEffectEnabled(Qt::UI_AnimateCombo, oldAnimationEffects);
}
Then, for the second problem, I moved the frame in the Show event:
bool MyComboBox::eventFilter(QObject *o, QEvent *e)
{
bool handled = false;
if (e->type() == QEvent::Show)
{
if (o == view())
{
QWidget *frame = findChild<QFrame*>();
//For some reason, the frame's geometry is GLOBAL, not relative to the QComboBox!
frame->move(frame->x(),
mapToGlobal(lineEdit()->geometry().topLeft()).y() - frame->height());
}
}
/*else if other filters here*/
if (!handled)
handled = QComboBox::eventFilter(o, e);
return handled;
}
if you want to force popup to open above only when it is out of view you can do this:
void SteuerQComboBox::showPopup() {
QComboBox::showPopup();
QWidget *popup = this->findChild<QFrame*>();
if((popup->y() + popup->height()) > this->window()->height())
popup->move(popup->x(),popup->y()-this->height()-popup->height());
}
i'm pulling my hair out. need to print html generated invoices from a distant server, using
the print class, event if bitmap is set as false, will render the invoice a bitmap. at least the text is blurry and not usable. alivepdf could be a solution but i need to print straight, not save the pdf locally. i don't even understand, giving the fact this print class sucks badly, flex won't allow a simple javascript print function from the remote page.
i beg for some help here !
thank you
Why don't you use the browser to print?
Here's an example:
Put this in your index.html template:
<script language="JavaScript">
function printPage(htmlPage)
{
var w = window.open("about:blank");
w.document.write(htmlPage);
w.print();
w.close();
}
</script>
Put this in your Flex Project. What you're doing is checking to see if you have access to ExternalInterface to have access to the browser. Then you're going to use the ExternalInterface static method of "call" to call the javascript:
import mx.controls.Alert;
import flash.external.ExternalInterface;
public static function PrintHtmlPage(pHtmlPage:String):void
{
if (ExternalInterface.available)
{
try
{
ExternalInterface.call("printPage",pHtmlPage);
}
catch (error:SecurityError) { Alert.show("Security Error"); }
catch (error:Error) { Alert.show("Error");}
}
else { Alert.show("ExternalInterface not avalible");}
}
Now the user can print clean html from their browser!
http://cookbooks.adobe.com/post_How_to_print_in_Flex_using_browser_capabilities-11468.html
EDIT:
If you are using AIR and need to do this, you can try using AlivePDF and following this tutorial:
use alivepdf (http://alivepdf.bytearray.org/), and look at this tutorial for printing from AIR (http://murrayhopkins.wordpress.com/2011/01/07/using-alivepdf-to-print-from-air-javascript-via-actionscript3-part-1/)
parse the HTML into Spark components, and then add them as a Sprite, then use printAsBitmap = true in your option, and FlexPrintJob
I'm using AlivePDF to create a PDF file, then save it to the desktop. I can then use an HTMLLoader to display my lovely PDF file.
Now, the print button in Adobe Reader works fine. However, there will be young children using the app, so I'd like to have a big "Print" button right above it.
I figured I could just start up a print job and feed it my HTMLLoader. This won't work because the HTML loader rasterizes the content.
Any suggestions?
One answer I have found in order to solve this problem is called Cross-scripting PDF content. The idea is that a PDF can have embedded JavaScript, which can be called from the JavaScript within the HTML page "housing" said PDF (object tag only, no embed).
This site was of particular help. I had to simplify the JavaScript from that page down quite a bit. I kept getting syntax errors.
I also need my program to generate the PDF and the HTML content. I cannot ship a single PDF with embedded JS and an HTML file pointing to it. They need to be dynamically generated by the user. Here is a basic rundown:
private function printText(text:String):void
{
var p:PDF=new PDF(Orientation.PORTRAIT, Unit.MM, Size.LETTER);
p.addPage();
p.addText(text, 100, 100);
p.addJavaScript(this.getJavascript());
var f:FileStream=new FileStream();
var html:File=File.desktopDirectory.resolvePath("exported.html");
f.open(html, FileMode.WRITE);
f.writeUTF(this.getHtml());
f.close();
var file:File=File.desktopDirectory.resolvePath("exported.pdf");
f.open(file, FileMode.WRITE);
var bytes:ByteArray=p.save(Method.LOCAL);
f.writeBytes(bytes);
f.close();
Now that we have our two files, HTML and PDF, we can view the PDF, and create a giant purple print button for our younger / sight-impared users.
if (HTMLLoader.pdfCapability == HTMLPDFCapability.STATUS_OK)
{
var win:PrintTitleWindow; //the window w/giant button
var htmlLoader:HTMLLoader=new HTMLLoader();
var url:URLRequest=new URLRequest(html.url);
htmlLoader.width=880;
htmlLoader.height=(appHeight - 150); //i figure out the height elsewhere
htmlLoader.load(url);
var holder:UIComponent=new UIComponent();
holder.addChild(htmlLoader);
win=PrintTitleWindow(PopUpManager.createPopUp(mainWindow, PrintTitleWindow, true));
win.width=900;
win.height=(appHeight - 50);
win.addChild(holder);
win.addContent(htmlLoader);
PopUpManager.centerPopUp(win);
}
}
Here is the JS and HTML I used. I'm adding these in here for laughs. I'm sure there is a better way to do this, but I'm tired and it is late.
private function getJavascript():String
{
return 'function myOnMessage(aMessage) { print({ bUI: true, bSilent: false, bShrinkToFit: true }); } function myOnDisclose(cURL,cDocumentURL) { return true; } function myOnError(error, aMessage) { app.alert(error); } var msgHandlerObject = new Object(); msgHandlerObject.onMessage = myOnMessage; msgHandlerObject.onError = myOnError; msgHandlerObject.onDisclose = myOnDisclose; this.hostContainer.messageHandler = msgHandlerObject;';
}
private function getHtml():String
{
return '<html><head><script>function callPdfFunctionFromJavascript(arg) { pdfObject = document.getElementById("PDFObj");pdfObject.postMessage([arg]);}</script></head><body><object id="PDFObj" data="exported.pdf" type="application/pdf" width="100%" height="100%"></object></body></html>';
}
The PrintTitleWindow is a simple title window with the print button on it. The code to print is simple.
myHtmlLoader.window.callPdfFunctionFromJavascript('Print');
Eh Voila! I have a gigantor-print-button like so:
(source: cetola.net)
Hitting that big purple print button is the same as hitting the print icon in the PDF toolbar. The difference for me is that my users, who could be elementary or middle-school kids, won't have to look around for the stupid button.
So, it's a long way around the block. Still, if you need to print and can't rely on that adobe toolbar button, here's your answer :) .