Problems when printing a SWF in browser - apache-flex

I'm trying to print a SWF and have come across some problems.
When using the Print function in the browser, the SWF will be distorted, and not scaled correctly. So I've tried to implement a Print function using Actionscript instead.
The different approaches I've taken are:
Printing using the right click context menu of the Flash Player and choose Print. This works almost as expected, but It flattens transparent PNGs and isn't scaled correctly.
Creating a FlexPrintJob and adding the component to the job. Will not scale the component to fit the page, even though I've set FlexPrintJobScaleType.SHOW_ALL on the print job.
Creating a PrintView containing an Image. Then taking a screenshot of the component and set this as the Image in the PrintView. When this is done, I create a new FlexPrintJob and send it. This seems to work most of the times, but the scaling will distort and make small elements (like text) look really bad.
The code for printing looks like this:
var pj:FlexPrintJob = new FlexPrintJob();
if (pj.start())
{
pj.addObject(componentToBePrinted, FlexPrintJobScaleType.SHOW_ALL);
pj.send();
}
What I would like to do is to get the right click context menu to work, and by that I mean setting the scaling of the SWF. Is this possible? Are there any other alternatives when printing a SWF? What am I doing wrong?
When testing, I'm printing to a PDF, but I don't think that will change the results.

You need to scale your Print Job for what you want in FlexPrintJobScaleType:
MATCH_WIDTH
(Default) Scales the object to fill
the available page width. If the
resulting object height exceeds the
page height, the output spans multiple
pages.
MATCH_HEIGHT
Scales the object to fill the
available page height. If the
resulting object width exceeds the
page width, the output spans multiple
pages.
SHOW_ALL
Scales the object to fit on a single
page, filling one dimension; that is,
it selects the smaller of the
MATCH_WIDTH or MATCH_HEIGHT scale
types.
FILL_PAGE
Scales the object to fill at least one
page completely; that is, it selects
the larger of the MATCH_WIDTH or
MATCH_HEIGHT scale types.
NONE
Does not scale the output. The printed
page has the same dimensions as the
object on the screen. If the object
height, width, or both dimensions
exceed the page width or height, the
output spans multiple pages.
See http://livedocs.adobe.com/flex/3/html/help.html?content=printing_3.html
for more information on this.

Related

Preventing layouts from expanding beyond the window size

I'm trying to make my UI content expand nicely when the user resizes the window. I'm doing this in Qt Designer and learning about layouts and size policies.
Seems that everything is working fine for now: one layout stays within its maximum size, while another expands with the window resize, and they all stay above their minimum sizes. That's great and all, but the problem is that if I have a list with a lot of items, or if I am displaying a very large image, it will expand beyond the available window space and cause the window to be huge.
How can I specify something along the lines of "do not expand beyond the available window space"? I've played around with the size policies, but I couldn't get it to work. Is this something I need to set for the form itself rather than the layouts it contains?
I should specify this is the desired behavior: Display the widget as large as the available window, even if the widget content is too small. Expand/Shrink the widget to fill the window when the window is resized. Do not expand beyond the available window space. The widgets in question are 2 images (labels) and 1 list view.
I set the size policy to "ignored" for the respective widgets. That fixed it.
Or you can set the window maximum size.

Qt Layout, resize to minimum after widget size changes

