Call method when user changes focus from on textfield to another (RubyMotion) - ios

I'm using RubyMotion (had been writing Obj C in Xcode previously but now I'm collaborating with someone that wants to use RubyMotion due to bkgd in Ruby)
I have a ViewController with 2 textfields. I need to have it so that whenever user switches from being in textfield1 to textfield2 if a condition of textfield1 isn't met, Error Label shows (I use self.ErrorLabel.show for this). I know how to write my condition statements but I really do not know how to know when user switches to next textfield.
I thought I could use:
if ([textField1 isFirstResponder] && (textField1 != touch.view))
log( 'left textfield1' )
end
if ([textField2 isFirstResponder] && (textField2 != touch.view))
log( 'left textfield2' )
end
from this question Detect UITextField Lost Focus but no such luck. I know I'm using RubyMotion so there are some differences.
How do I get this to work? I don't think I'm searching with the right keywords because it seems like something developers use all the time yet I'm not finding any results.
Thank you for any help available.
Update: I am thinking I will be using this method:
- (void)textFieldDidEndEditing:(UITextField *)textField
In RubyMotion:
def textFieldDidEndEditing( textField )
I used log() to determine that this does indeed let me know that the user has changed from one textfield to the next. I just need to do a couple of tweaks so that I can specify which textfield was left.

