Reputation: 568
I'm trying to use a QStackedWidget with a custom QWidget subclass. I'm working on a simple kiosk for my house that shows one of a set of widgets when the screen is tapped. This works very well IFF I create all the stacked widgets in the class that contains the QStackedWidget. When I try to add a subclassed QWidget (lots of labels, need a container), then it displays correctly, but whenever setCurrentIndex() == 0, the subclassed QWidget's showEvent() is called. This means that the first showing has two widgets visible (see image below). Because no hideEvent is ever called for my subclassed widget, it remains visible forever. Below though, you can see that hideEvent is called when the index moves away from this widget, though it immediately gets a showEvent again.
I can hide the subclassed QWidget, but it's complicated if I can't tell that the showEvent I'm getting is the one for me, so skipping it is hard.
I see a showEvent in my subclass whenever QStackedWidget's index == 0.
I have included a short example. This example is a subset but will show the issue, as I stripped out some of the extra functions that don't impact the example (MQTT, setters/getters). I'm running KUbuntu 20.04, Qt5.12.1. I have not found a bug report related to this behavior, but I am hoping I just missed it.
Edited to udpate code examples and debug output
HomeInfo.h
#ifndef HOMEINFO_H
#define HOMEINFO_H
#include <QtCore/QtCore>
#include <QtGui/QtGui>
#include <QtWidgets/QtWidgets>
#include <QtQmqtt/QtQmqtt>
#include "resizelabel.h"
#include "trafficlightwidget.h"
#include "weatherwidget.h"
class HomeInfo : public QMainWindow
{
Q_OBJECT
public:
explicit HomeInfo(QWidget *parent = nullptr);
~HomeInfo() override;
protected:
bool event(QEvent *e) override;
private:
QLabel *m_wallClockLabel;
QLabel *m_dateLabel;
QLabel *m_officeHumidityLabel;
QLabel *m_officeTempLabel;
QLabel *m_atmosphericPressureLabel;
QLabel *m_basementHumidityLabel;
QLabel *m_basementHumidityLabelName;
QLabel *m_basementTemperatureLabel;
QLabel *m_basementTemperatureLabelName;
QWidget *m_trafficLight;
QStackedWidget *m_stack;
QWidget *m_clockGridWidget;
QGridLayout *m_clockWidgetLayout;
QWidget *m_houseGridWidget;
QGridLayout *m_houseGridLayout;
WeatherWidget *m_weatherWidget;
};
#endif // HOMEINFO_H
main application HomeInfo.cpp
#include "homeinfo.h"
HomeInfo::HomeInfo(QWidget *parent) : QMainWindow(parent)
{
QPalette pal(QColor(0,0,0));
setBackgroundRole(QPalette::Window);
pal.setColor(QPalette::Window, Qt::black);
setAutoFillBackground(true);
setPalette(pal);
QFont c("Roboto-Regular", 84);
c.setBold(true);
QFont d("Roboto-Regular", 32);
QFont t("Roboto-Regular", 24);
QFont n("Roboto-Regular", 18);
m_stack = new QStackedWidget(this);
m_clockGridWidget = new QWidget();
m_clockWidgetLayout = new QGridLayout(m_clockGridWidget);
m_wallClockLabel = new QLabel();
m_wallClockLabel->setScaledContents(true);
m_wallClockLabel->setFont(c);
m_wallClockLabel->setAlignment(Qt::AlignCenter);
m_dateLabel = new QLabel();
m_dateLabel->setScaledContents(true);
m_dateLabel->setFont(d);
m_dateLabel->setAlignment(Qt::AlignCenter);
m_officeHumidityLabel = new QLabel();
m_officeHumidityLabel->setScaledContents(true);
m_officeHumidityLabel->setFont(t);
m_officeHumidityLabel->setAlignment(Qt::AlignCenter);
m_officeTempLabel = new QLabel();
m_officeTempLabel->setScaledContents(true);
m_officeTempLabel->setFont(t);
m_officeTempLabel->setAlignment(Qt::AlignCenter);
m_trafficLight = new QWidget();
m_clockWidgetLayout->setHorizontalSpacing(20);
m_clockWidgetLayout->addWidget(m_wallClockLabel, 0, 0, 3, 6);
m_clockWidgetLayout->addWidget(m_officeTempLabel, 3, 0, 1, 3);
m_clockWidgetLayout->addWidget(m_officeHumidityLabel, 3, 3, 1, 3);
m_clockWidgetLayout->addWidget(m_trafficLight, 3, 5, 3, 1);
m_clockWidgetLayout->addWidget(m_dateLabel, 4, 0, 2, 5);
m_basementHumidityLabel = new QLabel();
m_basementHumidityLabel->setScaledContents(true);
m_basementHumidityLabel->setAlignment(Qt::AlignCenter);
m_basementHumidityLabel->setFont(t);
m_basementTemperatureLabel = new QLabel();
m_basementTemperatureLabel->setScaledContents(true);
m_basementTemperatureLabel->setAlignment(Qt::AlignCenter);
m_basementTemperatureLabel->setFont(t);
m_basementTemperatureLabelName = new QLabel("Basement Temp");
m_basementTemperatureLabelName->setFont(n);
m_basementHumidityLabelName = new QLabel("Basement Humidity");
m_basementHumidityLabelName->setFont(n);
m_houseGridWidget = new QWidget();
m_houseGridLayout = new QGridLayout(m_houseGridWidget);
m_houseGridLayout->addWidget(m_basementTemperatureLabelName, 0, 0);
m_houseGridLayout->addWidget(m_basementHumidityLabelName, 0, 1);
m_houseGridLayout->addWidget(m_basementTemperatureLabel, 1, 0);
m_houseGridLayout->addWidget(m_basementHumidityLabel, 1, 1);
connect(m_stack, &QStackedWidget::currentChanged, this, &HomeInfo::stackWidgetChanged);
m_weatherWidget = new WeatherWidget();
m_weatherWidget->setVisible(false);
m_stack->addWidget(m_clockGridWidget);
m_stack->addWidget(m_houseGridWidget);
m_stack->addWidget(m_weatherWidget);
setCentralWidget(m_stack);
}
HomeInfo::~HomeInfo() = default;
void HomeInfo::stackWidgetChanged(int index)
{
qDebug() << __PRETTY_FUNCTION__;
Q_UNUSED(index)
}
bool HomeInfo::event(QEvent *e)
{
if (e->type() == QEvent::MouseButtonRelease) {
qDebug() << __PRETTY_FUNCTION__;
if (m_stack->currentIndex() == (m_stack->count() - 1)) {
m_stack->setCurrentIndex(0);
}
else {
m_stack->setCurrentIndex(m_stack->currentIndex() + 1);
}
return true;
}
return QMainWindow::event(e);
}
WeatherWidget.h
#ifndef WEATHERWIDGET_H
#define WEATHERWIDGET_H
#include <QtCore/QtCore>
#include <QtWidgets/QtWidgets>
class WeatherWidget : public QWidget
{
Q_OBJECT
public:
WeatherWidget(QWidget *parent = nullptr);
~WeatherWidget() override;
protected:
void hideEvent(QHideEvent *event) override;
void showEvent(QShowEvent *event) override;
private:
QLabel *m_outdoorTemperatureLabel;
QLabel *m_outdoorTemperatureTextLabel;
QLabel *m_outdoorHumidityLabel;
QLabel *m_outdoorHumidityTextLabel;
QLabel *m_luxLabel;
QLabel *m_luxTextLabel;
QLabel *m_uvRawLabel;
QLabel *m_uvRawTextLabel;
QLabel *m_uvIndexLabel;
QLabel *m_uvIndexTextLabel;
QLabel *m_rainTodayLabel;
QLabel *m_rainTodayTextLabel;
QLabel *m_totalRainLabel;
QLabel *m_totalRainTextLabel;
QLabel *m_airPressureMercuryLabel;
QLabel *m_airPressureMercuryTextLabel;
QLabel *m_airPressureTrendLabel;
QLabel *m_airPressureTrendTextLabel;
QGridLayout *m_layout;
};
#endif // WEATHERWIDGET_H
WeatherWidget.cpp
#include "weatherwidget.h"
WeatherWidget::WeatherWidget(QWidget *parent) : QWidget(parent)
{
QDate now = QDate::currentDate();
QFont text("Roboto-Sans", 14);
QFont content("Roboto-Sans", 20);
m_outdoorTemperatureLabel = new QLabel();
m_outdoorTemperatureLabel->setFont(content);
m_outdoorTemperatureLabel->setAlignment(Qt::AlignCenter);
m_outdoorHumidityLabel = new QLabel();
m_outdoorHumidityLabel->setFont(content);
m_outdoorHumidityLabel->setAlignment(Qt::AlignCenter);
m_luxLabel = new QLabel();
m_luxLabel->setFont(content);
m_luxLabel->setAlignment(Qt::AlignCenter);
m_uvIndexLabel = new QLabel();
m_uvIndexLabel->setFont(content);
m_uvIndexLabel->setAlignment(Qt::AlignCenter);
m_rainTodayLabel = new QLabel();
m_rainTodayLabel->setFont(content);
m_rainTodayLabel->setAlignment(Qt::AlignCenter);
m_totalRainLabel = new QLabel();
m_totalRainLabel->setFont(content);
m_totalRainLabel->setAlignment(Qt::AlignCenter);
m_airPressureMercuryLabel = new QLabel();
m_airPressureMercuryLabel->setFont(content);
m_airPressureMercuryLabel->setAlignment(Qt::AlignCenter);
m_airPressureTrendLabel = new QLabel();
m_airPressureTrendLabel->setFont(content);
m_airPressureTrendLabel->setAlignment(Qt::AlignCenter);
m_outdoorTemperatureTextLabel = new QLabel("Temperature");
m_outdoorTemperatureTextLabel->setFont(text);
m_outdoorTemperatureTextLabel->setAlignment(Qt::AlignCenter);
m_outdoorHumidityTextLabel = new QLabel("Humidity");
m_outdoorHumidityTextLabel->setFont(text);
m_outdoorHumidityTextLabel->setAlignment(Qt::AlignCenter);
m_luxTextLabel = new QLabel("Brightness");
m_luxTextLabel->setFont(text);
m_luxTextLabel->setAlignment(Qt::AlignCenter);
m_uvIndexTextLabel = new QLabel("UV Index");
m_uvIndexTextLabel->setFont(text);
m_uvIndexTextLabel->setAlignment(Qt::AlignCenter);
m_rainTodayTextLabel = new QLabel("Rainfall Today");
m_rainTodayTextLabel->setFont(text);
m_rainTodayTextLabel->setAlignment(Qt::AlignCenter);
m_totalRainTextLabel = new QLabel();
m_totalRainTextLabel->setFont(text);
m_totalRainTextLabel->setAlignment(Qt::AlignCenter);
m_airPressureMercuryTextLabel = new QLabel("Air Pressure");
m_airPressureMercuryTextLabel->setFont(text);
m_airPressureMercuryTextLabel->setAlignment(Qt::AlignCenter);
m_airPressureTrendTextLabel = new QLabel("Air Pressure Trend");
m_airPressureTrendTextLabel->setFont(text);
m_airPressureTrendTextLabel->setAlignment(Qt::AlignCenter);
m_layout = new QGridLayout(this);
m_layout->addWidget(m_outdoorTemperatureTextLabel, 0, 0);
m_layout->addWidget(m_outdoorTemperatureLabel, 1, 0);
m_layout->addWidget(m_outdoorHumidityTextLabel, 0, 1);
m_layout->addWidget(m_outdoorHumidityLabel, 1, 1);
m_layout->addWidget(m_airPressureMercuryTextLabel, 0, 2);
m_layout->addWidget(m_airPressureMercuryLabel, 1, 2);
m_layout->addWidget(m_luxTextLabel, 2, 0);
m_layout->addWidget(m_luxLabel, 3, 0);
m_layout->addWidget(m_uvIndexTextLabel, 2, 1);
m_layout->addWidget(m_uvIndexLabel, 3, 1);
m_layout->addWidget(m_airPressureTrendTextLabel, 2, 2);
m_layout->addWidget(m_airPressureTrendLabel, 3, 2);
m_layout->addWidget(m_rainTodayTextLabel, 4, 0);
m_layout->addWidget(m_rainTodayLabel, 5, 0);
m_layout->addWidget(m_totalRainTextLabel, 4, 1);
m_layout->addWidget(m_rainTodayLabel, 5, 1);
setLayout(m_layout);
m_totalRainTextLabel->setText(QString("%1 Rainfall").arg(now.year()));
}
WeatherWidget::~WeatherWidget()
{
}
void WeatherWidget::showEvent(QShowEvent* event)
{
qDebug() << __PRETTY_FUNCTION__;
}
void WeatherWidget::hideEvent(QHideEvent* event)
{
qDebug() << __PRETTY_FUNCTION__;
}
main.cpp
#include "homeinfo.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
HomeInfo w;
app.setOverrideCursor(QCursor(Qt::BlankCursor));
w.setGeometry(0, 0, 800, 480);
w.show();
return app.exec();
}
Debug output
void HomeInfo::stackWidgetChanged(int) : Index 0 // constructor
virtual void WeatherWidget::showEvent(QShowEvent*) // constructor
virtual bool HomeInfo::event(QEvent*) // touchevent
void HomeInfo::stackWidgetChanged(int) : Index 1
virtual bool HomeInfo::event(QEvent*) //touchevent
void HomeInfo::stackWidgetChanged(int) : Index 2
virtual bool HomeInfo::event(QEvent*) // touchevent
virtual void WeatherWidget::hideEvent(QHideEvent*) //WeatherWidget gets hidden
void HomeInfo::stackWidgetChanged(int) : Index 0 // signal that index changed to HomeInfo
virtual void WeatherWidget::showEvent(QShowEvent*) // WeatherWidget gets another showEvent
virtual void WeatherWidget::hideEvent(QHideEvent*) // after X closes window
virtual void WeatherWidget::hideEvent(QHideEvent*) // after X closes window
*** Exited normally ***```
Upvotes: 0
Views: 239
Reputation: 568
No, this was just a dumb mistake. I used autocomplete when I attempted to type setLux() in HomeInfo.cpp (not visible, I removed the MQTT functions), and what I got was setVisible(). This meant that every time I got a new value for how bright it is outside, it was setVisible(true) on the widget when the double was implicitly cast to true. I would have expected a warning from gcc, but either warnings are turned off, or it wasn't generated. Ah well, this was not a QT bug or odd unexpected behavior, it was a mistake in my code.
Upvotes: 1