when is the proper time to call UIObject.getOffsetWidth? - css

i want get the uiobject's offsetwidth in gwt. but this value depends:
where the uiobject attached or not?
where relative css loaded or not?
uiobject's size may be modified in onload callback.
...
so, things get complicate, especially when you want get this value of FlowPanel,Label,InlineLabel,etc.. which size is dynamically calculated.
my question: when or how to get offsetwidth properly?

You can get the correct size only after the page is completely rendered. Otherwise you will get zero values. Typically, there are two use cases:
(A) Tell the browser to render your view. Then use Scheduler to make sure the browser has finished rendering, before you check for sizes:
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
#Override
public void execute() {
int width = myPanel.getOffsetWidth();
// do something with this width
]
]
(B) Attach a resize handler to a Window. If a user changes the browser's window size, all width and heights may change. You don't need to use a Scheduler in the ResizeHandler - a browser will complete re-rendering the page before calling the ResizeHandler.

Related

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();
}
}

How do you make Interface Builder respect a custom view's intrinsic content size in constraint based layout?

Interface Builder in XCode 4.5 respects the intrinsicContentSize for some views, e.g. NSButton, but I can't convince it to respect it on my own custom subviews. This causes IB to add extra constraints trying to force the layout drawn in IB, which then causes the intrinsic sizes to not be used when the program is run.
For example, consider a button centered in a window, and a custom view centered in a window…
You can see that the custom view gets four constraints, presumably because IB doesn't know the view's intrinsicContentSize. You can change which extra constraints are added, e.g. you can force it to be width and height instead, but you can't delete them.
I'm coping with this now by searching and deleting the extra constraints in my awakeFromNib, but there must be a better way to do this.
Set a placeholder intrinsic content size — a "guess," if you will — in Interface Builder.
Select your custom view.
Show the size inspector (⌘Shift5).
Change the "Intrinsic Size" drop-down from "Default (System Defined)" to "Placeholder."
Enter reasonable guesses at your view's runtime width and height.
These constraints are removed at compile-time, meaning they will have no effect on your running app, and the layout engine will add constraints as appropriate at runtime to respect your view's intrinsicContentSize.
How to actually do this, 2019
import UIKit
#IBDesignable class TagPerson: ShadowRoundedImageView {
override var intrinsicContentSize: CGSize {
var s = super.intrinsicContentSize
s.height = 40
s.width = 40
return s
}
override func prepareForInterfaceBuilder() {
invalidateIntrinsicContentSize()
}
}
However, there is a problem. Xcode is buggy. You can sometimes reset it by:
The above will of course work flawlessly at runtime. But it randomly fails to work in interface builder (even with 11+).
To make it cycle, try
The usual 'Refresh all views'
Attach and delete a pointless constraint to one of your intrinsic size views. (I've noticed if you have a number of them, doing this to one is usually enough to make Xcode cycle, then they all work.)
And finally:
Xcode has an "intrinsic size placeholder" feature.
Select one or more of your intrinsic-size elements. Toggle the bizarre placeholder thing back and fore a few times. Often that makes it cycle and the view will then work correctly.
At worst, restarting Xcode with the usual clean-everything will, sometimes, get it working.
Ok, the point here is to make Xcode use the intrinsicContentSize of your custom view in IB.
This can be achieved by adding a placeholder view inside your custom view in IB with a fixed width and height (you can center it horizontally and vertically as well)
Then select your custom view and tap "Size To Fit Content" form the Edit Menu in IB.
At this point all extra size defining constraints will be deletable leaving only positioning ones.
That way IB will size your custom view to fit the placeholder view and and Autolayout would depend on your view's override of - (CGSize)intrinsicContentSize in run time to determine your custom view's size.
Last step is to delete the placeholder view to allow your view to display its content and size correctly:
- (void)viewDidLoad
{
[super viewDidLoad];
[_placeholderView removeFromSuperview];
}
I know this is a hack but hopefully it helps you.

Resize DataGrid When Shown

I'm trying to write my flex application so that it restores the user's settings when it starts up. The application has 3 data grids (only one is visible [on screen] at any time) and I simply save the state of the grids if the user ever does any resize events.
Saving the state works perfectly, the problem comes when restoring. It seems that only the visible data grid gets restored properly. On all the other grids, the widths are all wrong and do not match the settings I restored from.
The problem is that, when the application starts, the data grids are not sized correctly. Each data grid takes up the full screen, but initially they are only given a very small size (ie. 200 width)
Is there some way to force the data grid to resize properly when it is created? Or is it possible to know when the data grid is "maximized" I don't want to hook up to the resize event - if possible - because I would get that quite frequently, and I only want to restore the settings once.
Here's the code I'm using to restore the column widths:
var grid:DataGrid = ...;
... for each column ...
... parse width into width (ie. width is now "320")
// If it's in the config, it's visible
col.visible = true;
col.width = width;
... After loop ...
grid.invalidateSize();
grid.invalidateDisplayList();
Edit:
Here's the info you guys requested:
The settings are saved into a database (the flex proejct is connected to JBoss). I simply save a CSV type thing with the column's name and it's width. I know this works because the one data grid that is visible when the application starts gets sized correctly.
Yes, the grids use relative sizes (ie. 100%) -- I can't really change that because I want the grid to take up all available space in its container -- and I want the user to be able to resize their browser and still have it look right.
Each grid is contained in its own Hbox
The data grids are created when the application starts -- you can only see one of them though. They are in a tab navigator type thing, but it's creation policy is set to "all" so they can be populated with data (the population takes some time, and typically the user sits on the front grid for a little while.)
I can't put my resize stuff in the creationComplete handler because I end up with the same problem. The grid's size is like 50 right after it's created (it should be like 1000, 100% of the page width) -- and then I go to set the sizes of the columns (which are obviously > 50) and the resize does nothing
A couple thoughts:
Resize during CreationComplete(): When are your datagrids being created? Can you declare a method like resizeDataGrid() when the creationComplete() event fires for the datagrid? If you are using datagrids in, say, a TabNavigator, the default creation policy is to delay component creation until the user uses the component (e.g. makes the tab active).
Fixed Sizes: Are your datagrids using a fixed size, or a relative size? Relative sizing (e.g. width='50%') of a datagrid or datagrid columns is buggy in Flex, and the best workaround is to set a pixel width of both the datagrid and the datagrid columns
Storing User Preferences: How are you storing your user preferences? Using a SharedObject to store datagrid widths is probably the best option.
Spark Containers: How are the datagrids contained? For example, do they each sit within a VGroup, or are they not contained at all? I've found that using Spark layout tools (like a VGroup) to contain your datagrids improves datagrid layout issues.
What we did was saved off the column width on initialization and then reset the widths on rerender of the grid, this will occur on the first draw of the grid and subsequent resizes.
the only problem with this was that it requires columns to be resizable but does not allow the user to resize
// saves column width - this is intended to save width percent which
// will only be available on initialization, after that I beleive widths
// will be fixed size
private function saveOffColumnWidths(columns:ArrayCollection):void
{
for each(var column:TDMSEDataGridColumn in columns)
{
originalColWidths.push(column.width);
}
}
// resets the column widths - the saved widths are assumed to be width percentages
private function resetColumnWidths():void
{
dataGrid.columns[0].width=20; // set the check col seperately
for (var pos:int=0; pos<dataGrid.columnCount-1;pos++ )
{
dataGrid.columns[pos+1].width = (dataGrid.width - 20) * originalColWidths[pos];
}
}
protected function dataGrid_renderHandler(event:Event):void
{
resetColumnWidths();
}

InvalidateSize without screen flash?

Here's the scenario: I wait for a creationComplete event to occur for an mx:Text object at which point I can access the setTextFormat method of its protected member textField. (textField is not valid until creationComplete.) At that point the text formatting done through textField.setTextFormat increases the height of the text. But the mx:Text itself does not pick up this height change until I call invalidateSize. However, in my case invalidateSize causes the entire text to be redrawn, causing it to flash on the screen. However, if I just manually change the browser window size, the Text height change is made without the text flashing like that. So how could I through a function call accomplish what is taking place when I manually change the browser window size. (I just want mx:Text to pick up the height change accomplished through textfield.setTextFormat.)
did you tried to put your textfield inside a sprite or movieclip and scale it with your callback?
to invertedspear
I was in fact able to avoid the screen flash by calling
txt1.invalidateSize();
txt1.validateNow();
immediately after the calls to txt1.ui_txtfld().setTextFormat(....)
(ui_txtfld() is how I'm making the protected property textField visible.)
However, elsewhere in my code, it was also necessary to not reference txt1.height directly, but instead,
(txt1.ui_txtfld().textHeight+4)*txt1.scaleY,
as the txt1.textField.textHeight property is valid immediately after changing the height of a textField, whereas txt1.height is not.

Why are width & height of loaded SWFLoader zero?

I have a class which extends SWFLoader, I use it like a normal SWFLoader:
var loader:MySWFLoader = new MySWFLoader();
loader.load("myFile.SWF");
myScene.addChild(loader);
The loading works OK, except that it remains 0 because the width & height never change from 0. I had to override the width/height get properties to make it work:
class MySWFLoader extends SWFLoader
{
public override function get width():Number{ return contentWidth; }
public override function get height():Number{ return contentHeight; }
}
As well as being a big hack this isn't quite correct; especially since the SWF has multiple frames and the frames are of different width/height.
Why aren't width/height working in the first place? Shouldn't they be automatically set during loading? Is it possible the issue lies with the SWF itself somehow?
Update: Changing scaleContent to true or false makes no difference.
I'm not sure if this applies for SWF loading, but whenever I'm loading content, i cannot access width and height before the whole thing is loaded.
So make an event listener that listens when the loading is completed, and then read the height/width.
Also take a look at the loaderInfo class in AS3
I'm not sure what part of the cycle you're trying to grab the height and width (and is it of the loader object or the loaded content) but you can can access the height and width of the loaded object using SWFLoader.loaderInfo.height and SWFLoader.loaderInfo.width.
By default the SWFLoader scales the content to the size of the loader, so you have to set the size of the loader. If you want the loader to scale to the size of the content then you have to set the scaleContent property to false.
SWFLoader is a UIComponent.
It needs to be run through the UIComponent framework to set its dimensions correctly
In other words, it is waiting for calls to commitProperties(), updateDisplayList(), etc.
If you drop it in your application (so that it is part of the layout framework) it should be fine.

Resources