Basically I've got a QGridLayout with a few widgets in it. The important ones are 2 labels, which I use for drawing images to the screen. Well, if the user wants, he can change the resolution of the incoming images, thus, forcing the Labels to resize.
Let's assume the initial size of the label is 320x240. The user changes the VideoMode to 640x480, the label and the entire GUI resizes perfectly. But when the user switches back to 320x240, the label shrinks, but the Layout/Window does NOT.
I've played around with sizePolicies and sizeHints, and resize(0,0), but nothing did the trick. Could somebody help me with this?
Here some screenshots to clarify the problem:
You need to set the size constraint of the layout holding all your widgets to "SetFixedSize". Although the name doesn't sound like it will work, it ensures that your layout will only use the space it needs. You will not have the problem like you do in your second screenshot.
Example:
mainLayout.setSizeConstraint(QLayout::SetFixedSize);
QLayout::setSizeConstraint(QLayout::SetFixedSize) solves this problem well when you prefer keeping your widget's size fixed at all times--that is, if you'd like it to always be fixed to its "packed" size (which may still vary as the child widgets change size). That is what the "fixed" means there: "fixed" to the correct size, even as the latter varies. (In Qt terms, what I'm calling the "packed" size is simply the widget's sizeHint.)
But a constraint may be too strong a solution in some instances. In particular, if you apply it to a top-level window, then the user will not be free to resize the window. If you don't like that, you can instead perform the "set size to sizeHint" operation instantaneously each time it's needed, rather than imposing it as an unrelenting constraint. The way to do that is to call QWidget::adjustSize().
http://doc.qt.io/qt-5/qwidget.html#adjustSize
Note that if the container whose children are changing size is not the top-level window, then adjustSize() may have to be called recursively on the container and its parents. (In my case I had to do that, anyway. I also tried the size-constraint scheme, and found that applying the constraint at only the topmost level was successful in compacting all levels. I haven't enough knowledge of Qt to comment usefully on these observations, so I merely share them.)
You need to store the original size of your widget parent window before applying any changes to the layout and restore it when the user switches back to the original.
Notice that you need to work with the widget parent window size and not the widget parent size.
in your widget before applying the layout changes:
minimumWindowSize = this->window().size();
when you finished reorganizing the widget to the compact size
this->window().resize(minimumWindowSize);
So that is exactly what i'm doing in mu project.
Resolution os doesn't matter. I have only to have a widget for rendering video, or image in your case.
void MainWindow::resizeEvent(QResizeEvent* event)
{
QMainWindow::resizeEvent(event);
if ((player != 0) && ((player->isPlaying()) || player->isLoaded() || player>isLoaded())){
renderer->resize(ui->mainVideoWidget->width(),ui->mainVideoWidget->height());
resizeFilter();
}
}

Flex: Auto-resize contents of a group to fit a printed page

I have a large Group which contains two rulers and labels for distances, and a varied amount of smaller groups consisting of images and labels. Now my task is to print the large group on a page with a header and a footer. The large group extends outside the edge of the page and pushes the footer off the page. If I was printing just the Group, I could use
printJob.addObject(myView, FlexPrintJobScaleType.SHOW_ALL);
to fit it all on one page, but that would scale the header and footer as well, which I don't want - I'll be printing more pages and want the header and footer sizes to stay the same.
Is there a way to scale only the group and its contents automatically before printing?
arkward... you'd probably have to scale the group before adding it to your print job, which means you are doing to have to do lots of calculations about resolutions, DPIs, etc
The property to change is http://help.adobe.com/en_US/FlashPlatform//reference/actionscript/3/mx/core/UIComponent.html#scaleY
but working out what to scale by is a much harder job.

Making a Flex DataGrid scroll smoothly

I've noticed that the default behaviour for a DataGrid's vertical scroll bar is to scroll one row at a time. This is all well and good when the rows are all uniform and small (e.g. displaying a single line of text), but gets really ugly as soon as you have rows with variable heights.
I'm curious, is there a way to make DataGrid scrolling "smooth"? For instance, is there a way to have the DataGrid scroll by a set number of pixels, lines of text, etc. rather than scrolling one row at a time?
So far, the only solution I've managed to come up with is to place the DataGrid in a Canvas and have the Canvas do the scrolling instead of the DataGrid. The issue with this approach, though, is that as soon as the Canvas scrolls far enough, the DataGrid headers scroll off-screen. Ideally, I'd like to get the smooth-scrolling nature of the Canvas, but also keep the DataGrid headers visible. Is that possible?
The way that ItemRenderer's work in Flex 3 makes smooth scrolling difficult to achieve. Basically Flex recycles item renderers scrolled off of the top of the list as the display objects used for new data at the bottom of the list. Adobe's implementation of most list components in Flex 3 creates and adds these items as they come on to the screen rather than just off the screen, so they "pop in" and smooth scrolling isn't available. I'm not sure why they couldn't have done it in a similar manner for items +/- one position above or below the current scroll pane, but they didn't, and we're stuck with sticky scrolling by default.
Work-arounds do exist, though the one you've noted (dropping the datagrid into a canvas) negates the display-object saving intention of item renderers and incurs a performance cost. This will be fixed for most list-based Flex components in Flex 4, though it won't be fixed immediately for DataGrid. The DataGrid / AdvancedDataGrid component is maintained by a separate team based in India, last time I heard, and so it tends to be a bit behind the rest of the SDK.
I'd recommend trying something similar to this implementation of a smooth-scrolling list by Alex Harui. I'm not sure exactly how well it'd work for DataGrid or AdvancedDataGrid, but this is the most intuitive technique I can think of for making the list scroll correctly.
Try this... It's still based on Alex's code that was mentioned above. His should still be a great start for removing the snap-to-row behavior. Original source:
http://blogs.adobe.com/aharui/2008/03/smooth_scrolling_list.html
Alex's original some code for smooth vertical scrolling but that was not an issue I had with the DataGrid. It was smooth scrolling horizontally that I needed. I am using the DataGrid in an unorthodox manner for analyzing plain text reports output by our database (great way of providing visual feedback on a document). The code below allows content to go off screen and the user can scroll without that snap-to-column behavior.
You can adapt this to use the same math routines for vertical scrolling and then it will make scrolling possible and ignore the snap to row behavior. In particular switch the usage of the listContent.move method to move the contents vertically and use a inverse of the rounded pixel value you calculate from the vertical scroll bar (as opposed to my using the horizontal).
This method is bit simpler than Alex's method from the link above - a lot less code so try adapting and see how it works.
override protected function scrollHandler(event:Event):void
{
// Override the default scroll behavior to provide smooth horizontal scrolling and not the usual "snap-to-column" behavior
var scrEvt:ScrollEvent = event as ScrollEvent;
if(scrEvt.direction == ScrollEventDirection.HORIZONTAL) {
// Get individual components of a scroll bar for measuring and get a horizontal position to use
var scrDownArrow:DisplayObject = horizontalScrollBar.getChildAt(3);
var sctThumb:DisplayObject = horizontalScrollBar.getChildAt(2);
// I replaced maxHorizontalScrollPosition in Alex's code with "1300" to fix my exact application. In other situations you may finding using some property or different value is more appropriate. Don't rely on my choice.
var hPos:Number = Math.round((sctThumb.y - scrDownArrow.height) / (scrDownArrow.y - sctThumb.height - scrDownArrow.height) * 1300);
// Inverse the position to scroll the content to the left for large reports
listContent.move(hPos * -1, listContent.y);
}
// Go ahead and use the default handler for vertical scrolling
else {
super.scrollHandler(event);
}
}

How do I set the line height of a FormattedText

I am building a text-to-image generator that takes a text, a font, a max width and some other parameters and generates an image from this. It will be used as a custom server control in a web site to generate headlines.
I allready have a component like this which uses GDI+. The problem with this is that GDI+ is incapable of setting line height which means I have to render the text first and then copy the resulting rows into a new Bitmap using the line height I want.
I am now looking at using WPF components instead and have managed to create text images using FormattedText. The problem is that I still cannot set line height. Is there a way to do this? If I could set letter spacing as well, that would be even better.
You should just be able to set the LineHeight property, is that not working?

Resources