c++qtqmdiarea

How to display QLabel inside qwidget from active QMdiAreaSubwindow in statusbar?


I have a app that uses QMdiArea.

I want the text in the statusbar to update when another QMdiAreaSubwindow becomes active.

So the text in the statusbar should become the same as the Qlabel text inside the QWidget which is been displayed inside the QMdiAreaSubwindow.

But i can't find a way to do this. Right now the statusbar only shows the text from latest created QMdiAreaSubwindow. But it won't update the text in the statusbar(With qlabel from the qwidget) when another QMdiAreaSubwindow is selected.

As you can see in the screenshot, the text in the statusbar keeps saying "test2", but I want it to change to "text" from the active QMdiAreaSubwindow.

enter image description here

mainwindow.h:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QMdiArea>
#include <QMdiSubWindow>
#include <newwindow.h>

namespace Ui {
    class MainWindow;
}

class MainWindow : public QMainWindow 
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

    void NewSubWindow(QString name);

    void createStatusBar(QString name);

private slots:

    void on_actionNew_triggered();

    void on_mdiArea_subWindowActivated(QMdiSubWindow *arg1);

private:
    Ui::MainWindow *ui;

    NewWindow *nDialog;
};

#endif // MAINWINDOW_H

mainwindow.cpp:

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "mdisubwidget.h"
#include "newwindow.h"
#include <QDebug>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    nDialog = new NewWindow();
    connect(nDialog,&NewWindow::transmit,this,&MainWindow::NewSubWindow);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::NewSubWindow(QString name) {

    // new Widget to add to mdiareasubwindow
    mdisubwidget *mdiwidget = new mdisubwidget();
    mdiwidget->addName(name);
    mdiwidget->setWindowTitle(name);

    // Create new mdiAreaSubWindow
    ui->mdiArea->addSubWindow(mdiwidget);

    // Show mdiArea
    mdiwidget->show();
}

void MainWindow::on_actionNew_triggered()
{
    nDialog->show();
}

void MainWindow::on_mdiArea_subWindowActivated(QMdiSubWindow *arg1)
{
    mdisubwidget *mdiwidget = new mdisubwidget(arg1->widget());
    qDebug() << "name" << mdiwidget->returnName();
    createStatusBar(mdiwidget->returnName());
}

void MainWindow::createStatusBar(QString name)
{
    statusBar()->showMessage("chart = "+name);
}

mdisubwidget.h

#ifndef MDISUBWIDGET_H
#define MDISUBWIDGET_H

#include <QWidget>

namespace Ui {
    class mdisubwidget;
}

class mdisubwidget : public QWidget
{
    Q_OBJECT

public:
    explicit mdisubwidget(QWidget *parent = nullptr);
    void addName(QString name);
    QString returnName();
    ~mdisubwidget();

private:
    Ui::mdisubwidget *ui;
};

#endif // MDISUBWIDGET_H

mdisubwidget.cpp

#include "mdisubwidget.h"
#include "ui_mdisubwidget.h"
#include "mainwindow.h"

QString currentName;

mdisubwidget::mdisubwidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::mdisubwidget)
{
    ui->setupUi(this);
}

void mdisubwidget::addName(QString name) {
    ui->label_2->setText(name);
    currentName = name;
}

QString mdisubwidget::returnName() {

    return currentName;
}

mdisubwidget::~mdisubwidget()
{
    delete ui;
}

NewWindow.h:

#ifndef NEWWINDOW_H
#define NEWWINDOW_H

#include <QWidget>

namespace Ui {
    class NewWindow;
}

class NewWindow : public QWidget
{
    Q_OBJECT

public:
    explicit NewWindow(QWidget *parent = nullptr);
    ~NewWindow();

signals:
    void transmit(QString name);

private slots:
    void on_pushButton_clicked();

private:
    Ui::NewWindow *ui;
};

#endif // NEWWINDOW_H

NewWindow.cpp:

#include "newwindow.h"
#include "ui_newwindow.h"
#include "mainwindow.h"

NewWindow::NewWindow(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::NewWindow)
{
    ui->setupUi(this);
}

NewWindow::~NewWindow()
{
    delete ui;
}

void NewWindow::on_pushButton_clicked()
{
    QString name = ui->lineEdit->text();
    emit transmit(name);
}

Solution

  • ok you're using Qt Designer to connect the signal of subWindowActivated to the slot of on_mdiArea_subWindowActivated of your MainWindow, double check with qDebug in your on_mdiArea_subWindowActivated function if the name of your selected sub window appears on the console as you tried to change your current mdi sub window so follow my code snippets to find your way:

    connect(ui->mdiArea, &QMdiArea::subWindowActivated, this, &DesignerWindow::activeViewChanged);
    

    activeViewChanged():

    void DesignerWindow::activeViewChanged(QMdiSubWindow *activeSubWindow)
    {
        // checks if there is no active sub window defined or the number of subwindows
        // are zero then return
        if (!activeSubWindow)
            return;
        if (ui->mdiArea->subWindowList().count() == 0) {
            ui->itemsTree->clear();
            return;
        }
    
        // defines the current Midi, View and graphical Scene when current sub window changes
        currentMidi = reinterpret_cast<MidiWindow*>(activeSubWindow->widget());
        currentView = reinterpret_cast<HMIView*>(currentMidi->internalView());
        currentScene = reinterpret_cast<HMIScene*>(currentMidi->internalScene());
    
        ItemsToolBar::ItemType currentType = currentScene->itemType();
        itemsToolBar->selectItemType(currentType);
    
        // updates the widgets and labels in status bar related to current midi sub window
        updateScale(currentView->zoomFactor() * 100);
        updateSelected();
        updateItemsTree();
        updateRendererType();
    }
    

    for example for updating the label in the status bar that holds the zooming factor of the current mdiSubWindow I wrote the updateScale procedure as below:

    void DesignerWindow::updateScale(double _scale)
    {
        scale = static_cast<int>(_scale);
        scaleLbl->setText(QString("%1%").arg(scale));
    }
    

    and finally I've noticed that your creating a label in status bar every time that you try to update the text in it, please avoid such a procedure and create a QLabel object and add it to your status bar as a permanent widget like below:

    scaleLbl = new QLabel(this);
    scaleLbl->setFrameStyle(QFrame::Sunken | QFrame::Panel);
    scaleLbl->setMinimumWidth(50);
    statusBar()->addPermanentWidget(scaleLbl);