x

Search in
Sort by:

Question Status:

Search help

  • Simple searches use one or more words. Separate the words with spaces (cat dog) to search cat,dog or both. Separate the words with plus signs (cat +dog) to search for items that may contain cat but must contain dog.
  • You can further refine your search on the search results page, where you can search by keywords, author, topic. These can be combined with each other. Examples
    • cat dog --matches anything with cat,dog or both
    • cat +dog --searches for cat +dog where dog is a mandatory term
    • cat -dog -- searches for cat excluding any result containing dog
    • [cats] —will restrict your search to results with topic named "cats"
    • [cats] [dogs] —will restrict your search to results with both topics, "cats", and "dogs"

How does one make a text box to only take numbers

Hello, I' m trying to set a text box to only take numbers. This is so I can use the player input to set a int? Does anyone have any clue on how to this, or how to make the spin box round up to the nearest whole number? Thank you for any response on the matter.

Product Version: Not Selected
Tags:
more ▼

asked Oct 22 '16 at 12:47 AM in C++ Programming

avatar image

Emithises
28 2 3 6

(comments are locked)
10|2000 characters needed characters left

2 answers: sort voted first

You want to perform this operation before any other bindings to OnTextChanged or OnValueChanged because you want to validate that the input is a different, valid integer before other events are called; so you can't just bind your method to OnTextChanged or OnValueChanged as you would otherwise.

