How can I get the text from an editable text in C++

I have created an editabletextbox (EditNum1) but I can’t seem to get the text from the textbox using OnTextChanged or OnTextCommited. Instead, I have added this code to a OnClicked listener but I am not getting any text from the EditableTextBox. Any C++ examples would be great;y appreciated.

userValue = EditNum1->GetText().ToString();
int32 NewInt = FCString::Atoi(*userValue);
sum = NewInt;
1 Like

Hi AeolusRlcky,

This is how I’ve got it set up using the hooks:

FReply FMyOptionsCustomization::OnKeyCharHandler(const FGeometry& geo,const FCharacterEvent& charEvent) {
	TCHAR ch=charEvent.GetCharacter();
	if( (ch>=L'a' && ch<=L'z') || (ch>=L'A' && ch<=L'Z') || (ch>=L'0' && ch<=L'9') ) return FReply::Unhandled();
	return FReply::Handled();
}

FText FMyOptionsCustomization::GetMyName() const { return  FText::FromString(*MyOptions->MyName); }

void FMyOptionsCustomization::SetMyName(const FText& NewText, ETextCommit::Type InTextCommit) const { 
	MyOptions->MyName=NewText.ToString(); 
	MyOptions->bItExists=myListBlahContains(MyOptions->MyName);
}


			SNew(SEditableTextBox)
			.Text(this, &FMyOptionsCustomization::GetMyName)
			.OnTextCommitted(this, &FMyOptionsCustomization::SetMyName)
			.OnKeyCharHandler(this,&FMyOptionsCustomization::OnKeyCharHandler)
			.ForegroundColor_Lambda([=]{ return (MyOptions->bItExists)?FLinearColor(0.4f,0.0f,0.0f):FLinearColor(0.0f,0.4f,0.0f); })
			.SelectAllTextWhenFocused(true)
			.SelectAllTextOnCommit(false)
			.ClearKeyboardFocusOnCommit(true)
			.RevertTextOnEscape(true)
			.MinDesiredWidth(194)

2 Likes

Thanks RecourseDesign. I am new to c++, and want to create a calculator. Do you have this project on GitHub so that I can have a look?
I keep getting an error that I need to create a namespace or class

2 Likes

This is what I have so far:
#include “RndWidget.h”
#include <Components/Button.h>
#include <Components/TextBlock.h>
#include <Components/EditableTextBox.h>
#include
using namespace std;

int SUM = 0;
FString userValue;
int RANDOM_NUM1 = FMath::RandRange(5, 15);
int RANDOM_NUM2 = FMath::RandRange(5, 15);
int RANDOM_NUM3 = FMath::RandRange(5, 15);

//namespace globals {
//FText Text1;
//}

void URndWidget::NativeConstruct() {

Super::NativeConstruct();

CalculateRandom();
CalculateSum();

RndBtn->OnClicked.AddUniqueDynamic(this, &URndWidget::OnRandomClicked);
SumBtn->OnClicked.AddUniqueDynamic(this, &URndWidget::OnSumClicked);
//EditNum1->OnTextChanged.AddUniqueDynamic(this, &URndWidget::OnSumClicked);

}

void URndWidget::OnRandomClicked() {
CalculateRandom();
}

void URndWidget::OnSumClicked() {
CalculateSum();
}

void URndWidget::CalculateRandom() {
RANDOM_NUM1 = FMath::RandRange(1, 15);
RANDOM_NUM2 = FMath::RandRange(5, 15);
RANDOM_NUM3 = FMath::RandRange(5, 15);

RndNumTxt1->SetText(FText::AsNumber(RANDOM_NUM1));
RndNumTxt2->SetText(FText::AsNumber(RANDOM_NUM2));
RndNumTxt3->SetText(FText::AsNumber(RANDOM_NUM3));

}

void URndWidget::CalculateSum() {

userValue = EditNum1->GetText().ToString();

int32 NewInt = FCString::Atoi(*userValue);

SUM = NewInt;

RndNumTxt1->SetText(FText::AsNumber(SUM));

}

The code I pasted uses a slightly different approach (built by the UI system). I copy/pasted that out of a plugin I sell so can’t really publish the code here (rdLODtools and has the source included if you already own it).

I think you’re “EditNum1->OnTextChanged.AddUniqueDynamic” is along the correct lines - what error does that produce?

Did you try “AddDynamic()” rather than AddUniqueDynamic()?

1 Like

Thanks, I tried both but no luck. I really thought this was going to be straight forward hahaha:
I get this error for both AddUnique and AddDynamic
C++ no instance of function template matches the argument list argument types are: (URndWidget , void (URndWidget::)(), FName) object type is: UEditableTextBox::FOnEditableTextBoxCommittedEvent

Just going to use the OnClickedEvent and revisit this later. Thanks again for the assist. This works:

#include “RndWidget.h”
#include <Components/Button.h>
#include <Components/TextBlock.h>
#include <Components/EditableTextBox.h>
#include
using namespace std;

