Slate button causes the editor to hang when instantiated

I’m poking around in Slate for the first time and it’s pretty neat. I’ve created a tab, added some UI and added a button, but when I instantiate the tab in the editor the entire editor hangs.

  1. How do you debug something like that?
  2. How should I have implemented it?

This is what I have:


SNew(SButton).OnClicked(this, &FMyPluginModule::OnActivateButtonClicked)

I was originally getting following error during compile:


error C2039: 'AsShared' : is not a member of 'FMyPluginModule'

So after googling around, in my .h file I inherited from the TSharedFromThis template:


class FMyPluginModule : public IModuleInterface, public TSharedFromThis<FMyPluginModule >

Which is fine until the tab instantiates, then it hangs.

I fired up the debugger with the onclicked() line as a breakpoint but I’m still a bit new to this so without knowing more about the engine and delegates, it wasn’t very helpful.

So, what’d I do wrong?

I understand the basic concept of delegates and I’ve used them in C# but naturally everything is more difficult in C++. In particular I don’t have my head around the TSharedRef<> template yet. In particular, can someone explain what’s happening here?


TSharedRef<class SDockTab> OnSpawnPluginTab(const class FSpawnTabArgs& SpawnTabArgs);

So I’m assuming that when this is instantiated, a value somewhere is incremented so that SDockTab can be garbage collected once OnSpawnPluginTab is removed. Is this right? My description feels a bit ***-backwards to me.

Are there any good resources to read that would help me out here?

1 Like

I’d start with this reference.

OnSpawnPluginTab is just creating a new widget, which it returns wrapped in a shared reference. So yes, essentially it is just something to help maintain the lifetime of the object for as long as something is relying on it.

OnClicked is expecting a shared ptr/ref, or something that can be converted to one. If you use OnClicked_Raw instead, that expects a normal pointer, so you wouldn’t need to derive from TSharedFromThis. It’s hard to say if/why that would be causing the crash though. Posting more contextual code may help, but really you just need to step through the debugger and find what triggered it - most probably accessing a null pointer or freed memory somewhere.

Thanks for the reply! It wasn’t a crash per se, it just hung, as in it was doing something, endlessly.

I should have been more clear as I know what the delegate functions themselves do. My specific question is, what’s this?


TSharedRef<class SDockTab> OnXYZFunction

Is OnXYZFunction passing something to the TSharedRef<class SDockTab> part or something? How do we mentally structure this? What exactly is TSharedRef<class SDockTab> doing? I understand templates as well, just not THIS template, mostly because my grasp of what it’s doing with the reference is still a bit sketchy.

Check out the link from kamrann and read the documentation on shared pointers.

TSharedRef<class SDockTab> is just a shared reference to a SDockTab widget.

and when it comes to this:


SNew(SButton).OnClicked(this, &FMyPluginModule::OnActivateButtonClicked)

you dont have to make use of


public TSharedFromThis<FMyPluginModule >

to bind OnClicked delegate. It’s just that slate events takes Shared pointers as default while binding but you’re not limited to them.
You can bind delegates to static functions, UObjects and raw (native) c++ objects. You can actually use this code and it should work as expected:


SNew(SButton).**OnClicked_Raw**(this, &FMyPluginModule::OnActivateButtonClicked)

If you would like to bind OnClicked to an UObject you would do something like this:


SNew(SButton).**OnClicked_UObject**(UOBJECT_POINTER, &UMyObject::OnActivateButtonClicked)

For more examples check out the source code of other plugins and make use of widget reflector inside Unreal Editor to check out the source code of specific widgets.

Cheers

4 Likes

Gotcha. It seems to be what I thought then, I just didn’t know about _raw. I thought there was some black magic going on, but I guess not. :slight_smile: Thanks again!

I’m not sure I follow, but it seems your question is more of C++ syntax.


TSharedRef<class SDockTab>

This is just a type, just like int or SDockTab or SDockTab*. We can describe it as the type ‘Shared reference to SDockTab’. The fact that the type is generated from a template is essentially irrelevant.


TSharedRef<class SDockTab> OnSpawnPluginTab(const class FSpawnTabArgs& SpawnTabArgs);

So this is just a function declaration, of a function that returns a ‘Shared reference to SDockTab’. If you look at the implementation, it is just calling SNew, which creates a new SDockTab and stuffs it into the shared reference.

So


TSharedRef<class SDockTab> MyThing()

is similar in concept to writing


SDockTab& MyThing()

?

Absolutely. On a high conceptual level, they’re the same.

In practice, the latter is a raw C++ reference to a SDockTab, which guarantees nothing about the lifetime of the SDockTab being referenced. The former is a smart reference, an object which conceptually acts like a reference to a SDockTab, but ensures that the SDockTab will continue to exist at least as long as the reference itself does.

Ah, that’s much more clear now. Thank you for helping me connect the dots!

So having moved on from that issue, I’m having trouble with a different SLATE_EVENT.


SNew(SEditableTextBox).OnTextCommitted(this, &FMyPluginModule::MyUsernameUpdated)

This compiles but hangs on load. Two questions:

  1. If I know what line is causing it to hang, is there any point in firing up the debugger?
  2. Why is it likely to be hanging?

The last delegate is working and I’ve done the same thing for this one (except it has arguments). Here’s the delegated function:


void FMyPluginModule::MyUsernameUpdated(const FText& Value, ETextCommit::Type Type){
    UE_LOG(LogTemp, Warning, TEXT("Username updated"));
}

Edit: nevermind, there’s a OnTextCommitted_Raw() method I totally forgot to look for.

1 Like