Unity/NGUI Updating List at runtime - unity3d

I was wondering if someone could explain to me how I update a list at runtime in Unity?
For example I have a spell book, which has 3 spells in it, when I drag them to my action bar they get re-parented to it, what I'm trying to do is get a list of each child under the actionbar transform,
My problem is where to actually do something like this if I try something like below in the update, it adds whatever's there many times, which I can understand since update runs every frame..
list = actionbarui.GetComponent(UIGrid).GetChildList();
for(var i =0;i < list.size; i++)
{
buttonList.Add(list[i].gameObject);
}
If I add a callback to the buttons so that whenever they're drag and dropped it runs the above code and add thing's additively, as in, if you drag just one "spell" on it will loop through once, which is fine, but as soon as you add another it loops through three times, that is, it already has one it then adds the same one again PLUS the new button that's just been dragged on for a total of 3.
I've tried changing the code to
list = actionbarui.GetComponent(UIGrid).GetChildList();
for each(var child : Transform in list.GetEnumerator())
{
buttonList.Add(child.gameObject);
}
But this simple doesn't add anything, I am unsure how to go about keep the lists update as they are dragged off and on, could anyone please explain how this is achieved?
Please ignore the second "list" code, it's implementing "BetterLists" as apart of NGUI, so doesn't follow standard list methods.
Thank you for reading

If I add a callback to the buttons so that whenever they're drag and dropped it runs the above code and add thing's additively, as in, if you drag just one "spell" on it will loop through once, which is fine, but as soon as you add another it loops through three times, that is, it already has one it then adds the same one again PLUS the new button that's just been dragged on for a total of 3.
That is the expected result here. You are running through the list of children and adding them to your buttonlist, so first time there is only one item to add, then when you add another child there are two items to add, thus resulting in three items.
Either don't have a for loop and do:
buttonList.Add(the_GameObject_that_was_just_added_to_the_bar);
Or clear your buttonList before the for loop:
list = actionbarui.GetComponent(UIGrid).GetChildList();
buttonList.Clear();
for(var i =0;i < list.size; i++)
{
buttonList.Add(list[i].gameObject);
}

Alternatively to Dover8's response, you can first check if the buttonList already contains a reference to the child to be added. If it does, continue. Otherwise add the new child.
However, given the expense of doing the checks, and since you are already looping through the list already, I'd recommend that you follow his suggestion to clear the list before running the loop. It will probably give you the best performance out of these examples.
If there's a reason you can't or shouldn't clear the buttonList, and you still need to run through it, I'd recommend my suggestion. It really depends on which implementation works best for what you are trying to do. The point is that there are several ways to do this, and they have different performance profiles you need to consider.

Related

PyQt5 select text across multiple QTextEdit boxes

I am trying to create something similar to this in PyQt5:
https://www.screencast.com/t/1FikGosKbS
I tried using a separate QTextEdit widget for each bullet point and overriding the enter key to go to the next textbox, but I don't know how to make multiple QTextEdit widgets selectable (and able to copy paste) like in the example.
How can I allow the user to drag to select text across multiple QTextEdit boxes? Or is there a better approach to this?
I don't know this application is made from Qt or not,but I have an idea.
Parhaps you might have made the most part of this application... I can't know them from your question.I write my opinion on the premise that you don't know QText handling at all.
QTextEdit,QTextDocument,QTextCursor are used fully.
1.To understand block.
2.To use QTextBlockUserData(If you want.)
3.To use QGraphicsItem as nodes.
4.To go other page,we add a new QTextEdit on QStackedWidget or replace the QTextDocument of QTextEdit.
5.To make sub-nodes block,you can coordinate the indentation of blocks.
QTextBlock is a read-only data in a document.
You make QTextBlockUserData and set it to the block.
If you select multiple blocks you want to drag & drop , you use QTextCursor and movePosition methods with sequence.
The nodes of this application can not be QTextListFormat,because we cannot handle mouse click on the style.But you can insert empty-style QTextListFormat.
The truth of the nodes may be QGraphicsItem.
You can allocate it each the start position of blocks and the item can also have the block data.
It will difficult to take care of the connection between the nodes and the blocks.
In advance, you must set QGraphicsView & QGraphicsScene.
I insert many data on the container.
Which should we control with nodes or block?
My trial.
1.Nodes & Text
2.To the other page
3.Sub nodes & blocks
4.close sub nodes & blocks
My trial is incomplete,but it will be completed with endurance.
Logically,I think I can go step until the good point with these combinations.
But it will be diffcult...
These nodes are made from QGraphicsItem and allocated each Blocks.
You must calculate the position and recalculate during editing.
The mouse cursor image is deleted on these images.
It is outrange of screenshot.

Xamarin Forms SearchBar + ListView slow to update

