NS Timer to update textField - cocoa

Thanks for the help.
I have a textField that I want to update according to the following time increments:
[textField setStringValue:#"Audio 1"]; 7sec.
[textField setStringValue:#""]; 3sec.
[textField setStringValue:#"Audio 2"]; 7sec.
I need the above to loop cumulatively for a total of 5 min.
Any guidance on how to set up NSTimer(s) to accomplish this?
Again - thanks.

Create the timer to fire every second.
Create a counter variable, set it to 600 and decrement it in the timer action. Stop the timer – or whatever you need to do – when the counter reaches zero.
Create two arrays, one with the string values and the other with the durations.
Create a second counter variable for the durations.
Create an index variable and set it to 0.
Get the string value and duration at the given index.
Set the second counter to the duration and assign the string value to the text field.
In the timer action decrement also the second counter. If it's 0 increment the index, if the index is equal to the number of items in the array set the index to 0.
Goto to the step "Get the string value and duration at..."

Related

QTableWidget resizeRowsToContents very SLOW

I've a QTableWidget that contains over 200.000 rows and 8 columns.
The columns has a fixed size.
The rows has a variable size.
Adding the items to the table is fast (few seconds).
Then the call of resizeRowsToContents() takes almost 60/120 seconds! I see that this call is single thread! (Only one core works).
Can I force MultiThreading ?
How Can I speedup the row resizing ?
Thank you,
Salvo
One thing you might try is to update the QTableWidget row-by-row using QTableWidget::resizeRowToContents(Note: Row rather than Rows) with the updates being interleaved with other events in the queue. Overall the process would still take the same amount of time but your GUI would remain responsive during the process.
Firstly, take advantage of the fact that a QTimer with a zero timeout will emit its timeout signal whenever the event queue becomes empty. So code such as...
QTimer::singleShot(0, &my_callback);
will effectively wait until the event queue is empty and then invoke my_callback. If my_callback calls the same line of code then you have a function that automatically invokes itself during the next idle period.
Now write the function...
void resize_row (QTableWidget *view, int row, int count = 1)
{
/*
* Resize rows `row' -> `row + count - 1'
*/
for (int todo = count; row < view->rowCount() && todo--; ++row) {
view->resizeRowToContents(row);
}
/*
* If there are still rows remaining then reschedule.
*/
if (row < view->rowCount()) {
QTimer::singleShot(0, [=](){ resize_row(view, row, count); });
}
}
This will invoke view->resizeRowToContents(...) on all rows in the range [row, row + count). If the row index is still less that the row count it will schedule itself for the next idle period with updated parameters.
Now, replace...
table_widget->resizeRowsToContents();
with...
QTimer::singleShot(0, [table_widget, row = 0](){ resize_row(table_widget, row, 10); });
Seems to work fine in the basic tests I've done.
Resize has to re-calculate, each row hight and adjust. I would not recommend having this many rows in a single QTableWidget. I would go for a pagination technic or some dynamic loading functionality for this long list.
If you want more speed use QAbstractTableModel instead of QTableWidget and override the required functions. This is a simple and good example:
https://doc.qt.io/qt-5/modelview.html

Game Maker - Mouse Click image_index Checking

I have this sprite: spr_meteoriteLv3, which has two sub-images with index image_index 0 and 1 respectively.
I have these objects: obj_meteoriteLv3, obj_tempMeteoriteLv3, and obj_score. Object obj_meteoriteLv3 spawns from above with random position, random amount, and random sub-image. Object obj_tempMeteoriteLv3 makes obj_meteoriteLv3s spawn. When player clicks on a meteorite, the program checks the value of image_index for that object.
obj_meteoriteLv3 has these events:
Create Event: change sprite_index into spr_meteoriteLv3, and start moving downwards.
Left-pressed Mouse Event: destroy the self instance, and check image_index: if image_index == 0 then score += 5; else score -= 5).
obj_tempMeteoriteLv3 has these events:
Create Event: set Alarm 0 to 3600, set variable exist to 1, and set variable add to 1.
Alarm 0: set variable add to 0, and destroy the obj_meteoriteLv3 instance.
Alarm 1: set variable exist to 1.
Step Event: if (exist == 1) then, if (add == 1) then create instance of obj_meteoriteLv3, set variable exist to 0, and set Alarm 1 to 10.
obj_score has these events:
Create Event: set score to 0.
Draw Event: draw the value of score.
The problem is, no matter which sub-image the meteorite image_index has when clicked, the score will always be incremented by 5 points. It's like the else condition isn't working. How can I fix this? Please explain your answer. Thanks.
I add some images for better understanding. Link 1. Link 2
In obj_meteoriteLv3 it's being destroyed before it can execute the rest of the code blocks. Move "Destroy Instance" to the bottom.
In obj_tempMeteoriteLv3 both variables "add" and "exist" are not necessary, instead have-
Create Event-
alarm[0] = 3600
alarm[1] = 10
Alarm[0] Event-
destroy_instance
Alarm[1] Event
Create_instance of obj_meteoriteLv3
alarm[1] = 10
Potentially, when you click, every single meteorite is triggered.
On the left click event of the meteorite, you did not check if the cursor was on the sprite. You have to use the position_meeting function, to which you pass the mouse position and the instance to click.
it would look like :
if (position_meeting(mouse_x, mouse_y, id))
{
//your destroy code
}
Moreover, when the instance_destroy(); line is read, the following code is ignored and the program jumps to the destroy_event. William explained it well and suggested to change the order of the lines of code, but you can also change the score in the destroy event directly.
I would like to add that checking for clicks in every instance of the meteorites is not optimal for performances.
My recommendation would be to use a single object to check for clicks (your player or your meteorite spawner, for example), in which you would check for clicks, and if a meteorite is touched, you would trigger it's destroy event. And in this event, you would increment the score and check the sprite.
Your click event would look like :
with (instance_position(mouse_x, mouse_y, obj_meteoriteLv3))
{
instance_destroy();
}
and in the meteorite destroy event, you would check the image_index and change the score accordingly.
EDIT : why the score doesn't change
I believe you didn't declare the score as a global variable, but as an instance variable. So when you write "score = ..." in an other object, it creates a new score variable, unrelated to the precedent.
You have 2 options :
1 - Declare the score a global variable in the create event of obj_score:
globalvar score;
score = //your starting score
Be aware that a global variable can't be set on it's initialisation line.
2 - Change the score through the score object :
whenever the score has to change :
obj_score.score = ...

Swift: Repeat action after a random period of time

Previously, with Objective-C I could use performSelector: in order to repeat an action after a random period of time which could vary between 1-3 seconds. But since I'm not able to use performSelector: in Swift, I've tried using "NSTimer.scheduledTimerWithTimeInterval". And it works in order to repeat the action. But there is a problem. On set the time variable to call a function that will generate a random number. But it seems that NSTimer uses the same number every time it repeats the action.
What that means is that the action is not performed randomly, but instead, after a set period of time that is generated randomly at the beginning of the game and it is used during all the game.
The question is: Is there any way to set the NSTimer to create a random number every time it executes the action? Or should I use a different method? Thanks!
#LearnCocos2D is right... use SKActions or the update method in your scene. Here is a basic example of using update to repeat an action after a random period of time.
class YourScene:SKScene {
// Time of last update(currentTime:) call
var lastUpdateTime = NSTimeInterval(0)
// Seconds elapsed since last action
var timeSinceLastAction = NSTimeInterval(0)
// Seconds before performing next action. Choose a default value
var timeUntilNextAction = NSTimeInterval(4)
override func update(currentTime: NSTimeInterval) {
let delta = currentTime - lastUpdateTime
lastUpdateTime = currentTime
timeSinceLastAction += delta
if timeSinceLastAction >= timeUntilNextAction {
// perform your action
// reset
timeSinceLastAction = NSTimeInterval(0)
// Randomize seconds until next action
timeUntilNextAction = CDouble(arc4random_uniform(6))
}
}
}
use let wait = SKAction.waitForDuration(sec, withRange: dur) in your code. SKAction.waitForDuration with withRange parameter will compute random time interval with average time = sec and possible range = dur
Generate a random time yourself and use dispatch_after to do the action.
For more information on dispatch_after, see here. Basically you can use this instead of performSelector

Visual Basic: Increasing integer every 3 clicks

So my question is pretty much what the title says: how do I get a certain integer to increase by 1 for every three clicks of a button? For example, let's say the integer is 900. I click button1 once, then again, then again, and on the third click the integer changes to 901. How can this be accomplished?
Thanks in advance.
Use a counter that is actually three times larger behind the scene. Start at 2700 instead of 900, and increase the value by one for each click.
When you want to display the value that increases every third click, you divide the counter by three:
displayValue = counter \ 3
Try this maybe this could help or give you idea
Dim click = 0
Dim num = 900
if (click % 3 = 0)
num+=1
else
click+=1
end if

string/number from TextField to be used for calculation?

sorry for my question and for the long explanation following here, probably there's a simple solution for someone who is experienced in Cocoa and Objective-C, but I'm just starting few weeks ago and I can't figure out how to get this thing working, Grrrrrrr!!
OK, let's put it like this, in my window I have the following:
2 TextField(NSTextField) called:
blockOffText
blockOnText
1 Label(NSTextField) called:
flightTimeText
1 button(NSButton) called:
updateButton
What I want to do is all about time calculation I guess, get the "start-time" in one TextField and the "end-time" in the other.
One is supposed to be the "takeoff-time" and the other the "landing-time" or for example the "duty-startTime" and "duty-endTime"...it's the same!
Then I want to calculate the "flight-time" or "duty-time" and show it in the Label.
At the end I will also need to store the value or the time in a database as an integer, the value should be represented by all minutes corresponding to each time, but the database part is not a problem at the moment.
Maybe I can write the number in the TextField without the format but just the number and get the time show-up formatted in some way?
I would like to write for example "1245" and "1525" without having the needs to put the ":" between the hours and minutes, then can I get the value formatted "12:45" "15:25" in the TextField in some way? Maybe after pressing the button?
Ok, that is a second problem anyway, my real problem is I need to get the value I wrote in the TextField ("1245" and "1525") to be assigned to some variables in the program that I called "BlockOff" and "BlockOn".
I need to transform them in an integer that represent the minutes corresponding to their value..example:
The 1245 will become 765 minutes...(12 times 60 + 45)
and 1525 will become 925 minutes...(15 times 60 + 25)
HOW CAN I DO THIS?
In this way I can use the minutes to calculate the difference to get the flight time or even add flight time to other flight time.
At the moment my program works a little bit differently... like this:
If I directly assign the value to the two variables:
int blockOff = 765;
int blockOn = 925;
then I can calculate and show in the two TextField the takeOff and landing time formatted like I want: "12:45" "15:25"...I use other 2 variables to do so:
int oreBlkOff, minBlkOff = 0;
minBlkOff = blockOff % 60;
oreBlkOff = (blockOff - minBlkOff) / 60;
Then I can show the value in the TextField:
[blockOffText setStringValue:[NSString stringWithFormat: #"%d:%d", oreBlkOff, minBlkOff]];
Same with blockOnText and flightTimeText, so there is no problem there, but this is not really what I need right?
HOW CAN I GET THE VALUE OF THE TEXTFIELD AND STORE THE VALUE IN VARIABLES THAT CAN BE USED TO DO CALCULATION?
HOW DO I GET THE FIRST TO DIGITS AND LAST TO DIGITS FROM THE VARIABLES SO I CAN USE THEM AS HOURS AND MINUTES FOR MY CALCULATION?
I WOULD LIKE TO BE ABLE TO TYPE THE VALUE IN THE TEXTFIELD, PRESS "ENTER" OR "RETURN" AND GET THE VALUE ASSIGNED IN THE VARIABLE.
IS THIS THE CORRECT WAY OR I'M JUST GOING THE WRONG WAY IN THIS.
IN ANOTHER PROGRAM I DID IN VISUAL BASIC THAT WAS THE WAY I USED.
THANK YOU VERY MUCH IN ADVANCE FOR YOU HELP!
Gianluca
To get the int value from text field you'd use integerValue or floatValue for float. But you should definitely check out the date/time controls in cocoa.
Ok, if I didn't miss the point of your long question...
You have a text field with something like #"2345:8743" and you want to get the two numbers in int variables (a=2345, b=8743).
First you need to get these two text representations of your numbers in two NSStrings. You can do it like this:
NSString * yourString = #"2345:8743";
NSString *stringA = [yourString substringToIndex:4]; //stringA = #"2345"
NSString *stringB = [yourString substringFromIndex:5]; //stringB = #"8743";
Now to get the in values, just do:
int a = [stringA intValue];
int b = [stringB intValue];
Let me know if that is helpful to you.

Resources