Flex TileList itemrenderer + scroll = HELL - apache-flex

I'm going insane over this issue. Basically, I have a TileList with a custom item renderer that has a TextInput in it. Let's say that the list can show 4 items at once, if there are 5 items and I edit the text on the first one, the fifth will be edited also. In general if an item is out of view, it will be change when I edit one that is showing.
Also, I had overriden the TileList class to expose the rendererArray property (so that I could access the texts on each renderer) but it will only return the renderers which are displayed.
Any help is appreciated. I need to know how to override this weird behaviour with itemrenderers that aren't currently displayed. Thanks.

Ok, if anyone runs into a similar issue, here is what you need to do:
First of all, avoid trying to iterate through the itemrenderers like I did. If you need a TextInput or another control on your TileList, make sure that these controls are bound to a property on your data object, otherwise off-screen items will have incorrect values since their itemrenderers will be recycled from the items that left the screen when you scrolled.
If you think it through, any requirement can be solved by iterating through the dataprovider instead of the itemrenderers.
Also, if you try to expose the rendererArray property like I did, notice that you will only be able to iterate through the itemrenderers that are currently displayed, since those that would belong to the items that are off-screen will not be created yet.
I hope this wasn't too confusing..

Related

Flex 4.6 Mobile - how to know which itemrenderer is visible

I have a sparks List with the following attributes:
verticalScrollPolicy="off"
horizontalScrollPolicy="on"
pageScrollingEnabled="true"
scrollSnappingMode="leadingEdge"
and inside is an ItemRenderer that takes up a full screen for each item. So basically it is a horizontal list that lets you swipe left and right one page at a time. Note the scrollSnappingMode is on, so the pages always snap perfectly on the page.
Also, I am setting "useVirtualLayout=true" on the Layout, so I have virtual ItemRenderers that are getting recycled.
My question is this: how do I know which ItemRenderer is currently on the screen? Is there an event or property to watch that lets me know when this page has snapped into view and is the currently visible page?
how do I know which ItemRenderer is currently on the screen?
In the situation you describe, which uses Virtual Layouts and only one element displayed on screen at a time; there will only be a single itemRenderer.
You can access the dataProvider element of the itemRenderer using the data property on your itemRenderer.
You can find the index of your data in the dataProvider using the itemIndex property on the itemRenderer.
If you want to know when the list changes from the component that contains the list; you may try listening to the change event; but I'm not sure if that will give you want you need; as it is possible to scroll without selecting a new item.

How to update a QLayout and get the new dimensions before returning?

This is driving me nuts. I have a custom menu class that, when set visible, shows a list of items located in a particular folder. When a hardware button is pressed, my application gets the latest list of items, populates the menu with them, and returns.
The menu displaying these items uses a QListWidget filled with custom widgets. Each of the widgets contains one or more QLabels in a horizontal layout, and is created at the time the menu is shown. In order to adjust the text displayed based on the menu width available, I need to get the size of the QLabel AFTER it has been resized according to the layout, but before the menu becomes visible to the user. The problem is, my layout does not get updated until all of the functions constructing my list return.
I have tried QApplication::ProcessEvents() and the layout update functions, but none of them have updated the values of my QLabels before returning. I can set a QTimer when the button is initially pressed, and have it show the menu, update the items, and stop itself, but that seems like a terrible solution.
Any help would really be appreciated! I've spent most of a day on this.
Marlon
I had this exact problem and could not find an answer anywhere on the Internet. Calling Layout.update(), Layout.activate(), or widget.adjustSize() (all suggested in various places) all did not work.
I had a widget with a vertical layout that I wanted to add a QLabel to and then immediately use the size of the QLabel.
The only thing that worked reliably was
layout->addWidget(myLabel);
myLabel->show();
size = myLabel->size();
It would seem that layouts will just not recalculate until you either return from a function and allow the Qt event loop to progress or manually call show() yourself.
How to update a QLayout and get the new dimensions before returning?
Don't. You're not meant to do that. It'll drive you "nuts" because you're doing it backwards. Layout updates are handled asynchronously from the event loop. Instead of getting layout dimensions right away, set yourself up to be part of the system. Some options are:
Implement a custom widget that will interact properly with the layout, growing to fill the available width of the layout. Perhaps all you need is a size policy and a way to elide text?
Make a custom layout that takes the special properties of your use case into account.
You want to call QWidget::adjustSize() on your parent widget. This will force the layout recalculations.
Have you tried using layout()->update(); ?
I've tried many but nothing works for me on Qt 5.15.
Only invented little patch - create timer and get size after 20 msec:
QTimer::singleShot(20, this, [this]
{
const auto height = myLayout->contentsRect().height();
// ...
});

Flex 4: Item renderer and setting values for named objects (Odd Bug)

I have a custom component as an item renderer.
In this renderer there is an item called dlFirstChoice.
Now when I add more items to this list and force the list to rebuild itself something odd happens.
Part of the creation of the renderer I set a default selection for the DropDownlist as follows: dlFirstChoice.selectedIndex=0
The problem is once I have more than one item to render from my dataset this property stops working.
So if my dataset has only 1 item to render the drop downlist sets itseld up properly, the momment I need to render more than 1 copy of my item renderer, all of a sudden nothing gets set for dlFirstChoice.selectedIndex. Its almost as if the namespace fails partially.
This is very odd behavior any ideas?
Please and thank you.
Craig
Turns out using DataChange is a very bad Idea, I moved my functions to creationComplete as the initilisiasing event then all of a sudden it took :)
Thanks for all those who looked or tried to help.

Flex/AS3 easy (I hope) drag and drop question - prevent dragging to other controls

I searched but couldn't find my answer, I'm sure it's easy for anyone with a little experience. I have multiple datagrids on a page, each one I want sortable with drag and drop, but I don't want items drug from one control to the other. How can I prevent a user from dragging an item out of a conrol. I would prefer to have it just stop moving with the mouse, but I am prepared to just completely cancel out of the dragging if need be.
I was trying to do something like this
dragExit="dragEvent.CANCEL"
This is obviously wrong, but I can't find the correct way to do it.
Thanks in advance.
~Mike
Ok, so you have an app with multiple drag/drop datagrids, and you only want items dragged within a datagrid, and not from 1 to the other, is how I understand this.
What you need to do is create a custom dragDrop event handler for each datagrid which has the following command: event.preventDefault(). This in effect will stop a datagrid from receiving items from another .
This does not prohibit the dragging an item outside its host's borders, but it will prohibit the item being dropped into a different datagrid.
HTH.

Flex datagrid control with expanding rows

I'm looking for a DataGrid with expandable rows implementation in Flex. I don't want to use Advanced DataGrid control because it's too slow and too complex.
The desired behavior is like this: when you click a row, a panel opens between the rows with some details and the rest of the rows are moved down, and when you click again the panel is closed and the rows are back to normal. If you click the other row, the one that was expanded collapses and the row you clicked is expanded.
You'll probably need to use a custom ItemEditor that responds to clicks and expands itself.
The variableRowHeight property may need to be set to true as well.
The behavior you are describing sounds an awful lot like an Accordion component, though that doesn't quite sound like what you are looking for. Another approach would be to use a List component with a custom itemRenderer that is expanded when in the selected (clicked) state, and collapsed when not selected.
We extended Flex Datagrid component and used custom item renderer for this. We actually expand one cell and resize it to cover all other cells in the same row. While this may be not the easiest solution it works and the Datagrid is very fast.

Resources