Unfortunately, you can't directly override the HandleOnTextChanged implementation because it's protected (unless you want to rewrite engine source), but you can override RebuildWidget. You can create your own method to handle text changes, and then tie that method back into the native HandleOnTextChanged.

 //MyIntegerEditableText.h
 
 #include "Runtime/UMG/Public/UMG.h"
 #include "Runtime/UMG/Public/Components/EditableText.h"
 
 #include "MyIntegerEditableText.generated.h"
     
 UCLASS(Blueprintable, BlueprintType)
 class MYGAME_API UMyIntegerEditableText : public UEditableText
 {
     GENERATED_BODY()
 
 protected:
 
     UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Input Data")
     int32 IntegerValue;
 
 public:
 
     UMyIntegerEditableText();
 
     //~ Begin UWidget Interface
     virtual TSharedRef<SWidget> RebuildWidget() override;
     // End of UWidget
 
     UFUNCTION(BlueprintCallable, Category = "User Input")
     void MyHandleOnTextChanged(const FText& InText);
 
     UFUNCTION(BlueprintCallable, Category = "User Input")
     bool ValidateIntegerValue(FText& InText);
 
     UFUNCTION(BlueprintCallable, Category = "User Input")
     int32 GetIntFromFloat(const float& FloatValue);
 
 };
     
 //MyIntegerEditableText.cpp
 
 #include "MyGame.h"
 
 #include "MyIntegerEditableText.h"
     
 UMyIntegerEditableText::UMyIntegerEditableText()
     :
     UEditableText(),
     //set your default value to whatever you like
     IntegerValue(0)
 {
     //update the default Text value to reflect your integer value
     Text = FText::AsNumber(IntegerValue);
 
 }
 
 TSharedRef<SWidget> UMyIntegerEditableText::RebuildWidget()
 {
     //this is a duplication of the UEditableText RebuildWidget method, but
     //with our MyHandleOnTextChanged method bound to OnValueChanged
     MyEditableText = SNew(SEditableText)
         .Style(&WidgetStyle)
         .MinDesiredWidth(MinimumDesiredWidth)
         .IsCaretMovedWhenGainFocus(IsCaretMovedWhenGainFocus)
         .SelectAllTextWhenFocused(SelectAllTextWhenFocused)
         .RevertTextOnEscape(RevertTextOnEscape)
         .ClearKeyboardFocusOnCommit(ClearKeyboardFocusOnCommit)
         .SelectAllTextOnCommit(SelectAllTextOnCommit)
         //here we replace HandleOnValueChanged with our MyHandleOnTextChanged method
         .OnTextChanged(BIND_UOBJECT_DELEGATE(FOnTextChanged, MyHandleOnTextChanged))//<-- 
         .OnTextCommitted(BIND_UOBJECT_DELEGATE(FOnTextCommitted, HandleOnTextCommitted))
         .VirtualKeyboardType(EVirtualKeyboardType::AsKeyboardType(KeyboardType.GetValue()));
 
     return BuildDesignTimeWidget(MyEditableText.ToSharedRef());
 
 }
 
 void UMyIntegerEditableText::MyHandleOnTextChanged(const FText& InText)
 {
     //the native HandleOnTextChanged takes a constant, but we 
     //may be changing this value so we'll convert it to something editable
     FText NewText(InText);
     //We use ValidateIntegerValue to determine if the value has actually changed and is a valid integer
     if (ValidateIntegerValue(NewText)) {
         //important to tie back into the OnTextChanged event with the validated value
         HandleOnTextChanged(NewText);
         //natively HandleOnTextChanged just broadcasts the OnTextChanged event; we could just
         //do that here, but I always prefer to go back to the native method if possible so
         //any future engine updates will seemlessly integrate (hopefully)
 
     }
 
 }
 
 //this verifies the passed in text can be interpreted as an integer and cleans the value
 bool UMyIntegerEditableText::ValidateIntegerValue(FText& InText) {
     //checking to make sure the value is different prevents an infinite loop via SetText
     if (!InText.EqualTo(Text)) {
         if (InText.IsNumeric()) {
             //convert the value to a float so we can round properly if the user entered a decimal
             float FloatValue = FCString::Atof(*InText.ToString());
             //set our integer value
             IntegerValue = GetIntFromFloat(FloatValue);
             //you can use FMath::CeilToInt or FMath::Floor if you prefer
             //IntegerValue = FMath::CeilToInt(FloatValue);
             //IntegerValue = FMath::Floor(FloatValue);
 
             //then set our new integer back to the text value
             InText = FText::AsNumber(IntegerValue);
 
             //then we have to set the value back to the SEditableText object
             SetText(InText);
             return true;
 
         }
     else if (InText.IsEmpty()) {
         //handle the special case of deleting the last digit.
         //here I just set everything to 0; you could set it to a stored default, or whatever
         //I find this to be nicer behavior than refusing to delete the last digit;
         //unfortunately, if the last digit is 0 it still appears to be non-responsive
         IntegerValue = 0;
         SetText(FText::AsNumber(IntegerValue));
         return true;
     }
     else {
             //if we haven't been given a good integer value, set the text value back to our current
             //stored integer value; you can, of course, modify this behavior if you desire
             SetText(FText::AsNumber(IntegerValue));
 
         }
 
     }
     return false;
 
 }
 
 //converts referenced float to integer value with proper rounding rules
 int32 UMyIntegerEditableText::GetIntFromFloat(const float& FloatValue) {
     if (FloatValue >= 0.0f) {
         return (int)(FloatValue + 0.5f);
 
     }
     return (int)(FloatValue - 0.5f);
 
 }

