Problem z #include w Qt

Problem z #include w Qt
CO
  • Rejestracja:prawie 8 lat
  • Ostatnio:ponad 6 lat
  • Postów:31
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"

Kopiuj
#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"

Kopiuj
#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

edytowany 1x, ostatnio: ciekaryniczny_otwieracz
kq
Moderator C/C++
  • Rejestracja:ponad 11 lat
  • Ostatnio:dzień
  • Lokalizacja:Szczecin
1

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

Kopiuj
#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...


edytowany 1x, ostatnio: kq
Prav
Nic, tylko się doczekiwać aż C++ zaprzestanie używania archaicznego systemu z lat 70 i przejdzie na moduły w teorii msvc i clang mają już implementacje modułów. #soon :)
kq
Tja, ostatnio jak sprawdzałem (ok, dawno), to te implementacje były wzajemnie niekompatybilne :​P Przez to zresztą modułów w 17 nie ma.
Prav
Pozostaje tylko liczyć, że w ostatecznej formie nie będą wymagały przeczytania książki do poprawnego używania.
kq
Dobre sobie :​{
koszalek-opalek
  • Rejestracja:około 9 lat
  • Ostatnio:około 2 lata
0

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

CZ
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 2 lata
  • Postów:231
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ę.

gośćabc
  • Rejestracja:prawie 11 lat
  • Ostatnio:ponad 3 lata
  • Lokalizacja:Szczecin
  • Postów:500
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.

CO
  • Rejestracja:prawie 8 lat
  • Ostatnio:ponad 6 lat
  • Postów:31
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.

koszalek-opalek
  • Rejestracja:około 9 lat
  • Ostatnio:około 2 lata
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...

CZ
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 2 lata
  • Postów:231
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.

edytowany 2x, ostatnio: czaffik
CO
Widget powitalny służy do wyboru planszy kalibracyjnej potem wywołuje mainwindow z odpowiednim parametrem który określa rodzaj planszy i inne funkcje powiązane z tym wyborem
CZ
tak, ale sama nazwa "mainwindow" oznacza że to okno główne, więc raczej twoje okno powitalne powinno być mainwindow a reszta jakimś widgetem wywoływanym pod jego kontrolą, niefortunnie dobrałeś nazwy, niefortunnie to rozplanowałeś, np pojawia się okno powitalne a mainwindow jest ukryte, te dwa widgety komunikują się za pomocą własnych sygnałów, no musisz trochę doczytać o qt.
CO
Na początku pojawia się okno powitalne a potem po wyborze planszy dynamicznie tworze obiekt mainwindow i tam już się dzieje właściwy program.... Problem polega na tym że nie mogę powrócić do ekranu powitalnego przyciskiem BACK i zwolnić zajętą przez mainwindow pamieć. Teraz mam coś takiego : connect(mainWindow, SIGNAL(mainWindow->on_backToMenu_clicked()), this, SLOT(this->back())); i to mi nie chce działać bo wyświetla się komunikat : QObject::connect: No such signal MainWindow::mainWindow->on_backToMenu_clicked() nie wiem czemu
CZ
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 2 lata
  • Postów:231
0

To powinno wyglądać chyba tak:

Kopiuj
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).

CO
  • Rejestracja:prawie 8 lat
  • Ostatnio:ponad 6 lat
  • Postów:31
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...

CO
  • Rejestracja:prawie 8 lat
  • Ostatnio:ponad 6 lat
  • Postów:31
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

Kopiuj

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";

}
Kopiuj

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 :)

edytowany 1x, ostatnio: ciekaryniczny_otwieracz
CZ
i tak pewnie ktoś przekombinuje i będzie trzeba gadać że można tworzyć własne sygnały albo coś innego xD
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)