I am creating a simple TableView in QML, 5 col wide by 4 rows tall. This table connects to a QSortFilterProxyModel, which connects to a QAbstractTableModel. When I call the sort method of the QSFPM my table refreshes as expected and works great.
Now, I am trying to highlight a row of my table; the row delegate just uses BLUE as the background color instead of WHITE if that row is selected. On mouse click on the table I call my 'emitDataChanged' method in the QSFPM, and I see my "Ready to emit!" message in the debug output.
However, my table does not refresh (confirmed with console.log statements in the table). It's as if the emit signal is not reaching my table (though calling the resort method in this same class DOES cause the table to refresh).
Why is the dataChanged signal not working as expected? My emitDataChanged method is below...I can post any other code needed.
Source file companysortfilterproxymodel.cpp (descends from QSortFilterProxyModel):
void CompanySortFilterProxyModel::emitDataChanged(QItemSelection firstCellInRowToBeUpdated) {
QModelIndex topLeft, bottomRight;
if (!firstCellInRowToBeUpdated.indexes().isEmpty())
{
qDebug() << "Ready to emit!";
topLeft = createIndex(0,0);
bottomRight = createIndex(3,4);
emit dataChanged(topLeft, bottomRight);
}
}
I tried using the 2 model indices passed into my method (firstCellInRowToBeUpdate) but get the same result, so to make things simple I hard coded just trying to select the whole table.
Related
So I have my Q and E set to control a Camera that is fixed in 8 directions. The problem is when I call Input.is_action_just_pressed() it sets true two times, so it does its content twice.
This is what it does with the counter:
0 0 0 0 1 1 2 2 2 2
How can I fix thix?
if Input.is_action_just_pressed("camera_right", true):
if cardinal_count < cardinal_index.size() - 1:
cardinal_count += 1
else:
cardinal_count = 0
emit_signal("cardinal_count_changed", cardinal_count)
On _process or _physics_process
Your code should work correctly - without reporting twice - if it is running in _process or _physics_process.
This is because is_action_just_pressed will return if the action was pressed in the current frame. By default that means graphics frame, but the method actually detect if it is being called in the physics frame or graphic frame, as you can see in its source code. And by design you only get one call of _process per graphics frame, and one call of _physics_process per physics frame.
On _input
However, if you are running the code in _input, remember you will get a call of _input for every input event. And there can be multiple in a single frame. Thus, there can be multiple calls of _input where is_action_just_pressed. That is because they are in the same frame (graphics frame, which is the default).
Now, let us look at the proposed solution (from comments):
if event is InputEventKey:
if Input.is_action_just_pressed("camera_right", true) and not event.is_echo():
# whatever
pass
It is testing if the "camera_right" action was pressed in the current graphics frame. But it could be a different input event that one being currently processed (event).
Thus, you can fool this code. Press the key configured to "camera_right" and something else at the same time (or fast enough to be in the same frame), and the execution will enter there twice. Which is what we are trying to avoid.
To avoid it correctly, you need to check that the current event is the action you are interested in. Which you can do with event.is_action("camera_right"). Now, you have a choice. You can do this:
if event.is_action("camera_right") and event.is_pressed() and not event.is_echo():
# whatever
pass
Which is what I would suggest. It checks that it is the correct action, that it is a press (not a release) event, and it is not an echo (which are form keyboard repetition).
Or you could do this:
if event.is_action("camera_right") and Input.is_action_just_pressed("camera_right", true) and not event.is_echo():
# whatever
pass
Which I'm not suggesting because: first, it is longer; and second, is_action_just_pressed is really not meant to be used in _input. Since is_action_just_pressed is tied to the concept of a frame. The design of is_action_just_pressed is intended to work with _process or _physics_process, NOT _input.
So, apparently theres a built in method for echo detection:
is_echo()
Im closing this.
I've encountered the same issue and in my case it was down to the fact that my scene (the one containing the Input.is_action_just_pressed check) was placed in the scene tree, and was also autoloaded, which meant that the input was picked up from both locations and executed twice.
I took it out as an autoload and Input.is_action_just_pressed is now triggered once per input.
Say you have a UICollectionView with a normal custom UICollectionViewLayout.
So that is >>> NOT <<< a flow layout - it's a normal custom layout.
Custom layouts are trivial, in the prepare call you simply walk down the data and lay out each rectangle. So say it's a vertical scrolling collection...
override func prepare() {
cache = []
var y: CGFloat = 0
let k = collectionView?.numberOfItems(inSection: 0) ?? 0
// or indeed, just get that direct from your data
for i in 0 ..< k {
// say you have three cell types ...
let h = ... depending on the cell type, say 100, 200 or 300
let f = CGRect(
origin: CGPoint(x: 0, y: y ),
size: CGSize(width: screen width, height: h)
)
y += thatHeight
y += your gap between cells
cache.append( .. that one)
}
}
In the example the cell height is just fixed for each of the say three cell types - all no problem.
Handling dynamic cell heights if you are using a flow layout is well-explored and indeed relatively simple. (Example, also see many explanations on the www.)
However, what if you want dynamic cell heights with a (NON-flow) completely normal everyday UICollectionViewLayout?
Where's the estimatedItemSize ?
As far as I can tell, there is NO estimatedItemSize concept in UICollectionViewLayout?
So what the heck do you do?
You could naively just - in the code above - simply calculate the final heights of each cell one way or the other (so for example calculating the height of any text blocks, etc). But that seems perfectly inefficient: nothing at all of the collection view, can be drawn, until the entire 100s of cell sizes are calculated. You would not at all be using any of iOS's dynamic heights power and nothing would be just-in-time.
I guess, you could program an entire just-in-time system from scratch. (So, something like .. make the table size actually only 1, calculate manually that height, send it along to the collection view; calculate item 2 height, send that along, and so on.) But that's pretty lame.
Is there any way to achieve dynamic height cells with a custom UICollectionViewLayout - NOT a flow layout?
(Again, of course obviously you could just do it manually, so in the code above calculate all at once all 1000 heights, and you're done, but that would be pretty lame.)
Like I say above the first puzzle is, where the hell is the "estimated size" concept in (normal, non-flow) UICollectionViewLayout?
Just a warning: custom layouts are FAR from trivial, they may deserve a research paper on their own ;)
You can implement size estimation and dynamic sizing in your own layouts. Actually, estimated sizes are nothing special; rather, dynamic sizes are. Because custom layouts give you a total control of everything, however, this involves many steps. You will need to implement three methods in your layout subclass and one method in your cells.
First, you need to implement preferredLayoutAttributesFitting(_:) in your cells (or, more generally, reusable views subclass). Here you can use whatever calculations you want. Chances are that you will use auto layout with your cells: if so, you will need to add all cell's subviews to its contentView, constrain them to the edges and then call systemLayoutSizeFitting(_:withHorizontalFittingPriority:verticalFittingPriority:) within this "preferred attributes" method. For example, if you want your cell to resize vertically, while being constrained horizontally, you would write:
override func preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes {
// Ensures that cell expands horizontally while adjusting itself vertically.
let preferredSize = systemLayoutSizeFitting(layoutAttributes.size, withHorizontalFittingPriority: .required, verticalFittingPriority: .fittingSizeLevel)
layoutAttributes.size = preferredSize
return layoutAttributes
}
After the cell is asked for its preferred attributes, the shouldInvalidateLayout(forPreferredLayoutAttributes:withOriginalAttributes:) on the layout object will be called. What's important, you can't just simply type return true, since the system will reask the cell indefinitely. This is actually very clever, since many cells may react to each other's changes, so it's the layout who ultimately decides if it's done satisfying the cells' wishes. Usually, for resizing, you would write something like this:
override func shouldInvalidateLayout(forPreferredLayoutAttributes preferredAttributes: UICollectionViewLayoutAttributes, withOriginalAttributes originalAttributes: UICollectionViewLayoutAttributes) -> Bool {
if preferredAttributes.size.height.rounded() != originalAttributes.size.height.rounded() {
return true
}
return false
}
Just after that, invalidationContext(forPreferredLayoutAttributes:withOriginalAttributes:) will be called. You usually would want to customize the context class to store the information specific to your layout. One important, rather unintuitive, caveat though is that you should not call context.invalidateItems(at:) because this will cause the layout to invalidate only those items among the provided index paths that are actually visible. Just skip this method, so the layout will requery the visible rectangle.
However! You need to thoroughly think if you need to set contentOffsetAdjustment and contentSizeAdjustment: if something resizes, your collection view as a whole probably will shrink or expand. If you do not account for those, you will have jump-reloads when scrolling.
Lastly, invalidateLayout(with:) will be called. This is the step that's intended for you to actually adjust your sections/rows heights, move something that's been affected by the resizing cell etc. If you override, you will need to call super.
PS: This is really a hard topic, I just scratched the surface. You can look here how complicated it gets (but this repo is also a very rich learning tool).
Sorry in advance, this is an extremely noobie question (but i'm just getting into NGUI with unityscript and can't find many answers/tutorials/docs).. Also my untiyscript skills are sub-par.
I have a TCG/Playing card game object with some basic RPG stats (strength, dexterity) that currently display on the card in GUIlabel and trying to convert this to NGUI. I'm adding a UILabel as a child to the card (which contains the stats script)
Looking for some advice on going about this, the only way I've even remotely gotten something to display correctly is, unfortunately I have to attach the stats script to the label too:
var strLbl : UILabel;
function Start() {
var strLbl = GetComponent(UILabel);
}
function OnGUI() {
strLbl.text = strength.ToString();
}
This is throwing numberous 'nullreferenceexception: object reference not set to an instance of an object (for the stats script)
Do I need to make a separate label for each stat or is there a way
to aggregate it into one label? (seems when I try to add strength
,then dexterity it overrides it)
is OnGUI the correct course for NGUI or is there a more efficient
function?
Is this script attached to the object that the UILabel is on? You should do a check for
if(strLbl != null)
strLbl.text = strength.ToString();
You could aggregate them into one label (though if individual stats update I would advise against it), assuming you want each stat on a newline then your next would be: strLbl.text += "\n" + dexterity.ToString()
No need to use OnGUI with NGUI. Especially not for setting things. You probably want to do this whole stage in Start() and have another method called for updating the label.
I am writing a iPhone app that calls a web service. Let say the web service returns 1000 elements in the json object. I don't want to load all 1000 of them since parsing can take some time. What I would like to do is load the first 15 elements of the NSDictionary that I created from the json object and then when the user scrolls to the bottom of the tableview have a 16th row that says "load more....". Since I already have all of the data stored in the NSDictionary object is there a way to break this up so that it returns the 15, then the user clicks "load more...." and it loads the next 15 and continues until there are no more elements in the NSDictionary? I can present examples of my code but I am wondering if anyone has an example of how to accomplish this. Thanks in advance for any assistance.
i think a UITableView does this for you. Only the visible cells are ever constructed. Their memory is then swapped with the next rows as you scroll down. I don't see a point in re-inventing the wheel.
Also as a note, only the visible cells are "parsed" as you put it. It will not construct a cell for every item in your datasource on load.
Assuming I hear you correctly I would say you just need a little tricky logic to get this working
I would simply maintain an index offset which I would multiply by the amount of rows you want to show at any time(15 in your case)
Your logic is to always return the amount of rows that you want to allow + 1 for the final. ex: return _indexOffset * 15 + 1; //for your numberOfRowsForSection
In your didSelectIndexPathOf you check if you're the last row:
if(indexPath.row == _indexOffset * 15)
{
_indexOffset ++;
[tableView reloadData];
}
This isn't an exact answer but I think it can get you started
I'm running an update() method n times per second to "update" the keyboard input from the user so I can read it later in the logic part of the program. So I find two ways of implementing this in the SDL Docs and I'm not sure which one should I use.
1; Loop for all events using SDL_PollEvent searching for key down/up events and saving the key states in a map so I can check for each key state in the logic of the program.
Note: Alternatively, I can also use SDL_PeepEvents instead of SDL_PollEvent to take only the event types that matter; so, it would not "thrown away" the events on the queue.
std::map<int, bool> keyboard; // Saves the state(true=pressed; false=released) of each SDL_Key.
void update()
{
SDL_Event event;
while(SDL_PollEvent(&event))
{
switch(event.type)
{
case SDL_KEYDOWN:
keyboard[event.key.keysym.sym] = false;
break;
case SDL_KEYUP:
keyboard[event.key.keysym.sym] = true;
break;
}
}
}
2; Taking a snapshot from the keyboard each frame so I can read it easily.
Uint8* keyboard;
void update()
{
SDL_PumpEvents();
keyboard = SDL_GetKeyState(NULL);
}
With any of above implementations I can read keyboard just like this:
if (key_map[SDLK_Return]) printf("Return has been pressed.");
Also, is there another way to do so?
I prefer to do a variation of 1, where I fill three arrays, indicating not only the current state, but also which keys just went down and which keys just went up. This allows me to easily check for those events in code (without comparing to the previous snapshot), but, most importantly, it won't miss events that last less than a frame. For example, if your game is running at 10 fps due to a slow machine, the user might press and release an important key between two calls of your update routine, and then your system will never register it. This is extremely frustrating.
SDL also sends key events when the key is held down, which allow you to have multiple key down events for each key up. I find this particularly useful when implementing keyboard scrolling through a list of items, e.g. a keyboard-controlled menu.
You should use solution 2.
Why? As SDL_GetKeyState() docs point out, before using it you are expected to call SDL_PumpEvents() to update the state array.
When you are calling SDL_PollEvent(), it implicitly calls SDL_PumpEvents(). So, it basically updates the array for SDL_GetKeyState() anyway. By parsing these events manually, you just create a second array (well, actually a much slower map) holding the same information which SDL already collected for you.
So, I would dare say that first solution means doing the same thing twice. And if you ever decide to support things such as repeated keystrokes (SDL_EnableKeyRepeat()), you'll be reimplementing even a larger part of SDL.
I realize this question is quite old, but my answer could benefit someone. Personally, I use two arrays with SDL_GetKeyState. I store one array holding the current frame's keyboard state, and one array holding that last frame's keyboard state. (With some memcpy commands, it's really easy to update them.) Along with those two arrays, I have a map that converts strings like "A" to the SDL scancode values, but that is optional.
Then, when you need to check if something is released or pressed, you can combine the two arrays to check. (I made this a function.) For example, if you know that the key is pressed this frame, but wasn't pressed last frame, it was clearly just pressed this frame. if (currentFrame["A"] == true && lastFrame["A"] == false) {/*just pressed*/}
You would then do the opposite for the released. I find that method super easy to implement and use.