Problem z #include w Qt

0

Mam problem z #include w Qt, chodzi o to że chcę zrobić sygnał i slot pomiędzy dwoma klasami które znajdują się oddzielnych plikach. No i potrzebuje w każdej z tych dwóch poniższych klas stworzyć instancję obiektu MainWindow w welcome.h oraz Welcome w mainwindow.h żeby potem móc się odwołać poprzez nią za pomocą funkcji connect(). Kompilator zgłasza szereg błędów które są bezsensowne typu że brakuje * albo ' .

Szukałem w internecie i znalazłem tylko takie coś: https://stackoverflow.com/questions/36927878/c2143-syntax-error-missing-before-c4430-missing-type-specifier-in

No ale to nie rozwiązuje mojego problemu...

"welcome.h"

#ifndef WELCOME_H
#define WELCOME_H

#include "mainwindow.h"
#include <QDialog>

namespace Ui
{
    class Welcome;
    static int MAX_CAMERA_NUMBER; // zmienna statyczna na ilość dostępnych kamer
}

class Welcome : public QDialog
{
    Q_OBJECT

public:

    explicit Welcome(QWidget *parent = 0);

    ~Welcome();

private slots:

   void on_chessBoardButton_clicked(); // reakcja na wciśnięcie odpowiedniej planszy

   void on_chArucoBoardButton_clicked();

   void on_circlesBoardButton_clicked();

private:

    Ui::Welcome *ui;

    MainWindow *mainWindow;  //TUTAJ JEST PROBLEM

public slots:

    void on_backButton_clicked();
};

#endif // WELCOME_H



"mainwindow.h"

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QTimer>
#include <QDialog>

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

#include "welcome.h"

namespace Ui
{

    class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT   // makro Qt, wywoływane przez Qt tłumaczy wstawki Qt na kod w stylu C++

public:
    explicit MainWindow (unsigned char CalibType, QWidget *parent = 0);
    ~MainWindow();

private:

    Welcome *previousWelcome;    // TUTAJ JEST PROBLEM

    cv::VideoCapture capWebcam; // obiekt kamery do wyswietlania

    void calibrateChessboard();

    void open_Camera(int); // f. do otwierania danej kamery

    Ui::MainWindow *ui;

    cv::Mat matOriginal;   // Obraz Mat z w stylu biblioteki OpenCV

    QImage qimgOriginal;            // Obraz w stylu biblioteki Qt

    QTimer* tmrTimer;       // timer

    int camera_index = 0;  // aktualnie włączona kamera

public slots:
    void processFrameAndUpdateGUI();  // // f. aktualizująca klatkę przechwyconą z kamery oraz GUI

private slots:

    void on_tryAgain_clicked();

    void on_nextButton_clicked();

    void on_previousButton_clicked();

    void on_back_clicked();
};

#endif // MAINWINDOW_H

1

Nie możesz tak inkludować plików nawzajem. Zamiast tego, użyj forward deklaracji. Np. w pliku welcome.h zadeklaruj klasę MainWindow:

#ifndef WELCOME_H
#define WELCOME_H
 
#include <QDialog>
 
namespace Ui
{
    class Welcome;
    static int MAX_CAMERA_NUMBER; // zmienna statyczna na ilość dostępnych kamer
}

class MainWindow; // o tak
 