int SUM = 0;
FString userValue;
int RANDOM_NUM1 = FMath::RandRange(5, 15);
int RANDOM_NUM2 = FMath::RandRange(5, 15);
int RANDOM_NUM3 = FMath::RandRange(5, 15);

void URndWidget::NativeConstruct() {

Super::NativeConstruct();

CalculateRandom();
CalculateSum();

RndBtn->OnClicked.AddUniqueDynamic(this, &URndWidget::OnRandomClicked);
SumBtn->OnClicked.AddUniqueDynamic(this, &URndWidget::OnSumClicked);
//EditNum1->OnTextCommitted.AddDynamic(this, &URndWidget::OnSumClicked);

}

void URndWidget::OnRandomClicked() {
CalculateRandom();
}

void URndWidget::OnSumClicked() {
CalculateSum();
}

void URndWidget::CalculateRandom() {
RANDOM_NUM1 = FMath::RandRange(1, 15);
RANDOM_NUM2 = FMath::RandRange(5, 15);
RANDOM_NUM3 = FMath::RandRange(5, 15);

RndNumTxt1->SetText(FText::AsNumber(RANDOM_NUM1));
RndNumTxt2->SetText(FText::AsNumber(RANDOM_NUM2));
RndNumTxt3->SetText(FText::AsNumber(RANDOM_NUM3));

}

void URndWidget::CalculateSum() {
userValue = EditNum1->GetText().ToString();
int32 NewInt = FCString::Atoi(*userValue);
SUM = NewInt;
SumNumTxt->SetText(FText::AsNumber(SUM));
}

1 Like

This post was very useful to me and I managed to create a text box and get text from it purely in C++ (4.27). I thought some people might want an example because it was actually really tricky to find any info about this online.

The text box is invisible because I have my own text box solution that I feed with the characters gotten from the widget. This is great because I can get characters generated by the platform, keyboard settings and everything, with no work on my side. I haven’t explored what it would take to make the text box visible or usable in the game.

Anyway, here’s a code example:

// H file content

#include "Widgets/Input/SEditableTextBox.h"

TSharedPtr<SEditableTextBox> m_textBox;

FReply OnKeyCharHandler(const FGeometry& geo, const FCharacterEvent& charEvent);

FReply OnKeyDownHandler(const FGeometry& geo, const FKeyEvent& keyEvent);


// CPP content, put this literally anywhere.

// Creates the text box with some settings.
m_textBox = SNew(SEditableTextBox)
    .SelectAllTextWhenFocused(true)
    .SelectAllTextOnCommit(false)
    .ClearKeyboardFocusOnCommit(true)
    .RevertTextOnEscape(true)
    .IsReadOnly(false);

// Add handlers to catch the characters and even some FKeys(not the mouse ones).
// Use CreateRaw if not in UObject code.
m_textBox->SetOnKeyCharHandler(FOnKeyChar::CreateUObject(this, &AMyUObjectClass::OnKeyCharHandler));
m_textBox->SetOnKeyDownHandler(FOnKeyDown::CreateUObject(this, &AMyUObjectClass::OnKeyDownHandler));

// This gets whatever widget has the focus and puts the text box under it so it actually works.
// I haven't added any widgets to my project, so I expect this to work on any project.
TSharedPtr<SWidget> focusedSlateWidget = FSlateApplication::Get().GetUserFocusedWidget(0);
m_textBox->AssignParentWidget(focusedSlateWidget);

// Call this to start typing.  All non-mouse inputs will be directed to the text box instead of your game.
FSlateApplication::Get().SetUserFocus(0, m_textBox, EFocusCause::SetDirectly);


FReply AMyUObjectClass::OnKeyCharHandler(const FGeometry& geo, const FCharacterEvent& charEvent)
{
    TCHAR ch = charEvent.GetCharacter();
    
    if(ch == L'a')
        // Do something if the character is lowercase a.

    // I always return Handled because I don't want the tex box to actually have anything in it.
    // If you want the text box to actually receive characters, return Unhandled.
    // __You could also get the text from your text box at any time by simply calling GetText() on m_textBox.__
    return FReply::Handled();
}

FReply AMyUObjectClass::OnKeyDownHandler(const FGeometry& geo, const FKeyEvent& keyEvent)
{
    FKey key = keyEvent.GetKey();

    if (key == EKeys::Enter)
    {
        // Do whatever logic you need to do when Enter is pressed.

        // Release the focus from the textbox and put it back on the window(very important).
        FSlateApplication::Get().ReleaseAllPointerCapture();
        FSlateApplication::Get().SetUserFocusToGameViewport(0);
    }
    else if (key == EKeys::Escape)
    {
        // Do whatever logic you need to do when Escape is pressed.

        // Release the focus from the textbox and put it back on the window(very important).
        FSlateApplication::Get().ReleaseAllPointerCapture();
        FSlateApplication::Get().SetUserFocusToGameViewport(0);
    }

    // I always return Handled because I don't want the tex box to actually receive key events.
    // If you want the text box to actually receive the key events and commit or revert the text entered, return Unhandled.
    return FReply::Handled();
}