Unreal Engine 4.27.2 C++ | SetText not updating UserWidget’s TextBlock from a WidgetComponent in a BP - unreal-engine4

I have an Actor BP, inside this BP I have a UWidgetComponent with a Widget Class already selected in the Details, and that Widget Class has a TextBlock. Now, inside this BP I also have a C++ USceneComponent, this component is in charge of showing a random text, in the TextBlock mentioned above, each time the user presses a button.
This is in my USceneComponent's header file (.h)
class UWidgetComponent* QuestionWidget;
class UQuestionProjectionText* QuestionText;
class UTextBlock* QuestionTextBlock;
Then in the ".cpp" file, in the constructor
QuestionWidget = CreateDefaultSubobject<UWidgetComponent>(TEXT("CodeQuestionWidget"));
QuestionTextBlock = CreateDefaultSubobject<UTextBlock>(TEXT("CodeTextBlock"));
Then in the BeginPlay()
//Gets the WidgetComponent from the BP
QuestionWidget = Cast<UWidgetComponent>(GetOwner()->GetComponentByClass(UWidgetComponent::StaticClass()));
if (QuestionWidget)
{
QuestionWidget->InitWidget();
//Gets an instance of the UMyUserWidget class, from the UWidgetComponent in the BP
QuestionText = Cast<UMyUserWidget>(QuestionWidget->GetUserWidgetObject());
this->QuestionTextBlock = QuestionText->QuestionTextBlock;
//Sets the text to an empty String
QuestionTextBlock->SetText(FText::FromString(""));
}
else
{
UE_LOG(LogTemp, Error, TEXT("QuestionWidget was not found"));
return;
}
Then in the TickComponent(), when the user presses the button, I use a something that looks like this
QuestionTextBlock->SetText(FText::FromString(QuestionStringsArray[9]));
The problem is that when I press the button, the text does not change in the Widget, but if I print the text that I'm passing, it does print the string, so I'm not passing an empty value to the "SetText()".
Another weird thing, is that the line in the BeginPlay that sets the text, that one works, I have changed it to a random string, instead of an empty one, and it does display it.
I don't know if when I do the "QuestionWidget->InitWidget();" I'm creating a new one separate from the one in the BP, or if I'm just missing something. If I eliminate the "QuestionWidget->InitWidget()" the widget gets initialized on time sometimes, and sometimes it doesn't.
I have some error handling in my code, but eliminated it here so that it didn't look too messy. But also, none of the Errors popup, everything goes on smoothly, only that the Widget doesn't show the updated Text.

Related

How can I detect a Paste event in a TextEditingController?

I have a TextEditingController which is for phone numbers. If text is pasted in it, I need to process and modify it, trimming whitespaces etc. But that should not happen if the user is typing in whitespaces. How can I differentiate between these two types of events, and call my function only when user pastes text into the field?
Currently my code looks like this and uses onChanged. I'm looking for something like onPaste:
String getCorrectedPhone(String phone) {
phone = phone.replaceAll(RegExp(r"\s+"), "");
return phone;
}
FormBuilderTextField(
controller: _phoneController,
name: "phone",
onChanged: (String txt) {
print('Phone field changed! Is now $txt');
_phoneController.text = getCorrectedPhone(txt);
},
),
You can do something like declare a length with the phone number field and add a listener to the text editing controller or in oNchanged which checks if its length - the old length is >1. Then its pasted
int length = 0;
...
_phoneController.addListener((){
if (abs(textEditingController.text.length - length)>1){
// Do your thingy
}
length = _phoneController.length;
});
So there is another way, that is to ignore any touches on the text field using the IgnorePointer widget and then use Gesture Detector to implement custom long tap and short taps. For long taps, you'll have to create your own small pop up menu for copy cut paste and stuff. Here is some sample code for the UI. As for the functioning, I would recommend using the https://api.flutter.dev/flutter/services/Clipboard-class.html class of flutter. If you need any help in doing this let me know but it should be mostly straightforward

How to access control from the popup fragment by ID