class Welcome : public QDialog
{
    Q_OBJECT
// ...

Tak w ogóle, staraj się unikać inkludowania zbędnych plików - szczególnie w nagłówkach. Tutaj jest fajny opis kiedy jest to konieczne, a kiedy nie: https://jonjagger.blogspot.com/2013/04/the-include-test.html

Nic, tylko się doczekiwać aż C++ zaprzestanie używania archaicznego systemu z lat 70 i przejdzie na moduły...

0

A jakiego rodzaju to jest problem? Co pisze kompilator? Bo (bardzo z grubsza) nie wygląda to jakoś źle...

0

"No i potrzebuje w każdej z tych dwóch poniższych klas stworzyć instancję obiektu MainWindow w welcome.h oraz Welcome w mainwindow.h żeby potem móc się odwołać poprzez nią za pomocą funkcji connect()" - a nie wystarczy potworzyć connectów w mainwindow?

Jeśli chcesz connecty wykorzystać w welcome a ci nie działają to nie zapominaj że do każdej klasy trzeba dołączać Q_OBJECT.

Takie zapętlone includowanie wygląda jakbyś gdzieś coś pokomplikował ponad miarę.

0

MainWindow może mieć tylko jedną instancję, w konstruktorze okna głównego połącz signal slotem to co potrzebujesz, w pliku cpp możesz dodać include do wybranych obiektów.

0

Sytuacja wygląda tak że mam ekran powitalny swojego programu i jak użytkownik kliknie przycisk to wywołuje się funkcja która ukrywa ekran powitalny i dynamicznie alokuje pamięć na okno główne programu. No i potem chce z tego okna głównego móc wrócić do ekranu powitalnego klikając przycisk "back", a potem oczywiście zwolnić dynamicznie pamięć zajmowaną przez okno główne.

Niestety nie wiem jak odwołać się do tego okna rodzica ( okno powitalne) w konstruktorze klasy pochodnej ( ekran główny)poprzez funcję connect.

0
kq napisał(a):

Nic, tylko się doczekiwać aż C++ zaprzestanie używania archaicznego systemu z lat 70 i przejdzie na moduły...

Archaiczny to był już w latach 70 -- bo chyba np. Ada od początku (czyli od lat 70) miała moduły...

0
  1. Widget powitalny i widget "głównego okna" mogą pracować pod kontrolą trzeciego widgetu który nie jest pokazywany na ekranie;
  2. Widget powitalny albo widget głównego okna ustawiasz jako wdiget główny, drugi pracuje pod kontrolą pierwszego, przełączanie polega na ukrywaniu widgetu głównego i "kreacji i anihilacji" widgetu drugiego.
    Ekran powitalny utworzyłbym raczej jako ten wywoływany przez ekran główny bo jak mniemam jego głównym zadaniem będzie wyświetlenie napisu w stylu: "witaj urzyszkodniku, już psujesz mój wspaniały program".

Wciśnięcie przycisku back może nie tylko odpalić slot ale też wyemitować inny sygnał, który zostanie przechwycony przez okno główne.

Wciskasz back na oknie pochodnym, to powoduje wyemitowanie sygnału przez okno pochodne (poprzez funkcję connect w oknie pochodnym), a ten sygnał zostaje przechwycony przez okno główne które odpala slot i tam niszczy okno pochodne itp.

Poczytaj o własnych sygnałach.

0

To powinno wyglądać chyba tak:

connect(mainWindow, SIGNAL(on_backToMenu_clicked()), this, SLOT(this->back()));

poczytaj o sygnałach i slotach: http://doc.qt.io/archives/qt-4.8/signalsandslots.html

Nie rozumiem czemu jakiś tam se widget zarządza mainwindowem, już zmień mainwindow na jakiś inny widget, mainwindow nie jest wymagany (no chyba że ten jakiś tam widget po prostu nazwałeś mainwindow).

0

No właśnie nie działa bo on_backToMenu_clicked() jest SLOTem na sygnał wysłany przez wciśnięty przycisk BACK w klasie mainwindow. A gdy chce to połączyć connectem w welcome to pisze że funkcja oczekuje sygnału...

0

Po kilku dniach walki znalazłem rozwiązanie swojego problemu :D

Gdy użytkownik wybierze którąś z plansz dostępnych na ekranie powitalnym wywołuje się funkcja która dynamicznie alokuje pamięć na właśnie tworzone okno główne programu.
Gdy tylko utworze nowy obiekt odraz łącze go z ekranem powitalnym. Konieczne było utworzenie w tym obiekcie własnego sygnału signalBackToMenu() który zostanie emitowany gdy użytkownik kliknie przycisk BACK na ekranie głównym chcąc wrócić do ekranu z wyborem plansz. A gdy to nastąpi wywołuje się funkcja back() w welcome i zwalniamy pamieć zajętą wcześniej przez mainWindow


void Welcome::on_chessBoardButton_clicked()
{
 
    mainWindow = new MainWindow(0,this);
    this->hide()
    mainWindow->show();
       
    qDebug()<<"Stworzono i pokazano mainWindow";
      
    connect(mainWindow, SIGNAL(signalBackToMenu()), this, SLOT(back()));
    
    qDebug()<<"Polonczono nowy powstaly obiekt z oknem powitalnym";

}

void Welcome::back() // reakcja na powrót do menu z wyborem plansz
{
    mainWindow->close();
    this->show();
    delete mainWindow;
    qDebug()<<"Zwolnienie pamieci";

}

Główny problem jaki popełniłem to brak wiedzy na temat działania slotów i sygnałów, chciałem aby funkcja void on_backToMenu_clicked(); która jest obsługuje przycisk była slotem i sygnałem a Qt na to nie pozwoliło. No więc powyższa funkcja wywołuje sygnał void signalBackToMenu(); który już da się połączyć connectem. Swoją drogą nie wiedziałem że istnieje możliwość stworzenia własnego sygnału przy użyciu słowa kluczowego signals

Pisze takie obszerne wyjaśnienie bo może komuś tutaj to się przyda bo będzie miał podobny problem :)

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