You need to set the delegate of each of your text fields to the view controller class, then implement the textFieldDidEndEditing method. Here's a working example:
class MyViewController < UIViewController
attr_accessor :textField1, :textField2
def viewDidLoad
#textField1 = UITextField.alloc.initWithFrame([[10, 100], [300, 40]])
# Customize your text field...
#textField2 = UITextField.alloc.initWithFrame([[10, 150], [300, 40]])
# Customize your text field...
view.addSubview(#textField1)
view.addSubview(#textField2)
#textField1.delegate = self
#textField2.delegate = self
end
def textFieldDidEndEditing(textField)
if textField == #textField1
puts 'left textField1'
elsif textField == #textField2
puts 'left textField2'
end
end
end

Related

How to get te text of a textfield from inside a function?

I want to make an app that has 2 textfields, 4 buttons and a Text view. 1 button that clears the content of the first textfield and another button that inputs the current time rounded to the nearest 4 and the Text view to display the total time in minutes. Same with the other textfield. It's an app to calculate the total time spent on something in minutes.
I also want to limit the amount of possible insertable characters to 5 as a time has a maximum of 5 characters as in "15:00". I have been able to make an observable object:
class TextFieldManager: ObservableObject {
let characterLimit = 5
#Published var userInput = "" {
didSet {
// Limit the max length of the field
if userInput.count > characterLimit {
userInput = String(userInput.prefix(characterLimit))
} else if userInput.count >= 4 {
// call the setTotalTime func or something to set totalTime
}
}
}
}
which works really well.
I am also able to clear the textfield and set the current time rounded to the nearest 5, but i am unable to limit the characters to 5 AND have the buttons do something at the same time.
So right now it's either being able to:
- Limit characters to a maximum of 5
OR being able to:
clear textfield with a button
input time now rounded to nearest 5 into textfield with a button.
If i go with the observable object method, when i have this above the body block of my ContentView:
#ObservedObject var startTimeManager = TextFieldManager()
#ObservedObject var endTimeManager = TextFieldManager()
and this inside the body for the textfields:
TextField("hh:mm", text: $startTimeManager.userInput)
TextField("hh:mm", text: $endTimeManager.userInput)
and the TextFieldManager class as shown above, than now i don't know how to get the value of the Textfield anymore.
If inside the input the current time button i try to set the time by doing
$startTimeManager.userInput = "whatever the current time is"
i get an error saying that i can't change the value of a binding<String> type something something. Likewise i also can't clear the textfield in the same way.
Also i would like to call a function inside this part:
} else if userInput.count >= characterLimit {
// call the setTotalTime func or something to set totalTime
}
I have a Functions.swift file where both the TextFieldManager class is and my function that i want to call, but if i try to call a function inside here, it says that the function doesn't exist? And inside the function i again would like to have access to the textfield values at the time of the call, but i don't know how to read the value of the textfields from inside the function.
I hope i am making sense and that someone is able to help me, or point me in the right direction. I made the same app for android (android studio), windows (python3) and Mac (python3), but this iphone and Xcode thing really doesn't want to work. I have watched a bunch of tutorial videos and guides, but none are trying to do what i am trying to do. Like i said i can get either to work, but never together and in both cases i am unable to somehow access the textfield values inside the function. I feel like i should be so close, but something is not coming together for me in my head.
Also while i'm at it, in Python 3 to catch all errors and let them pass silently i can do:
Try:
break_my_stuff = int("Break my stuff)"
ignore_some_more_stuff = int("ignore some more stuff)"
etc.
etc.
except Exception:
# catch silently and do nothing
pass
Is there something similar in swift, because
do {
breakMyStuff = whatever might make something break in swift
ignoreSomeMoreStuff = whatever might make something break in swift
etc.
etc.
} catch {
// do nothing and pass silently
}
doesn't work because it needs something to try and i wasn't able to try a complete section like i can with Python.
If inside the input the current time button i try to set the time by doing
$startTimeManager.userInput = "whatever the current time is"
you don't need binding in this case, just assign property in regular way
self.startTimeManager.userInput = "whatever the current time is"

PICO-8 making a button press show an output of text only once?

I'm a complete newbie to both Lua, PICO-8, and coding in general. I'm having trouble with a function I want to put in my first program. The text is all placeholder, I will change it once I get the code right and comprehend it.
Basically, before the _init() I have a function ow() defined where I press a button and the program displays the text "ow." I put the function name in _update() so that it will update 30x/second to see if the button is pressed; however, this is making the "ow" appear 30 times a second (or however long the button is pressed) instead of appearing once when I initially press the button. How do I fix this? Thank you for your tolerance of a new coder's question in advance. Here's my code:
function ow()
if btn((X))
then print "ow"
--how do i make it do this
--only once?
end
end
function _init()
print "hello."
print "i have been waiting for you."
end
function _update()
ow()
end
function _draw()
end
You need a global variable to save previous status of the button.
function ow()
if btn((X)) then
if not button_was_pressed then
button_was_pressed = true
print "ow"
end
else
button_was_pressed = false
end
end

Disable/Enable button based on which control has focus

What I'm trying to do here is loop through the different controls and if any of the controls got focus to disable a button. This is a loop that I used for another task, so I'm kinda basing it off of this...
Dim cControl As Control
For Each cControl In Me.controls
If Not cControl.Container Is framClient Then
If Mid(cControl.Name, 1, 3) = "txt" Or Mid(cControl.Name, 1, 3) = "msk" Or Mid(cControl.Name, 1, 3) = "cbo" Then
'WHAT I'm trying to do here is
'if cControl.gotfocus then
'cmdExit.enabled=false
'end if ' but it barks at me
'cControl.Enabled = False
End If
End If
Next
I didn't make these text boxes in an array and I do not want to go through each text box to see if got focus and do whatever. Please take a look.
In vb6 only one control can have focus: the ActiveControl, so there's no point in looping and asking if the control has focus.
If you need to do something based on whether a certain control with a particular name has focus you could do this:
cmdExit.Enabled = (Me.ActiveControl.Name = "MyTextBox")
If you need to do it based on whether any TextBox has focus:
If TypeOf Me.ActiveControl Is TextBox Then
cmdExit.Enabled = false
Else
cmdExit.Enabled = true
End If
You can go ahead with Subclassing of text boxes as suggested in this SO Post.
As the post suggests, you have to do this exercise for every form where you have this requirement. I think, from your post that you have to do it only for one form.

Having trouble with some computercraft/lua code

Hi I want my lua code in Computercraft to allow the user to turn the redstone signal on/off by right clicking on a monitor on top, but I can't get it to work.
monitor = peripheral.wrap("top")
monitor.clear()
monitor.setTextColor(colors.red)
monitor.setCursorPos(1, 1)
monitor.setTextScale(1)
monitor.write("Hello")
function rubber()
monitor.setCursorPos(1, 2)
monitor.clearLine()
if rs.getOutput("right", true) then
monitor.write("Rubber farm is on")
elseif rs.getOutput("right", false) then
monitor.write("Rubber farm is off")
end
local event = { os.pullEvent() }
if event == "monitor_touch" then
if rs.getOutput("right") == true then
rs.setOutput("right", false)
else
rs.setOutput("right", true)
end
else
write("test")
end
rubber()
end
Right now all it displays is 'hello' and I don't know how to fix it, anyone know how? Also I'm a beginner at Lua so I've probably made some pretty simple mistakes. Thanks
local event = { os.pullEvent() }
if event == "monitor_touch" then
os.pullEvent returns a tuple. In your code, you're packing this tuple into a table. That's fine, but you then compare that table to a string. Tables can't be equal to strings - they're a table. Either don't pack the tuple into a table, and keep the first return value (the type):
local event = os.pullEvent()
if event == "monitor_touch" then
Or extract the first element when comparing
local event = { os.pullEvent() }
if event[1] == "monitor_touch" then
The problem is you wanted to have that function infinitly looping, but you have not called your function outside your function.... also you should look into using while loops
while true do
//stuff here
end
just add
rubber()
to the last line after your last end tag.
You have to call the function.
rubber()
You need to close your function
function rubber()
monitor.setCursorPos(1,1)
monitor.clearLine()
end
The end is it you need to make this little word
this is a simple fix, simply add rubber() after you finish the function rubber, cause while you have created the function rubber, you have not called for it to start yet.
The "monitor_touch" event is what you should be using. Also, make sure the monitor you are using is an advanced monitor (the one with the yellow border).
If you need help in understanding the event, check out this page: http://computercraft.info/wiki/Monitor_touch_(event)

If else or case statement help!

I could really use some help with the best way to accomplish the following:
I have the below in my controller (and I know this should not be here and needs to move to the model)
This is an email messaging system so according to what position you hold you are able to email out to set groups of people. So if you are Battalion Commander etc you can choose to message out to one of the 5 groups defined below. If you are a Company Commander your groups change. In the view there is a drop down menu and you choose the group your message goes out to. The select menu is populated depending on the position of the signed in user.
The problem seems that the "elsif" portion does not populate the message correctly. It shows the right drop down list and acts as if the email is sent but the emails are not being populated. However the first value (Battalion Commander) works fine.
Do I have something written incorrectly in the if else statement? It seems like it should be pretty simple. The user position always reflects correctly so that is not it.
if (#position == "Battalion Commander" or "Command Sergeant Major" or "FRSA" or "Battalion FRG Leader")
#bnok = (#user.battalion.primaries).collect(&:email).select{|s| !s.blank?}.join(", ")
#bspouses = (#user.battalion.primaries(:conditions => ["relationship = 'spouse'"])).collect(&:email).select{|s| !s.blank?}.join(", ")
#bsoldiers= (#user.battalion.soldiers).collect(&:email).select{|s| !s.blank?}.join(", ")
#bsoldierspouse=((#user.battalion.soldiers)+(#user.battalion.primaries(:conditions => ["relationship = 'spouse'"]))).collect(&:email).select{|s| !s.blank?}.join(", ")
#ballcontacts=((#user.battalion.soldiers)+(#user.battalion.primaries)+(#user.battalion.additionals)).collect(&:email).select{|s| !s.blank?}.join(", ")
elsif
#position == ("Company Commander" or "First Sergeant" or "FRG Leader")
#nok = (#user.company.primaries).collect(&:email).select{|s| !s.blank?}.join(", ")
#spouses = (#user.company.primaries(:conditions => ["relationship = 'spouse'"])).collect(&:email).select{|s| !s.blank?}.join(", ")
#soldiers= (#user.company.soldiers).collect(&:email).select{|s| !s.blank?}.join(", ")
#soldierspouse=((#user.company.soldiers)+(#user.company.primaries(:conditions => ["relationship = 'spouse'"]))).collect(&:email).select{|s| !s.blank?}.join(", ")
#allcontacts=((#user.company.soldiers)+(#user.company.primaries)+(#user.company.additionals)).collect(&:email).select{|s| !s.blank?}.join(", ")
end
So this does not work, it work for either one set of positions or the other but not both. This correlates to a select menu in the view and depending on what position you hold the query on certain groups of people change.
So in the view I have this:
<% if #position == "Battalion Commander" %>
<%= f.select(:bcc_email, [["Please Select", ""], ["Battalion NOK", #bnok], ["Battalion Spouses", #bspouses], ["Battalion Soldiers Only", #bsoldiers], ["Battalion Soldiers & Spouses", #bsoldierspouse], ["All Battalion Contacts", #ballcontacts]]) %></h1><br />
I am still learning rails and I am not sure if a case statement would be better but then I am confused on where that goes and how that case statement fits into the view.
Any guidance would be great, I am trying to chip away at this and figure it out, but I would really appreciate some help.
Firstly it may help if you can format that a bit clearer - for us and yourself, often simple formatting will help identify issues.
Secondly, what is your goal here? I gather it's some sort of war simulator or something? And assume you realise that in an if statement, only one of them will be executed:
if (xxx)
aaaaaaaaaaaaaaaaaa
elseif (yyyy)
bbbbbbbbbbbbbb
end
in the case that xxx is true, the aaaaaaaa will be executed, and then it'll jump to end. The bbbbbbbbb part will not be executed - even if true, because the first statement was. If however xxx is not true, yyyy will be evaluated, and if true, bbbbbbbbbbbbb will happen.
I hope that helps a bit?
disclaimer: I don't know ruby. I have been told it is similar to python and LISP in some regards, so this answer makes that assumption.
What I would do is maintain these condition variables in a dictionary (or map, or hash table, whatever your language calls it). The "rank" of the person would be a key, and the value would correspond to the function you want to execute for that rank. for instance,
#the following example is python-esque. you'll have to port it to ruby.
def some_funct1(): #pass parameters if you need to. i don't, here.
sql_stuff_here
def some_funct2():
sql_stuff_here
map['important dude'] = some_funct1;
map['another important dude'] = some_funct1;
map['unimportant dude'] = some_funct2;
map['another_unimportant dude'] = some_funct2;
#after some time, you have a person whose rank is rank.
map[rank]() #this will execute the function
You wrote
if (... a big test ...)
..do some work..
elsif
..do something else..
end
but that is wrong! You should just write else instead of elsif unless you need to check another condition.
[I assume elsif followed by nothing=nil is always false]

Resources