A spinbox is very similar, but involves OnValueChanged instead of OnTextChanged.

 //MyIntegerSpinBox.h
     
 #include "Runtime/UMG/Public/UMG.h"
 #include "Runtime/UMG/Public/Components/SpinBox.h"
     
 #include "MyIntegerSpinBox.generated.h"
     
 UCLASS(Blueprintable, BlueprintType)
 class MYGAME_API UMyIntegerSpinBox : public USpinBox
 {
     GENERATED_BODY()
 
 protected:
 
     //within the spin box this is an optional value since we don't need it to restore
     //non-numeric input; if you choose you can just use the native float Value
     //and convert it to int when required
     UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Input Data")
     int32 IntegerValue;
 
     //this is an entirely optional value that your designers can use to
     //create alternative displays of the current, validated IntegerValue
     UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Input Data")
     FText DisplayValue;
 
 public:
 
     UMyIntegerSpinBox();
 
     //~ Begin UWidget Interface
     virtual TSharedRef<SWidget> RebuildWidget() override;
     // End of UWidget
 
     UFUNCTION(BlueprintCallable, Category = "User Input")
     void MyHandleOnValueChanged(float InValue);
 
     UFUNCTION(BlueprintCallable, Category = "User Input")
     bool ValidateIntegerValue(float& InValue);
 
     UFUNCTION(BlueprintCallable, Category = "User Input")
     int32 GetIntFromFloat(const float& FloatValue);
 
     UFUNCTION(BlueprintCallable, Category = "User Input")
     void UpdateDisplayValue();
 
 };
     
 //MyIntegerSpinBox.cpp
 
 #include "MyGame.h"
 
 #include "MyIntegerSpinBox.h"
     
 UMyIntegerSpinBox::UMyIntegerSpinBox()
     :
     USpinBox(),
     IntegerValue(GetIntFromFloat(Value)),
     DisplayValue(FText::AsNumber(IntegerValue))
 {}
 
 TSharedRef<SWidget> UMyIntegerSpinBox::RebuildWidget()
 {
     MySpinBox = SNew(SSpinBox<float>)
         .Style(&WidgetStyle)
         .Font(Font)
         .ClearKeyboardFocusOnCommit(ClearKeyboardFocusOnCommit)
         .SelectAllTextOnCommit(SelectAllTextOnCommit)
         .OnValueChanged(BIND_UOBJECT_DELEGATE(FOnFloatValueChanged, MyHandleOnValueChanged))
         .OnValueCommitted(BIND_UOBJECT_DELEGATE(FOnFloatValueCommitted, HandleOnValueCommitted))
         .OnBeginSliderMovement(BIND_UOBJECT_DELEGATE(FSimpleDelegate, HandleOnBeginSliderMovement))
         .OnEndSliderMovement(BIND_UOBJECT_DELEGATE(FOnFloatValueChanged, HandleOnEndSliderMovement))
         ;
     return BuildDesignTimeWidget(MySpinBox.ToSharedRef());
 
 }
 
 void UMyIntegerSpinBox::MyHandleOnValueChanged(float InValue) {
     if (ValidateIntegerValue(InValue)) {
         HandleOnValueChanged(InValue);
 
     }
 
 }
 
 bool UMyIntegerSpinBox::ValidateIntegerValue(float& InValue) {
     //checking to make sure the value is different prevents an infinite loop via SetValue
     if (Value != InValue) {
         //round up or down, depending on where we're going
         InValue = Value < InValue ? FMath::CeilToFloat(InValue) : FMath::FloorToFloat(InValue);
 
         //then we have to set the value back to the spinner
         SetValue(InValue);
 
         //we can store the integer value if desired
         IntegerValue = GetIntFromFloat(InValue);
         //you can use CeilToFlot or Floor if you prefer
         //IntegerValue = FMath::CeilToFloat(InValue);
         //IntegerValue = FMath::Floor(InValue);
 
         //finally, update the optional FText display value
         UpdateDisplayValue();
         return true;
 
     }
     return false;
 
 }
 
 int32 UMyIntegerSpinBox::GetIntFromFloat(const float& FloatValue) {
     if (FloatValue >= 0.0f) {
         return (int)(FloatValue + 0.5f);
 
     }
     return (int)(FloatValue - 0.5f);
 
 }
 
 void UMyIntegerSpinBox::UpdateDisplayValue() {
     DisplayValue = FText::AsNumber(IntegerValue);
 
 }
more ▼

answered Oct 23 '16 at 01:10 AM

avatar image

GigasightMedia
1.7k 42 11 60

(comments are locked)
10|2000 characters needed characters left

If you are not set on an editable text box, you can look into SNumericEntryBox https://api.unrealengine.com/INT/API/Runtime/Slate/SNumericEntryBox/index.html

more ▼

answered Dec 07 '18 at 06:59 PM

avatar image

TastyStock
3 1 2

(comments are locked)
10|2000 characters needed characters left
Your answer
toggle preview:

Up to 5 attachments (including images) can be used with a maximum of 5.2 MB each and 5.2 MB total.

Follow this question

Once you sign in you will be able to subscribe for any updates here

Answers to this question