[QT] jak przekazać przez this wskaźnik do klasy innemu obiek

0

Cześć

Mam taki problem: Klasa1 inicjuje obiekt z Klasa2, natomiast w jednej z funkcji w Klasa2 chce skorzystać z funkcji utworzonej w Klasa1. Gdzieś doczytałem, że powinienem w trakcie kreacji obiektu Klasa2 przekazać mu przez this wskaźnik do Klasa1, zapisać go w zmiennych Klasa2 (np. parent) i gdy będę chciał w obiekcie Klasa2 skorzystać z funkcji Klasa1 to zrobię coś takiego:
parent->funkcja_z_klasa1
czyli kod wygląda mniej więcej tak

klasa1.h: (MainWindow)

 
class MainWindow: public QMainWindow
{
public:
        MainWindow();
public slots:
        void showErr(QString);
private:
        StackedWidget *centralWidget;
};

klasa1.cpp (MainWindow)

MainWindow::MainWindow() : QMainWindow (0,Qt::Window)
{
        //nie ważne
        centralWidget = new StackedWidget(this);
        //nie ważne
}
void MainWindow::showErr(QString str) {
       // tą funkcje potrzebuje wywołać w obiekcie w klasie StackedWidget
}

klasa2.h (StackedWidget)

class StackedWidget : public QStackedWidget
{
public:
        StackedWidget(QWidget *parent = 0);

        //reszta nie ważna
};

klasa2.cpp (StackedWidget)

StackedWidget::StackedWidget(QWidget *parent) : QStackedWidget(parent)
{
        //konstruktor
}
void StackedWidget::p0_loginUser() {
        //w tej klasie chce wywołać funkcje z MainWindow
        //showErr("komunikat");
}

Próbowałem kombinować z przekazywaniem this w czasie inicjalizacji obiektu StackedWidget, a później wywoływać funkcje showErr bezpośrednio w konstruktorze StackedWidget (dla uproszczenia) ale jakbym tego nie pisał, zawsze wyskakuje jakiś błąd.
Kiedy w MainWindow przekazuje this w konstruktorze StackedWidget, to jaki typ zmienna ma mieć w konstruktorze klasy StackedWidget ?
Gdzieś tam wyczytałem coś takiego StackedWidget::StackedWidget(MainWindow& ptr) ale nie udało mi się tego uruchomić.
Jaka jest prawidłowa droga: chce mieć wewnątrz obiektu dostęp do funkcji klasy która zainicjowała obiekt.
Pomóżcie prosze.
pozdrawiam
Marek

0

aż się prosi o sygnał! Zdefiniuj sygnał void StackedWidget::errorReported(Qstring text);
Przy konstrukcji połącz go ze slotem MainWindow::showErr(QString).
W kodzie StackedWidget, gdzie chcesz wywołać MainWindow::showErr po prostu wpisz:

emit errorReported("Ale jaja");

PS. nie zapomnij o Q_OBJECT na początku StackedWidget.

0

Dzięki za podpowiedź z tym sygnałem na pewno skorzystam
i sorry że tak późno odpisuje.

pozdrawiam
Marek

0

Hej,

Jednak nie wszystko jest tak proste jak by się chciało, więc mam jeszcze pytanie.
Tak na prawdę strukturę klas mam taką:

  1. w main.cpp tworze obiekt window (zdefiowany w klasie MainWindow)
  2. w konstruktorze MainWindow tworzę obiekt centralWidget (zdefiniowany w klasie StackedWidget)
  3. w konstruktorze StackedWidget tworze obiekt itsql (zdefiniowany w klasie ItSql) która robi całą obsługę bazy i tam jak natrafię na błąd (coś nie tak w bazie, etc) to chce wyemitować sygnał z tym błędem, żeby odebrał go obiekt window i metoda showErr w nim zdefiniowana.
    czyli takie połączenie 3 obiektów.
    Pytanie jest takie, jak zrobić podłączenie tego sygnału prościej niż moimi wykombinowanymi sposobami:
  4. albo robię wszystkie obiekty publiczne (w tych 2 klasach) i podłączam w pliku main.cpp w ten sposób:
connect(window->centralWidget->itsql,SIGNAL(errorReported(QString)),window,SLOT(showErr(QString)))
  1. albo tworząc kolejne obiekty przekazuje referencje do klasy która obiekt utworzyła i (w konstruktorze ItSql) podłączam tak:
QObject::connect(this,SIGNAL(errorReported(QString)),parent_->parent_,SLOT(showErr(QString)));
  1. albo niejako w środku w konstruktorze StackedWidget
QObject::connect(itsql,SIGNAL(errorReported(QString)),parent_,SLOT(showErr(QString)));

ale dwa ostatnie sposoby wraz wymagają ode mnie zapisywania referencji do klasy która obiekt utworzyła, natomiast pierwszy, no nie wiem...
próbowałem wpisać w konstruktorze ItSql czyli tego ostatniego obiektu podłączenie sygnału na zasadzie:

QObject::connect(this,SIGNAL(errorReported(QString)),MainWindow,SLOT(showErr(QString)));

jakby odwołując się do definicji klasy MainWindow, ale zupełnie to nie działa, a błąd jest rodzaju:
error: expected primary-expression before ',' token

czyli tak jakby MainWindow to nie był dla kompilatora żaden obiekt QObject.
Także prośba o pomoc jakby mógł ktoś wyjaśnić.

pozdrawiam
Marek

0

Zdecydowanie nie rób tego w main.cpp, to narusza zasadę enkapsulacji!
Czemu nie w konstruktorze okna? To jest najbardziej naturalne miejsce na wykonanie połączenia.

Q_ASSERT( connect( centralWidget->dataBase(), SIGNAL(errorReported(QString)),
            this,SLOT(showErr(QString)) ) );

jak widać powyżej unikam też zewnętrznego stosowania pól klasy, poprzez centralWidget->dataBase().

0

Hej,

I tak też zrobiłem ja radzisz, tyle że:

QObject::connect(centralWidget->itsql,SIGNAL(errorReported(QString)),this,SLOT(showErr(QString)));

zamiast

QObject::connect(centralWidget->itsql(),SIGNAL(errorReported(QString)),this,SLOT(showErr(QString)));

bo wtedy kompilator skarży się że:

error: '((MainWindow*)this)->MainWindow::centralWidget->StackedWidget::itsql' cannot be used as a function

ale działa i jest git.
pozdrawiam
Marek

0

Wydawało mi się oczywiste, że akcesor trzeba zaimplementować!

1 użytkowników online, w tym zalogowanych: 0, gości: 1