Frage zu Signalen und Slots -> Einem Dialog einen Wert übergeben



  • Hiho,
    bin noch recht neu in Qt.
    Ich versuche ein Sudoku mit UI zu programmieren.
    Hab ich mich n bisschen in der Qt Dokumentation umgeschaut und bin da dann auf Signale und Slots gestoßen.
    Mein bisheriges (noch nicht schön gelayoutetes) Sudokufeld besteht aus QPushButtons

    Der Code meines MainFensters, mainwindow.cpp:

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include "fielddialog.h"
    #include <QGridLayout>
    
    //testen
    #include <iostream>
    using std::cout;
    using std::endl;
    
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
        QGridLayout *grid=new QGridLayout();
        grid->setSpacing(0);
        centralWidget()->setLayout(grid);
    
        for(int i=0;i<9;i++){
            for(int j=0;j<9;j++){
                buttonGrid[i][j]=new QPushButton();
                buttonGrid[i][j]->setFixedSize(30,30);
                grid->addWidget(buttonGrid[i][j],i,j);
    
                //signalzeuch
                connect(buttonGrid[i][j],SIGNAL(clicked()),this,SLOT(openDialog()));
            }
        }
    }
    
    void MainWindow::openDialog(){
        FieldDialog * fd=new FieldDialog(this);
        fd->show();
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    

    mainwindow.h:

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include <QMainWindow>
    #include <QPushbutton>
    
    namespace Ui {
    class MainWindow;
    }
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        explicit MainWindow(QWidget *parent = 0);
        ~MainWindow();
    
    private:
        Ui::MainWindow *ui;
    
        QPushButton *buttonGrid[9][9];
    
    private slots:
        void openDialog();
    };
    
    #endif // MAINWINDOW_H
    

    Mein Problem liegt beim Verbinden bzw Aufrufen des Dialogs.
    In der Zeile

    connect(buttonGrid[i][j],SIGNAL(clicked()),this,SLOT(openDialog()));
    

    würde ich gerne dem "openDialog()"-Aufruf noch den Index des jeweiligen Buttons übergeben, damit ich auf den Wert der im Button steht zugreifen kann.
    Wenn ich der Deklaration und Definition der Funktion "openDialog()" aber noch Eingabeparameter a la "openDialog(int a, int b)" spendiere, bekomme ich immer die Fehlermeldung: "No such slot in MainWindow::openDialog(i,j)"

    Liege ich da mit den Signal und Slots überhaupt richtig?? Oder müsste ich das von vorne herein schon anders regeln, wie z.b. mit mouseevents???
    Bin in C++ noch nicht so fit, kenne mich mit Java aus

    mfg



  • Stichwort QSignalMapper.



  • Mechanics schrieb:

    Stichwort QSignalMapper.

    Danke für den Hinweis, das bringt mich schon mal weiter.

    Aber eine Frage hätt ich noch: Aus Java kenn ich das Prinzip der Eventlistener, mit dem man Tastatur-, Mausevents etc abfangen und weiterverwenden kann.
    Ist QSignalMapper hierzu das passende Äquivalent in Qt, oder gibt es ncoh andere Möglichkeiten?? Ich frag nur, um meinen Überblick über zu vergrößeren



  • Das Equivalent eines EventListeners (Observer) in Qt ist der Signal/Slot Mechanismus. QSignalMapper ist nur eine Hilfsklasse, wenn du in einem Slot (=EventListener) auf die gleichen Events von vielen verschiedenen Quellen reagieren willst und dabei die Quellen unterscheiden.



  • Oke, langsam fügt sich das Qt Bild in meinem Kopf zu einem großen ganzen zusammen 🙂

    Es hat sich auch schon eine neue Frage aufgetan:
    Wie kann ich das Observer Prinzip auf eine Qt Klasse und eine Nicht Qt Klasse (Qt Klasse beobachtet Nicht Qt Klasse) anwenden?
    Ich seh da bisher 2 Möglichkeiten
    1. Die Nicht Qt Klasse entsprechend erben lassen, sodass ich dort Signals verwenden kann
    2. Mir eigene Observer Klassen/Interfaces erstellen und beide Klassen (Qt und Nicht Qt) davon erben lassen.

    Ersteres kommt mir ein wenig gepfuscht vor und erscheint mir unsauber. Letzteres würde für mich doch einiges an Aufwand bedeuten, da meine C++ Skills noch nicht so überragend sind.
    Bietet da Qt eigene Möglichkeiten?



  • Die Frage hat ja jetzt weniger mit Qt an sich zu tun, das ist eher eine allgemeine Frage, wie du das lösen willst. Beide Möglichkeiten wären ok.
    Du kannst deine Klasse von QObject ableiten und Signale definieren. Wenn die Klasse eh nur im Qt Umfeld verwendet wird, spricht gar nichts dagegen, das ist nicht gepfuscht. Wenn du die Klasse möglichst frei von irgendwelchen Abhängigkeiten halten willst, dann solltest du natürlich nicht von QObject ableiten.
    Einen Observer zu schreiben ist auch nicht schwierig, auf jeden Fall eine Möglichkeit.
    Du könntest auch boost::signals(2) verwenden. Ist aber auch eine Abhängigkeit, und wenn du eh im Qt Umfeld unterwegs bin, ist es nicht unbedingt sinnvoll, viele Unterschiedliche Ansätze zu mischen.



  • Danke nochmal für deine Antwort.
    Dann werd ich mal versuchen meine Nicht Qt Klasse von QObject erben zu lassen. Das erscheint mir grade am Einfachsten

    Edit:
    Ich stell mich hier grad etwas doof an und schaffs nich meine eigene Klasse von QObject erben zu lassen

    Kopf meiner Sudoku.h

    #ifndef SUDOKU_H
    #define SUDOKU_H
    
    #include <QObject>
    
    class Sudoku : public QObject
    {
        Q_OBJECT
    
        private:
    
        public:
            Sudoku(QObject *parent = 0);
            ~Sudoku();
    ...
    

    Konstruktor meiner Sudoku.c:

    Sudoku::Sudoku(QObject *parent)
        : QObject(parent), counter(0), round(0), field(), startfield(){
        //initField();
    }
    

    Bekomme 3 mal die Meldung "LNK2001: Nicht aufgelöstes externes Symbol ""public: virtual void..." und einmal "LNK2019: Verweis auf nicht aufgelöstes Symbol "" public virtual __thiscall..."

    Hört sich für mich so an als müsste ich noch virtuelle Funktionen von QObject implementieren. Kann aus den Fehlermeldung aber nciht rauslesen welche und wenn ich danach google find ich auch nicht was da noch zu implementieren wär.



  • Die Sache hat sich erledigt.
    Hab vergessen den Destruktor zu implementieren 😃


Anmelden zum Antworten