Béatrice M.
Béatrice M.

Reputation: 972

C++ Qt - How can (virtual) QWidget points to its children?

I am trying to change the border of a QFrame. BUT.

There is a Window::ui, inside of which there is a class inheriting from QWidget. In that class, there is a QFrame, set with a vertical Layout, which holds 2 other QFrame and do their QFrame business. Now, this structure is repeated a lot in Window::ui, so I simply added it to a vertical layout named kingdom_decks.

So far, so good.

Let's say, I want to select one of those element. To mark the selection, I want to change the border, from black to red, or just make it thicker. With a QFrame, very easy. BUT

My event handler is a slot in Window::ui. ui goes to kingdom_decks layout, and go to the item selected. itemAt retourn a QLayoutItem, that I can cast as QWidget with widget()... but then?

ui->kingdom_decks->itemAt(idx_prev)->widget()

I tried unsuccessfully

 ui->kingdom_decks->itemAt(idx_prev)->widget()->childAt(0,0)

I believe it failed because there is a Qframe in a Layout, instead of a geometry form with real coordonates, or maybe I didn't go deep enough?

Anyway, thank you very much in advance for any ideas on that! Thanks for your time.

EDIT

Code for window.cpp

    #include "window.h"
    #include "ui_window.h"


    Window::Window(Game_state * p, Card_generator * d, QWidget *parent) :
        QDialog(parent),
        ui(new Ui::Window)
    {
        ui->setupUi(this);

        /*Stuff happen here*/

        /* Display cards*/
        for (int i = 0; i < 10; ++i){

                /*Add widget to layout*/
                ui->kingdom_decks->addWidget(new Cards_kingdom(decks->decks_kingdom[i]),0,i);

                /*Connect widget to map*/
                connect(ui->kingdom_decks->itemAt(i)->widget(), SIGNAL(mousePressEvent()), signal_mapper, SLOT(map()));

                /*Map widget and data*/
                signal_mapper->setMapping(ui->kingdom_decks->itemAt(i)->widget(), i);
}

        /* Action "Select cards" */
        connect(signal_mapper, SIGNAL(mapped(int)), this, SLOT(card_kingdom_selected(int)));


    }

    Window::~Window()
    {
        delete ui;
    }


    /*Implementation of SLOT*/

    void Window::card_kingdom_selected(int idx){

    /*...*/
    //?????????????? What to do here???????????
    //ui->findChild<QLabel *>("img");
    //ui->kingdom_decks->itemAt(idx)->widget()->????;
    }

So what happen here is that I have a layout kingdom_decks, in which I loop to add a widget Cards_kingdom, overloading the function addWidget.

ui->kingdom_decks->addWidget(new Cards_kingdom(decks->decks_kingdom[i]),0,i);

This Object Cards_kingdom is a class, such that:

cards_kingdom.h :

class Cards_kingdom : public QWidget {

public:
    Cards_kingdom(Deck_kingdom * input_deck);    /* Constructor  */
    bool isSelected();
    QLabel * get_img();
/*
 * Price and Counter are display in the same label, then are wrapped with Icon in a vertical layout, inside a frame.
 */
private:
    QLabel       *img;       /* Icon         */
    QLabel       *info;      /* Nb Cards left*/
    QVBoxLayout  *layout;    /* Layout       */
    QFrame       *pack;      /* Frame        */
    Deck_kingdom *deck;      /* Type Deck    */
    bool select;
};

In window.cpp, i try to retrieve the QLabel * img, to put a border on this image, such that the user sees that it has been selected.

To answer to @Nicholas Smith, how can findChild, find the exact instanciation of Card_kingdom?

EDIT:

OK, I could change my architecture to something like this:

Create a vector of Cards_kingdom * vec

In the for loop, vec.push_back(new Card_kingdom *); ui->layout->addWIdget(vec[i])

So now, I think that would work, because layout is holding a pointer to my widget, so I pass by reference, therefore, if I change something in my object, it will appear in the GUI even if I didn't pass by there...

Right? :)

Upvotes: 0

Views: 605

Answers (1)

Nicholas Smith
Nicholas Smith

Reputation: 11754

The fun thing with Qt is layouts can become nests and layers and mazes, but I've just had this exact issue with a different twist, I'd personally go for something along the lines of ui->findChild<QFrame *>("frameObjectName") (if you've created QFrame as pointer, if not just drop the *) and access it from there. You'll need to make sure you have an object name filled it for the frame, but that's not too hard and has other benefits.

Upvotes: 0

Related Questions