Create Widget does not add widget to the viewport

I’m trying to add 10 images (InventorySlots) to my inventory tool bar, and create widget doesnt seem to add it to the uniform grid panel.
I have an “Inventory” c++ class based on UserWidget class, Inventory c++ class has a child blueprint class that implements the base uniform grid panel (the white bar is a “frame” for the grid panel, dont mind that)

Then I have another c++ class “InventoryBarSlot” (again based on UserWidget) that has a child blueprint widget that adds a simple image which is bound to the parent class (InventoryBarSlot). (This is the image that I want to add 10 times to the uniform grid panel)
kép

And now when I try to create the new widget it just doesnt do anything, runs without errors, but nothing is displayed, here is the code


The commented “//UImage* img = NewObject(UImage::StaticClass());” works flawlessly, it adds 10 blank images to the uniform grid panel, but the createwidget function just doesnt work. I tried to use different methods for the create widget but none of them worked, all compiled with errors, only the StaticClass() method worked without errors but still it doesnt display it. (If I manually display the InventorySlot through gamemode in blueprints, then it displays it streched to the whole screen, so it should be working in c++ too).

Thanks for any help!

I’m not seeing “Add to Viewport”… which is needed to add a widget to the viewport (screen).

1 Like

Tried that too, but it didnt work, where should I add it? Added it after (below) CreateWidget.

InventoryBarSlot → AddToViewport();

Add After: CreateWidget

1 Like


added it, no difference

With simple images (UImage* img = NewObject(UImage::StaticClass());):

Encapsulation!

  • Create a new function that creates and adds the view port to the screen.
  • Remove creation from AddInventoryBarSlots.
  • Execute Creation, then execute AddInventoryBarSlots.

Your creation code is inside a LOOP.


Is that what you meant? Or I messed it up?
Because it compiles with an error saying that the “InventoryBarSlot” variable is not declared in “AddInventoryBarSlots” function, I thought it would notice that its declared because of the before function.

Or should I declare it in the header then initiliaze it in the “AddSlotToViewport” function?

Thanks for your help!

I tried the method that I mentioned in the last line of my last comment, and still nothing, it doesnt add it. I must be missing something.

In AddSlotToViewport AFTER AddToViewport Call your loop.

InventoryBarSlot -> AddInventoryBarSlots();

Two Flow options exist here.

  • Create, Add to Viewport, Loop (create the grid slots).
  • Create, Loop, Add to viewport.

All of which are simply the order of the calls in the AddSlotToViewport function.


Like this? Sill nothing.


Wow, it doesnt add it anyway. Not even one instance of it.

Where is UCPP_InventoryBarSlot coming from?

I would expect all of those references to be UCPP_Inventory as noted in your construct.

Thus widget creation and viewport would be:
InventoryBarSlot = CreateWidget<UCPP_Inventory>(this, UCPP_Inventory::StaticClass());
InventoryBarSlot->AddToViewport();

UCPP_InventoryBarSlot (its parent is UserWidget) class is the parent class of the blueprint widget that I want to display (maybe I should display its child?!)

Its not a child of the c++ class where Im writing the functions (Inventory class)

Im on mobile, cant include pictures of the structures.

But its something like this:

  • UserWidget

    • UCPP_Inventory.cpp
      • Blueprint where I have the uniform grid panel (forgot the BP name)
  • UserWidget

    • UCPP_InventoryBarSlot.cpp
      • Blueprint with inventory slot that I want to addtoviewport

UCPP_InventoryBarSlot is just #included in the header of UCPP_Inventory

(Ooh, I had indentations on the structure, not sure how to add bulletpoints on mobile)

I have found a solution!

First, the problem was that I was trying to add the widget to the viewport inside itself, and you dont have a BeginPlay function in widget blueprints, BUT you can call ANY other widget inside a widget excluding itself in the NativeConstruct (so you can add widget to the viewport if it is not itself). Now I have added the Inventory through the character c++ class with the following commands:

Header

  • First #include the proper widget header file to your c++ character/gamemode/playerController header (for me it is CPP_Inventory.h): #include "CPP_Inventory.h"
  • Then declare some variables
UPROPERTY(EditAnywhere)
TSubclassOf<UCPP_Inventory> InventoryClass;
UPROPERTY(VisibleInstanceOnly, Category="Runtime")
UCPP_Inventory* Inventory;

CPP

  • Under BeginPlay create the widget and add it to the viewport
Inventory = CreateWidget<UCPP_Inventory>(GetWorld(),InventoryClass);
Inventory->AddToViewport();

Now the coding part is done, but it will crash the editor if you try to play, that is because we havent set the proper class for the created variable above (TSubclassOf<UCPP_Inventory> InventoryClass;). For that we just have to set the class here:
kép

This is under Graph->Class Defaults, and your variable name.

You can add some further code if you dont want to crash the editor if you forgot to select the class here, to do that just add something similar to this:

if(IsValid(InventoryBarSlotClass)){
        InventoryBarSlot = CreateWidget<UCPP_InventoryBarSlot>(GetWorld(),InventoryBarSlotClass);

        if(InventoryBarSlot != nullptr){
            InventoryBarSlot->AddToViewport();
        }
    }

The above code doesnt try to create the widget if the class is not set, so the editor wont crash.

Now back to the original problem, I wanted to add the created widget to the uniform grid panel 10 times.

  • Include necessary header files
  • Create variables and two functions inside header:
protected:
	void AddInventoryBarSlots();
	void NativeConstruct() override;
	UPROPERTY( meta = (BindWidget))
	UImage* InventoryBarFrame;
	UPROPERTY( meta = (BindWidget))
	UUniformGridPanel* InventoryBarSlotPanel;


	UPROPERTY(EditAnywhere)
	TSubclassOf<UCPP_InventoryBarSlot> InventoryBarSlotClass;
  • Code the created AddInventoryBarSlots function
function void UCPP_Inventory::AddInventoryBarSlots(){
    for(int i = 0; i <= 9; i++)
    {
        UPROPERTY(VisibleInstanceOnly, Category="Runtime")
	    UCPP_InventoryBarSlot* InventoryBarSlot = CreateWidget<UCPP_InventoryBarSlot>(GetWorld(),InventoryBarSlotClass);
        InventoryBarSlotPanel->AddChildToUniformGrid(InventoryBarSlot,0,i);
    }
}
  • Then call it inside the NativeConstruct function
void UCPP_Inventory::NativeConstruct(){
    Super::NativeConstruct();

    AddInventoryBarSlots();
}
  • Lastly set the class inside the Blueprint like before:
    kép

Result:

All this sounds/looks way more complicated then it really is!