Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Cannot interact with my ui widgets from a self defined slots



  • Hello,

    I am making a widget Application where I scan for Bluetooth Low Energy devices. When a device discovered a Slot is called (deviceDiscovered) and I want in this slot to add the device.name to a Combobox. the slot and the Signal are not in the same class:

    /*BluetoothModel.h*/
    
    #ifndef BLUETOOTHMODEL_H
    #define BLUETOOTHMODEL_H
    #include <QBluetoothDeviceDiscoveryAgent>
    #include <BluetoothController.h>
    #include <QObject>
    
    class BluetoothModel : public QObject
    {
        Q_OBJECT
    
    public:
        BluetoothModel();
        void startDeviceDiscovery();
        QBluetoothDeviceDiscoveryAgent *discoveryAgent;
        BluetoothController *controller = new BluetoothController();
    };
    
    #endif // BLUETOOTHMODEL_H
    
    
    /*BluetoothModel.cpp*/
    
    #include "BluetoothModel.h"
    #include "BluetoothController.h"
    #include <QBluetoothDeviceDiscoveryAgent>
    
    BluetoothModel::BluetoothModel()
    {
    
    }
    
    void BluetoothModel::startDeviceDiscovery(){
        discoveryAgent = new QBluetoothDeviceDiscoveryAgent(this);
        discoveryAgent->setLowEnergyDiscoveryTimeout(5000);
    
        connect(discoveryAgent, &QBluetoothDeviceDiscoveryAgent::deviceDiscovered, controller, &BluetoothController::deviceDiscovered);
        discoveryAgent->start();
    }
    
    
    /*BluetoothController.cpp*/
    
    #include "ui_BluetoothView.h"
    #include "ui_PlotterView.h"
    #include "BluetoothController.h"
    #include "PlotterController.h"
    #include "BluetoothModel.h"
    
    BluetoothController::BluetoothController(QWidget *parent)
        : QMainWindow(parent)
        , ui(new Ui::BluetoothController)
    {
        ui->setupUi(this);
    }
    
    void BluetoothController::on_button_scan_clicked(){
    
        BluetoothModel *bluetoothModel = new BluetoothModel();
        bluetoothModel->startDeviceDiscovery();
    }
    
    
    void BluetoothController::deviceDiscovered(const QBluetoothDeviceInfo &device)
    {
        qDebug() << device.name();
        ui->list_devices->addItem(device.name());
    }
    
    

    Because of the qDebug() << device.name(); I know that there are devices found because in the Application output the devices are printed. However the devices are not added to my combobox (list_devices). Also when I write something like ui->list_devices->addItem("Test"); in the slot nothign happens. But when I write this in my on_button_scan_clicked() slot, then it works so it has to to with my deviceDiscovered() slot I think.

    EDIT: I tested any interaction with the list_services Combobox e.g. setEnabled(false) or true, but it does not work out of the deviceDiscovered() slot but it works out of the on_button_scan_clicked() slot.


  • Lifetime Qt Champion

    Hi,

    That's likely because your are not looking at the widget which is connected to your BluetoothModel class.

    I am guessing your a creating a BluetoothController object in you main function. However when you click on that button, your BluetoothModel creates its own BluetoothController object.

    In any case, you should cleanly separate both, there's no real reason for BluetoothModel to know anything about BluetoothController.



  • @SGaist said in Cannot interact with my ui widgets from a self defined slots:

    Hi,

    That's likely because your are not looking at the widget which is connected to your BluetoothModel class.

    I am guessing your a creating a BluetoothController object in you main function. However when you click on that button, your BluetoothModel creates its own BluetoothController object.

    In any case, you should cleanly separate both, there's no real reason for BluetoothModel to know anything about BluetoothController.

    Thank you for your answer.
    The idea of ​​mine is that I separate the actual logic (in the model class) from the UI. The communication should take place via my controller. I.e. the user clicks on the "Scan for Bluetooth devices" button in the UI, this triggers a "button clicked" slot in my Bluetooth controller class. The startDeviceDiscovery method of the "BluetoothModel" class is then called in this slot. If devices are then found, my "BluetoothController" is notified by a signal (deviceDiscovered) and this controller interacts with the UI by entering the devices in the combo box.

    7c382191-4d5e-466d-8474-c33b412f4cff-image.png

    And you are right, in fact, I create a Bluetooth controller object in my main function.

    /*main.cpp*/
    
    #include "BluetoothController.h"
    
    #include <QApplication>
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        BluetoothController w;
        w.show();
        return a.exec();
    }
    

    That means, instead of the controller object that I created in the BluetoothModel class, I would actually have to communicate with the controller object that is created in the main right? If so, how can I best implement this? And how do I get access to my controller object from the main class from the Bluetooth model class?

    A suggestion from me would be to create the BluetoothController object in the Main globally so that I can access it from the BluetoothModel class.


  • Lifetime Qt Champion

    Your BluetoothController should have a member variable of the BluetoothModel class.
    Your BluetoothModel class should provide an API that your BluetoothController can connect to and also that provides whatever data is needed.