I have the following Qt code fragment in my widget.cpp:
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
m_Scene = new QGraphicsScene(this);
m_Scene->setSceneRect(0, 0, 1024, 768);
GraphicsTextItem* m_1 = new GraphicsTextItem(nullptr, QString("l_1"));
GraphicsTextItem* m_2 = new GraphicsTextItem(nullptr, QString("l_2"));
QGraphicsLinearLayout* layout = new QGraphicsLinearLayout;
layout->addItem(m_1);
layout->addItem(m_2);
QGraphicsWidget* list = new QGraphicsWidget;
list->setLayout(layout);
m_Scene->addItem(list);
qDebug() << m_2->x() << " " << m_2->y(); // Prints 0,0 Why?
QGraphicsView* view = new QGraphicsView(this);
view->setScene(m_Scene);
}
GraphicsTextItem is a derived class of QGraphicsWidget :
class GraphicsTextItem : public QGraphicsWidget
{
private:
QString m_Name;
public:
GraphicsTextItem(QGraphicsItem * parent = nullptr, const QString& name = QString());
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override
{
QFont font("Times", 12);
painter->setFont(font);
painter->drawText(0, 0, m_Name);
}
};
I also give my short main located in main.cpp:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
My question is that why the qDebug line prinnts me 0,0 as certainly the position of the widget is non-zero. If I don't put the widget in a layout and I call setPos() qDebug prints the correct value set previously.
The initial position of all QGraphicsItem is (0, 0) and that includes m_2, and m_2 will change its position when the QGraphicsLinearLayout is applied that will be an instant after the synchronous task is finished and the eventloop starts working, this can be observed using QTimer::singleShot(0, ...):
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
m_Scene = new QGraphicsScene(this);
QGraphicsView* view = new QGraphicsView(this);
view->setScene(m_Scene);
m_Scene->setSceneRect(0, 0, 1024, 768);
GraphicsTextItem *m_1 = new GraphicsTextItem(nullptr, QString("l_1"));
GraphicsTextItem *m_2 = new GraphicsTextItem(nullptr, QString("l_2"));
QGraphicsLinearLayout* layout = new QGraphicsLinearLayout;
layout->addItem(m_1);
layout->addItem(m_2);
QGraphicsWidget* list = new QGraphicsWidget;
list->setLayout(layout);
m_Scene->addItem(list);
qDebug() << "synchronous" << m_2->pos() << m_2->mapToScene(QPointF{});
QTimer::singleShot(0, m_2, [m_2](){
qDebug() << "asynchronous"<< m_2->pos() << m_2->mapToScene(QPointF{});
});
}
Output:
synchronous QPointF(0,0) QPointF(0,0)
asynchronous QPointF(62,6) QPointF(62,6)
Related
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 ***```
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.
I created a widget class. This class will be maintaining child_1 of type QFrame(which is of type QWidget) and also a child_2 of type QGridLayout . child_2 will be adding child_1 to itself. The child_1 will be having a child of type QGridLayout and ultimately QGridLayout will be having some push buttons.
*I am unable to adjust the size of QFrame child(child_1)as per the adjustment of parent widget.
Also, I am trying to set the size of QFrame child that of parent. Even this isn't happening.
I have tried using methods setFrameRect(), setGeometry() and resize().
I have implemented evenhandler resizeEvent(QResizeEvent event). But while application is running, I am trying to resize the widget and I see that log isn't printing.
main.cpp
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
widget.h
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
private:
Ui::Widget *ui;
QGridLayout* p_mPanelLayout; // Instance of QGridLayout.
FrameDemo* framePtr;
};
widget.cpp
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
p_mPanelLayout = new QGridLayout(this);
framePtr = new FrameDemo(this);
framePtr->createPushButtonUtility();
p_mPanelLayout->addWidget(framePtr, 0, 0, Qt::AlignCenter);
}
Widget::~Widget()
{
delete ui;
}
framedemo.h
#define LOG(message){\
qDebug()<< __LINE__<<__FUNCTION__<<message<<"\n";\
}
class FrameDemo : public QFrame
{
Q_OBJECT
public:
FrameDemo(QWidget *parent = 0);
void createPushButtonUtility();
private:
QGridLayout* m_pLayout;
protected:
void resizeEvent(QResizeEvent * event);
};
framedemo.cpp
FrameDemo::FrameDemo(QWidget *parent):QFrame(parent)
{
m_pLayout = new QGridLayout(this);
// m_pLayout->setRowStretch(0, parent->width());
QRect defaultRect = rect();
QSize currentSize = size();
LOG(currentSize.height())
LOG(currentSize.width())
int xP1 = 0;
int yP1 = 0;
int xP2 = 0;
int yP2 = 0;
defaultRect.getCoords(&xP1, &yP1, &xP2, &yP2);
LOG(xP1)
LOG(yP1)
LOG(xP2)
LOG(yP2)
LOG(parent->width())
LOG(defaultRect.height())
// QRect newRect = QRect(xP1,yP1,parent->width(),defaultRect.height());
// QRect newRect = QRect(0, 0, 0, defaultRect.height());
// setFrameRect(newRect);
resize(QSize(400, currentSize.height()));
setFrameShape(QFrame::Box);
// setGeometry(0, 0, parent->width(), defaultRect.height());
}
void FrameDemo::createPushButtonUtility()
{
QPushButton *readButton = new QPushButton("Read", this);
m_pLayout->addWidget(readButton, 0, 0, Qt::AlignCenter);
QPushButton *writeButton = new QPushButton("Write", this);
m_pLayout->addWidget(writeButton, 0, 1, Qt::AlignCenter);
QPushButton *updateButton = new QPushButton("Update", this);
m_pLayout->addWidget(updateButton, 0, 2, Qt::AlignCenter);
}
void FrameDemo::resizeEvent(QResizeEvent *event)
{
LOG("resize")
}
I managed to fix the problem.
I missed to implement the event handler resizeEvent(QResizeEvent *event) in parent widget.
I implemented the same and called the resizeEvent of FrameDemo. Inside this event handler, I called setGeometry().
I try to create a simple application with QGraphicsView. The application can load graphical files with different ratios in the view. I would like to implement the following feature: on the application window resize, the content of the view should be also resized and centered. I do not know this part of the Qt well, so I can resize the content, but I cannot center it. How can I fix it?
MainWindow.h snippet:
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
~MainWindow();
void resizeEvent(QResizeEvent *event) override;
public slots:
void onButtonClicked();
private:
bool m_flag = false;
QGraphicsPixmapItem *m_item = nullptr;
QGraphicsView *m_view = nullptr;
QPixmap m_pixmap;
};
MainWindow.cpp:
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
auto central = new QWidget(this);
setCentralWidget(central);
// layouts
auto mainLayout = new QVBoxLayout;
mainLayout->setAlignment(Qt::AlignTop);
central->setLayout(mainLayout);
// top layout
auto topLayout = new QHBoxLayout;
topLayout->setAlignment(Qt::AlignLeft);
mainLayout->addLayout(topLayout);
auto btn = new QPushButton(this);
btn->setText("Test");
connect(btn, &QPushButton::clicked, this, &MainWindow::onButtonClicked);
topLayout->addWidget(btn);
m_view = new QGraphicsView;
mainLayout->addWidget(m_view);
auto scene = new QGraphicsScene;
m_view->setScene(scene);
m_view->setMinimumSize(800, 600);
m_view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
m_view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
QString name = ":/pic1.jpg";
m_pixmap = QPixmap{ name }.scaled(800, 600, Qt::KeepAspectRatio);
m_item = scene->addPixmap(m_pixmap);
m_view->viewport()->resize(m_pixmap.size());
}
void MainWindow::onButtonClicked()
{
m_flag = !m_flag;
QString name = m_flag ? ":/pic2.png" : ":/pic1.jpg";
m_pixmap = QPixmap{ name }.scaled(m_view->size(), Qt::KeepAspectRatio);
m_item->setPixmap(m_pixmap);
m_view->fitInView(m_item, Qt::KeepAspectRatio);
}
void MainWindow::resizeEvent(QResizeEvent *event)
{
QMainWindow::resizeEvent(event);
m_view->fitInView(m_item, Qt::KeepAspectRatio);
}
Test result for the pic2.png:
When an image is scaled, it is done with respect to the top left, so it will always look up if the height is smaller than the prefix or to the right if the width is smaller.
The solution is to repaint the scaled QPixmap in the middle of the final QPixmap.
const QSize pixmap_size{800, 600};
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
auto central = new QWidget(this);
setCentralWidget(central);
// layouts
auto mainLayout = new QVBoxLayout;
mainLayout->setAlignment(Qt::AlignTop);
central->setLayout(mainLayout);
// top layout
auto topLayout = new QHBoxLayout;
topLayout->setAlignment(Qt::AlignLeft);
mainLayout->addLayout(topLayout);
auto btn = new QPushButton(this);
btn->setText("Test");
connect(btn, &QPushButton::clicked, this, &MainWindow::onButtonClicked);
topLayout->addWidget(btn);
m_view = new QGraphicsView;
mainLayout->addWidget(m_view);
auto scene = new QGraphicsScene;
m_view->setScene(scene);
m_view->setMinimumSize(pixmap_size);
m_view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
m_view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
m_pixmap = QPixmap(pixmap_size);
m_pixmap.fill(Qt::transparent);
m_item = new QGraphicsPixmapItem;
m_view->scene()->addItem(m_item);
show();
onButtonClicked();
}
QPixmap MainWindow::createPixmap(const QString & filename, const QSize & size) const{
QPixmap tmp = QPixmap{ filename }.scaled(size, Qt::KeepAspectRatio);
QPixmap pixmap(size);
pixmap.fill(Qt::transparent);
QPainter p(&pixmap);
QPoint point(QRect({}, size).center()-tmp.rect().center());
p.drawPixmap(point, tmp);
p.end();
return pixmap;
}
void MainWindow::onButtonClicked()
{
QString name = m_flag ? ":/pic2.png" : ":/pic1.jpg";
m_item->setPixmap(createPixmap(name, pixmap_size));
m_flag = !m_flag;
m_view->fitInView(m_item, Qt::KeepAspectRatio);
}
void MainWindow::resizeEvent(QResizeEvent *event)
{
QMainWindow::resizeEvent(event);
m_view->fitInView(m_item, Qt::KeepAspectRatio);
}
I added a QLabel inside my widget and it is editable through UI, able to set new text also, but not able to retrieve the updated text using function text();
QLabel *m_ColorName = new QLabel("_________");
m_ColorName->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextEditable);
In UI i am able to edit to new text but by calling function
m_ColorName->text();
Its giving default txt _________
Code
H file
class CascadeColorHighlightWidgetItem : public QWidget
{
Q_OBJECT
public:
CascadeColorHighlightWidgetItem(int jobID, QColor selectedColor, QWidget *parent = 0);
int getJobID();
QString getSelectedColor();
QString getColorText();
private:
QString m_titleName;
QRectF m_textRect;
QVBoxLayout *m_mainLyt;
QLineEdit *m_pTitleEditor;
QLabel *m_ColorName;
QColor m_SelectedColor;
};
Source File
CascadeColorHighlightWidgetItem::CascadeColorHighlightWidgetItem(QColor selectedColor, QWidget *parent)
: QWidget(parent),m_titleName("______"),m_SelectedColor(selectedColor)
{
setFixedHeight(40);
setContentsMargins(0,0,0,0);
setFocusPolicy(Qt::StrongFocus);
m_pTitleEditor = new QLineEdit();
m_ColorName = new QLabel("_________");
m_ColorName->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextEditable);
QFont font( "Calibri" );
font.setPixelSize(14);
m_ColorName->setFont(font);
QPixmap pixmap;
pixmap.fill(QColor("transparent"));
QWidget *pixMap = new QWidget;
pixMap->resize(100,100);
QString styl = QString("background-color: rgb(%1, %2, %3)").arg(QString::number(m_SelectedColor.red()),
QString::number(m_SelectedColor.green()),
QString::number(m_SelectedColor.blue()));
pixMap->setStyleSheet(styl);
m_ColorToStringMap.insert(m_ColorName->text(),m_SelectedColor);
QHBoxLayout * mnLyt = new QHBoxLayout(this);
mnLyt->addWidget(pixMap);
mnLyt->addWidget(m_ColorName);
mnLyt->addSpacerItem(new QSpacerItem(30, 0, QSizePolicy::Minimum, QSizePolicy::Minimum));
int width = pixMap->width();
int height = pixMap->height();
int side = qMin(width, height);
QRegion maskedRegion(width/2- side/2, height/2- side/2, 20,
20, QRegion::Ellipse);
pixMap->setMask(maskedRegion);
}
QString CascadeColorHighlightWidgetItem::getColorText()
{
qDebug() << "!!!CascadeColorHighlightWidgetItem::getColorText" << m_ColorName->text(); // returns "_________"
return m_ColorName->text();
}
It seems that although the text is editable, the data is not updated in the text, that can be solved with a hack, we use findChild to find the QTextDocument that is created when the flags are activated and get the text of that element:
QTextDocument *td = m_ColorName->findChild<QTextDocument *>();
if(td){
QString text = td->toRawText(); // >= Qt 5.9
// td->toPlainText();
// td->toHtml();
}
Example:
#include <QApplication>
#include <QLabel>
#include <QTextDocument>
#include <QTimer>
#include <QVBoxLayout>
#include <QWidget>
#include <QDebug>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget widget;
QLabel label("_________");
label.setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextEditable);
widget.setLayout(new QVBoxLayout);
widget.layout()->addWidget(&label);
QTimer timer;
QObject::connect(&timer, &QTimer::timeout, [&label](){
QTextDocument *td = label.findChild<QTextDocument*>();
if(td){
qDebug()<<td->toRawText();
//qDebug()<<td->toPlainText();
//qDebug()<<td->toHtml();
}
});
timer.start(100);
widget.show();
return a.exec();
}
Output:
[...]
"________"
"________"
"_______"
"____f___"
"____f___"
"____ff___"
"____fff___"
"____fff___"
"____ffff___"
"____fffff___"
"____fffff___"
[...]
i've got a problem for my school projet... I just can't get the scene position of any object in a QGraphicsGridLayout, it always give me (0,0). Maybe i subclass badly QGraphicsWidget ?
This is a example of how i use it :
main:
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QGraphicsScene *scene = new QGraphicsScene();
myCustomWidget *a = new myCustomWidget("a");
myCustomWidget *b = new myCustomWidget("b");
myCustomWidget *c = new myCustomWidget("c");
QGraphicsGridLayout *layout = new QGraphicsGridLayout();
layout->addItem(a,0,0,1,2, Qt::AlignCenter);
layout->addItem(b,1,0,1,1);
layout->addItem(c,1,1,1,1);
QGraphicsWidget *w = new QGraphicsWidget();
w->setLayout(layout);
scene->addItem(w);
QWidget* Window = new QWidget();
Window->setMinimumSize(640,380);
QVBoxLayout* layoutWindow = new QVBoxLayout();
Window->setLayout(layoutWindow);
QGraphicsView *view = new QGraphicsView(Window);
view->setScene(scene);
view->show();
layoutWindow->addWidget(view);
Window->show();
////////////////////////////////
// Always return QPointF(0,0) //
////////////////////////////////
qDebug() << c->scenePos();
return app.exec();
}
myCustomWidget:
class myCustomWidget : public QGraphicsWidget
{
private:
QString caption;
public:
myCustomWidget(QString caption, QGraphicsWidget* parent = 0) : QGraphicsWidget(parent)
{
this->caption = caption;
}
QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
{
Q_UNUSED(which);
Q_UNUSED(constraint);
return QSizeF(100,100);
}
QRectF boundingRect() const
{
return QRectF(QPointF(0,0), QSizeF(100,100));
}
void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget * = 0) Q_DECL_OVERRIDE
{
QFont font;
font.setPixelSize(0.75 * qMin(boundingRect().width(), boundingRect().height()));
painter->fillRect(boundingRect(), Qt::black);
painter->setFont(font);
painter->setPen(QPen(Qt::white));
painter->drawText(boundingRect(), Qt::AlignCenter, caption);
}
};