I would like some help into speeding up the process of filtering a long list of list items and viewing them on a ListView.
My app has a search bar, a ListView and a very long list of strings to choose from.
When the user enter a search term, the ListView is updated with every key stroke and filter out the irrelevant items.
Sorting itself takes a few milliseconds, but updating the ListView afterwards with the new filter-event takes a long time (20 seconds easy, if only a single character has been entered as search criteria)
I believe the time is spent on inflating a large number of ViewCells every time the filtered list updates.
Do any of you know how to speed up the process? I thought the way it could work was to have a very limited number of ViewCells (like 10 or 20) and then have them update and just show a selection of the filtered list. Scrolling would to be reusing the top/bottom one, update the content and put it back on the bottom/top - but I have not been able to wrap my head around how to do this.
Maybe it is the wrong approach and you know a better way?
I just had a similar problem that my list with just 20 elements would search extremely slow. Maybe your problem is similar. Sadly you didn't post any code. I had something like this:
List l = originalItems.Where((i) => i.Name.Contains(filterText));
listView.ItemsSource = l;
And I could not understand why this would be so slow. I found a different approach with more overhead that for some reason is faster and more responsive and overall feels better for the user. My ListView always has an ObservableCollection as ItemsSource. When I filter I calculate the difference to this ObservableCollection (the extra items and the removed items) and then remove or add accordingly. This avoids replacing the ItemsSource property which seems to be too harsh on the ListView.
//property of the class
ObservableCollection<FlightListItem> listViewItems;
// ....
//somewhere at initialization
listView.ItemsSoure = listViewItems;
// ....
//in the filter method:
List l = originalItems.Where((i) => i.Name.Contains(filterText));
IEnumerable itemsToAdd = l.Except(listViewItems).ToList();
IEnumerable itemsToRemove = listViewItems.Except(l).ToList();
listView.BeginRefresh();
foreach (FlightListItem item in removes)
listViewItems.Remove(item);
foreach (FlightListItem item in added)
listViewItems.Add(item);
listView.EndRefresh();
Notes:
removing the listView.BeginRefresh() and EndRefresh() did not seem to impact performance, but it seems the right thing to call them here.
We need to call ToList() on the itemsToAdd and itemsToRemove even though we only need IEnumerables! This is because Except is a lazy operation and will otherwise only be evaluated during the for loop. However during the for loop one of the parameters to Except changes which leads to an IllegalArgumentException due to modifying an IEnumerable while going over it.
If anyone knows a good filterable observable collection that would probably be a nicer solution.

How to configure agGrid grouping so it works like an accordion

is it possible to configure agGrid grouping so that it behaves like an accordion i.e. only one group can be expanded and when opening new group previously opened is closed?
Not sure if this answers your question, but I am sure this might be the only direction you'll have.
There is a method provided on gridApi - onGroupExpandedOrCollapsed
So I think (again, need to check) that this function would be called as its name suggests, and you can collapse the other rows (whichever is opened) and achieve your functionality.
Be cautious while using this as there is comment given by ag-grid
we don't really want the user calling this if one one rowNode was
expanded, instead they should be calling rowNode.setExpanded(boolean)
- this way we do a 'keepRenderedRows=false' so that the whole grid gets refreshed again - otherwise the row with the rowNodes that were
changed won't get updated, and thus the expand icon in the group cell
won't get 'opened' or 'closed'.

How to change what I've set a key to do in ahk

I'm trying to make a script for a game called Hearthstone. The script will be used to press a certain button and play a certain card. The only problem I have is that the cards change position based on how many you have. So I want to know how I could make buttons to choose the amount of cards in my hand.
I've come across the Hotkeys command but it seems to be more of a toggle thing. All the cards are bound from 1-10 and was thinking that I could make it so ^1-^10 represents how many cards I have but I don't know how I could do that.
Oleg's comment was more of my answer than I thought.
setting ^1 to ^1::numCards=1 and so on, I was able to set an if statement to do what I wanted something to do when the variable numCards equated to different things. Such as:
1:
if numCards = 1
{
do thing
}
return
and so on...

QCompleter and Tab key

I'm trying to make a Completion when pressing tab, you get the first completion of all possibilities.
But, in a QWidget-based main window, pressing tab will make that QLineEdit lost focus, and completion popup hides after that.
Is there a way to fix it ?
Have you tried to subclass QLineEdit and intercept the key press event?
Alternatively you could set up an event filter.
Whew. It took me some time to figure this out :) Multiple times I have tried to solve this problem, but always gave up. Now, I dug enough to find the answer.
OP, please pardon me, because the code here is Python, but should be understandable and work for C++ as well.
Basically, the problem I had was "how to select an entry in the QCompleter"; I didn't notice before, but the answer is in the popup() method. QCompleter works with a model and a view, which contains the things to show.
You can change the current row as you wish, then get the index of that row in the model, then select it in the pop-up.
In my code, I subclassed QLineEdit, created a tabPressed signal which is emitted every time Tab is pressed. Then, connected this signal to a method of the same class which does this:
get the current index;
select the index in the popup;
advance to the next row.
As implementation, this is very trivial, but for my current purpose this is enough. Here's the skeleton (just for the tab part, it's missing the model and everything else).
class MyLineEdit(QLineEdit):
tabPressed = pyqtSignal()
def __init__(self, parent=None):
super().__init__(parent)
self._compl = QCompleter()
self.tabPressed.connect(self.next_completion)
def next_completion(self):
index = self._compl.currentIndex()
self._compl.popup().setCurrentIndex(index)
start = self._compl.currentRow()
if not self._compl.setCurrentRow(start + 1):
self._compl.setCurrentRow(0)
def event(self, event):
if event.type() == QEvent.KeyPress and event.key() == Qt.Key_Tab:
self.tabPressed.emit()
return True
return super().event(event)
You may need to adjust/fix few things, but this is the basic idea.
EDIT:
For details see
http://www.qtcentre.org/threads/23518-How-to-change-completion-rule-of-QCompleter
There's a little issue: when Return is pressed, the things don't work properly. Maybe you can find a solution to this problem in the link above, or in the referenced resources therein. I'll fix this in the next few days and update this answer.
There is probably a better solution but one that comes to mind is to change the focus policy for all other widgets on the form to something that doesn't include "tab" focus. The only options that don't use the tab key are Qt::ClickFocus and Qt::NoFocus.