Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Qt window closes abruptally after changing dropdown option C++

Qt window closes abruptally after changing dropdown option C++

Scheduled Pinned Locked Moved Unsolved General and Desktop
4 Posts 3 Posters 71 Views 2 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • W Offline
    W Offline
    weverson
    wrote last edited by
    #1

    Hi, I am new in Gt and am using it to learn and improve my skills in c++. I am develping a GUI to show database information. The window opens fine, but as soon as I try to change 'Source' on the dropdown menu, the window abruptally closes without showing errors.

    What I've tried:
    Add:

    blocksignals(true)
    code
    blocksignals(false)
    

    On the QObject::connect (connect signals),
    replaced:

    QObject::connect(sourceCombo, &QComboBox::currentTextChanged, window, updateCategories); 
    QObject::connect(categoryCombo, &QComboBox::currentTextChanged, window, updateSubjects);  
    QObject::connect(subjectCombo, &QComboBox::currentTextChanged, window, updateDetails);
    

    For:

    QObject::connect(sourceCombo, &QComboBox::currentTextChanged, sourceCombo, updateCategories); 
    QObject::connect(categoryCombo, &QComboBox::currentTextChanged, sourceCombo, updateSubjects);  
    QObject::connect(subjectCombo, &QComboBox::currentTextChanged, sourceCombo, updateDetails);
    

    dbwindow.h:

    #include <QWidget>      // Qt base class for all UI objects
    #include <QComboBox>    // Qt widget for drop-down lists
    #include <QVBoxLayout>  // Qt layout for vertical arrangement of widgets
    #include <QTextEdit>    // Qt for text edit field
    #include <QStringList>  // Qt container for lists of strings
    #include <QString>      // Qt string class
    #include <QLabel>       // Qt widget for text labels
    #include <QSet>         // Qt container for text labels
    #include <vector>       // Standard C++ vector container
    #include <iostream>
    
    
    struct Record {
        QString source;     // Source name
        QString category;   // Category name
        QString subject;    // Subject name
        QString details;    // Details text
    };
    
    // Function to create and show the main window with dependent dropdowns
    inline QWidget* createDbWindow(const std::vector<Record>& records) {
    
    
        try {
    
            QWidget* window = new QWidget;                  // Create the main window widget
            QVBoxLayout* layout = new QVBoxLayout(window);  // Create a vertical layout and set it for the window
    
            // Create dropdowns and text field
            QComboBox* sourceCombo = new QComboBox(window);         // Dropdown for source
            QComboBox* categoryCombo = new QComboBox(window);       // Dropdown for categories
            QComboBox* subjectCombo = new QComboBox(window);        // Dropdown for subjects
            QTextEdit* detailsEdit = new QTextEdit(window);         // Multi-line text field for details
            detailsEdit->setReadOnly(true);                         // Make details field read-only
            detailsEdit->setLineWrapMode(QTextEdit::WidgetWidth);   // Enable line wrapping to fit the widget width
    
            // Collect unique source from records
            QSet<QString> sources;               // Set to store unique brands
            for (const auto& rec : records) {
                sources.insert(rec.source);     // Insert brand into set
            }
    
            sourceCombo->addItems(QStringList(sources.begin(), sources.end()));     // Add sources to dropdown
            layout->addWidget(new QLabel("Source:", window));    // Add label for source
            layout->addWidget(sourceCombo);                     // Add source dropdown to layout
            layout->addWidget(new QLabel("Category:", window)); // Add label for category
            layout->addWidget(categoryCombo);                   // Add category dropdown to layout
            layout->addWidget(new QLabel("Subject:", window));  // Add label for subject
            layout->addWidget(subjectCombo);                    // Add subject dropdown to layout
            layout->addWidget(new QLabel("Details:", window));  // Add label for details
            layout->addWidget(detailsEdit);                     // Add details text field to layout
    
    
            // Helper function to update details field based on selected subject
            auto updateDetails = [&]() {
                QString selectedSource = sourceCombo->currentText();        // Get selected source
                QString selectedCategory = categoryCombo->currentText();    // Get selected category
                QString selectedSubject = subjectCombo->currentText();      // Get selected subject
                for (const auto& rec : records) {
                    if (rec.source == selectedSource && rec.category == selectedCategory && rec.subject == selectedSubject) {
                        detailsEdit->setText(rec.details);              // Set details text for matching record
                        return;
                    }
                }
                detailsEdit->clear();                               // Clear details if no match found
            };
    
            // Helper function to update subject options based on selected category
            auto updateSubjects = [&]() {
                subjectCombo->blockSignals(true);
                subjectCombo->clear();               // Clear subject dropdown
                QSet<QString> subjects;              // Set to store unique subjects
                QString selectedSource = sourceCombo->currentText();    // Get selected source
                QString selectedCategory = categoryCombo->currentText(); // Get selected category
                for (const auto& rec : records) {
                    if (rec.source == selectedSource && rec.category == selectedCategory)   // If record matches brand and category
                        subjects.insert(rec.subject);                   // Insert subject into set
                }
                subjectCombo->addItems(QStringList(subjects.begin(), subjects.end()));  // Add subjects to dropdown
                subjectCombo->blockSignals(false);  // Re-enable signals
                
                updateDetails();
            };
    
            // Helper function to update category options based on selected source
            auto updateCategories = [&] () {
                categoryCombo->blockSignals(true);
                categoryCombo->clear();                                // Clear category dropdown
                QSet<QString> categories;                              // Set to store unique categories
                QString selectedSource = sourceCombo->currentText();   // Get selected source
                for (const auto& rec: records) {
                    if (rec.source == selectedSource)                  // If record matches selected brand
                        categories.insert(rec.category);               // Insert category into set 
                }
                categoryCombo->addItems(QStringList(categories.begin(), categories.end()));  // Add categories to dropdown
                categoryCombo->blockSignals(false);  // Re-enable signals
                
                updateSubjects();
            };
    
            
            // Connect signals to update dropdowns and details when selection changes
            QObject::connect(sourceCombo, &QComboBox::currentTextChanged, window, updateCategories);        // Update categories when source changes
            QObject::connect(categoryCombo, &QComboBox::currentTextChanged, window, updateSubjects);        // Update subjects when category changes
            QObject::connect(subjectCombo, &QComboBox::currentTextChanged, window, updateDetails);          // Update details when subject changes
    
            // Initialize dropdowns with first source selected
            if (sourceCombo->count() > 0) {
                sourceCombo->setCurrentIndex(0);    // Select first source
                updateCategories();                 // Update categories for initial source
            }
    
            window->setLayout(layout);                  // Set the layout for the window
            window->setWindowTitle("Database Viewer");  // Set the window title
            window->resize(755, 378);                   // Set window to 20 x 10
            window->show();                             // Show the window on the screen
            return window;
    
        } catch (const std::exception& e) {
            std::cerr << e.what() << "\n";
        }
        
    }
    
    
    #endif  //!DBWINDOW_H
    

    dbacess.h:

    #ifndef DBCONNECTION_WINDOW_H
    #define DBCONNECTION_WINDOW_H
    
    #include <pqxx/pqxx>
    #include <iostream>
    #include <vector>
    #include <string>
    
    // Structure to store each database record
    struct DataEntry {
        // Fields for 'source', 'category', 'subject' and 'details' column 
        std::string source;
        std::string category;
        std::string subject;
        std::string details;
    };
    
    // Function to open a connection to the PostgreSQL database
    inline pqxx::connection openDatabase() {
        // Connection string with db parameters (host, port, dbname, user, password)
        std::string conn_str = "host=localhost port=5432 dbname=prescreen_diag_data_api user=postgres password=shakey-10";
        return pqxx::connection(conn_str);  // Return a new pqxx connection object
    }
    
    // Function to fetch data from db
    inline std::vector<DataEntry> fetchData(pqxx::connection& conn) {
        std::vector<DataEntry> data;    // Vector to store all fetched records
        try {
            pqxx::work txn(conn);   // Start a transaction on the connection
            // Execute teh SQL query to select the desired columns
            pqxx::result res = txn.exec("SELECT source, category, subject, details FROM diagnostic_assistance_db;");
            
            for (const auto& row : res) {
                // Create a new DataEntry struct
                DataEntry entry;
                // Assign each column value to the struct fields
                entry.source = row["source"].c_str();
                entry.category = row["category"].c_str();
                entry.subject = row["subject"].c_str();
                entry.details = row["details"].c_str();
                data.push_back(entry);  // Add the entry to the vector
            }
        } catch (const std::exception& e) {
            std::cerr << "Error: " << e.what() << std::endl;
        }
    
        return data;    // Return the vector with all records
    }
    
    #endif  //!DBCONNECTION_WINDOW_H
    
    

    main.cpp

    #include <QApplication>         // Qt application class
    #include <QStringList>          // For QStringList
    #include <pqxx/pqxx>
    #include "dbwindow.h"           // For createDbWindow function
    #include "dbaccess.h"           // For database access functions
    
    
    int main(int argc, char *argv[]) {
        try {
            QApplication app(argc, argv);   // Create the Qt application
    
            pqxx::connection conn = openDatabase();   // Open database connection
        
            std::vector<DataEntry> data = fetchData(conn);    // Fetch all data from the database
        
            std::vector<Record> records;      // Vector to store all records for the GUI
    
            for (const auto& entry : data) {
                // Convert each DataEntry from the database to a Record for GUI
                records.push_back({
                    QString::fromStdString(entry.source),       // Set source field
                    QString::fromStdString(entry.category),     // Set category field    
                    QString::fromStdString(entry.subject),      // Set subject field
                    QString::fromStdString(entry.details)       // Set details field
                });
            }
    
            QWidget* window = createDbWindow(records);  // Create and show the window with dependent dropdowns
        
            return app.exec();      // Start the Qt event loop
        } catch(const std::exception& e) {
            std::cerr << e.what() << "\n";
        }
    
        return 1;
    
    } 
    
    
    1 Reply Last reply
    0
    • Axel SpoerlA Offline
      Axel SpoerlA Offline
      Axel Spoerl
      Moderators
      wrote last edited by
      #2

      Hi @weverson and welcome to the Qt forum!
      Are you running this in a debugger?
      Maybe add debug statements in the updateSomething() lambdas.
      The debugger of Qt Creator shows you where the program aborts (if it does).
      My guess is that you still end up in an endless recursion and eventually the executable runs out of memory.
      But that's hard to say, because the code is rather busy.
      I'd recommend to drop all the try()ing.

      Software Engineer
      The Qt Company, Oslo

      1 Reply Last reply
      0
      • W Offline
        W Offline
        weverson
        wrote last edited by
        #3

        Hi Axel,
        Thank you very much for your help. I forgot to mention some important details.
        I am using VS code, so the debbuger is MSVC.
        Also, I am executing the code on cmd after creating the build files through Cmake.

        JonBJ 1 Reply Last reply
        0
        • W weverson

          Hi Axel,
          Thank you very much for your help. I forgot to mention some important details.
          I am using VS code, so the debbuger is MSVC.
          Also, I am executing the code on cmd after creating the build files through Cmake.

          JonBJ Offline
          JonBJ Offline
          JonB
          wrote last edited by JonB
          #4

          @weverson
          So you need to run/step through your code under the MSVC debugger. People don't know where in your hundreds of lines of code the issue lies. Not sure what your "Also, I am executing the code on cmd after creating the build files through Cmake." means, but as stated you need to run this under the debugger, not free running in some console window outside of debugger. Learning to debug with whatever debugger you use is the single most useful coding skill you will ever obtain, so it's worth spending some time to get familiar with it.

          1 Reply Last reply
          2

          • Login

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • Users
          • Groups
          • Search
          • Get Qt Extensions
          • Unsolved