I want my text area to be empty after I press OK button.
I have try this line this.byId("id").setValue("")
onWorkInProgress: function (oEvent) {
if (!this._oOnWorkInProgressDialog) {
this._oOnWorkInProgressDialog = sap.ui.xmlfragment("WIPworklist", "com.sap.FinalAssestments.view.WorkInProgress", this);
//this.byId("WIP").value = "";
//this.byId("WIP").setValue();
this.getView().addDependent(this._oOnWorkInProgressDialog);
}
var bindingPath = oEvent.getSource().getBindingContext().getPath();
this._oOnWorkInProgressDialog.bindElement(bindingPath);
this._oOnWorkInProgressDialog.open();
},
//function when cancel button inside the fragments is triggered
onCancelApproval: function() {
this._oOnWorkInProgressDialog.close();
},
//function when approval button inside the fragments is triggered
onWIPApproval: function() {
this._oOnWorkInProgressDialog.close();
var message = this.getView().getModel("i18n").getResourceBundle().getText("wipSuccess");
MessageToast.show(message);
},
The text area will be in popup in the fragment. I am expecting the text area to be empty.
If you instantiate your fragment like this:
sap.ui.xmlfragment("WIPworklist", "com.sap.FinalAssestments.view.WorkInProgress", this);
You can access its controls like this:
Fragment.byId("WIPworklist", "WIP").setValue(""); // Fragment required from "sap/ui/core/Fragment"
Source: How to Access Elements from XML Fragment by ID
The better approach would be to use a view model. The model should have a property textAreaValue or something like that.
Then bind that property to your TextArea (<TextArea value="{view>/textAreaValue}" />). If you change the value using code (e.g. this.getView().getModel("view").setProperty("/textAreaValue", "")), it will automatically show the new value in your popup.
And it works both ways: if a user changes the text, it will be automatically updated in the view model, so you can access the new value using this.getView().getModel("view").getProperty("/textAreaValue");.
You almost have it, I think. Just put the
this.byId("WIP").setValue("") line after the if() block. Since you are adding the fragment as a dependent of your view, this.byId("WIP") will find the control with id "WIP" every time you open the WIP fragment and set its value to blank.
You are likely not achieving it now because A. it is not yet a dependent of your view and B. it is only getting fired on the first go-around.

How to validate Text mesh pro input field text in unity

I have tried to use text mesh pro input field in my project but I have face one series issue with that. i.e If try to validate empty or null text in input field it fails. For example when user without typing any text in tmp input field and click done button I have set a validation like not allowed to save null empty values but when user click done button without typing any text, those validations are fails. Please suggest any idea to fix this issue. Thanks in advance.
Here is the code I have tried :
var text = TextMeshProText.text; // here "TextMeshProText" is 'TMP_Text'
if(!string.IsNullOrEmpty(text))
{
//do required functionality
}
else
{
// Show alert to the user.
}
I have set the validation like this but without giving any text click on done button it fails null or empty condition and enter in to if.
I found the problem. It fails because you use TMP_Text instead TMP_InputField.
Note that: Use the code for TMP_InputField; not for TMP_Text that is inside it as a child.
Change your code to this:
TMP_InputField TextMeshProText;
...
public void OnClick ()
{
var text = TextMeshProText.text; // here "TextMeshProText" is 'TMP_InputField'
if (!string.IsNullOrEmpty(text))
{
//do required functionality
}
else
{
// Show alert to the user.
}
}
I hope it helps you

How to lock Form during lunch a class?

I have a simple Form MyCustomForm, in a Form's Button in Clicked method I call a Class (method run), so I want to lock (or block) this form during run execution.
My code is look like this :
void clicked()
{// in Button clicked in **MyCustomForm**
MyClass myClass;
super();
myClass = new MyClass();
// here I want to freeze my FORM
myClass.run();
// here I want to unlock my Form
}
I need this because when class (MyClass) is running can display Dialog etc, but I don't want to touc/click and other on MyCustomForm
If I use :
element.wait(); // not work well - block all
myClass.run();
Thanks,
enjoy.
If your class displays dialog you can make this dialog modal using the following line of code dialog.parmIsModal(true).
Or formRun.wait(true) for forms.

gtkentry focus behaviour

Is there any existing mechanism for a GtkEntry to simply position the cursor at the end of the text when focused, rather than selecting its contents to be overwritten by the next key? It seems odd to have to add a signal handler to do something this basic, but I can't find anything in the properties.
Edit: The signal handler doesn't work; whatever I do the default behaviour gets triggered after my handler runs. Here's my gtkd code; note that I am appending some text in the focus-in-event handler, and the appended text gets selected as well:
class NoteView : Entry
{
this(string text) {
if (text) {
setText(text);
}
setEditable(true);
setCanFocus(true);
addOnFocusIn(delegate bool(GdkEventFocus* f, Widget w) {
// clear selection
selectRegion(0, 0);
// test to see whether the appended text gets selected too
appendText("hello");
setPosition(-1);
// don't let any other handlers run
return 1;
}, ConnectFlags.AFTER);
}
}
The addOnFocusIn method is in the gtkd Gtk.Widget api; it calls g_signal_connect_data internally, which should in theory be honouring the G_CONNECT_AFTER flag I'm passing it, but doesn't seem to be.
Edit2: Solved - the grab-focus handler was doing the text selection, and being handled after focus-in-event
Turns out GtkEntry was selecting the text on the grab-focus signal, not focus-in-event. Working code:
class NoteView : Entry
{
this(string text) {
if (text) {
setText(text);
}
setEditable(true);
setCanFocus(true);
setHasFrame(false);
addOnGrabFocus(delegate void(Widget w) {
selectRegion(0, 0);
setPosition(-1);
}, ConnectFlags.AFTER);
}
}
Can't find anything in the docs.
I guess they figured that diverging from the default behavior is that uncommon that they just let people do it with signals, rather than provide a property for it.
Consider creating a subclass of GtkEntry that exhibits the behavior you require.