在 Qt 中保存和恢复带有图像的 QLabel
Save and restore QLabels with images in Qt
目前我正在使用 QLabel
s 在我正在开发的 GUI 应用程序上显示图像。它的工作原理是当用户单击 "Add Graphic" 按钮时,将创建一个新的动态标签并显示在 window 上。当用户双击标签时,文件对话框打开,用户可以 select 要显示的图像,效果很好。
应用的要求是在应用关闭时恢复图像,这样用户就不用再输入图像了,我正在苦苦思索解决方案。我正在尝试使用 QBuffer
s 和 QSettings
来恢复图像,但有一行代码使应用程序崩溃。
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
readSettings();
ui->setupUi(this);
// Set up the window size
this->setWindowTitle(QString::fromUtf8("Raspberry PI GUI v1.0"));
this->resize(800, 400);
// Add label Button
button = new QPushButton("Add Graphic", this);
button->setGeometry(QRect(QPoint(10, 20), QSize(200, 50)));
button->show();
QObject::connect(button, SIGNAL(pressed()), this, SLOT(input_label()));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::input_label()
{
Label *label = new Label(this);
label->setText("New Graphic");
label->show();
}
void MainWindow::writeSettings()
{
QByteArray bArray;
QBuffer buffer(&bArray);
buffer.open(QIODevice::WriteOnly);
this->label->pixmap()->save(&buffer, "PNG"); // This line of code is crashing everything
QSettings settings("Save state", "GUIApp");
settings.beginGroup("MainWindow");
settings.setValue("image", bArray);
}
void MainWindow::readSettings()
{
QSettings settings("Save state", "GUIApp");
settings.beginGroup("MainWindow");
QByteArray image = settings.value("image", QByteArray()).toByteArray();
}
void MainWindow::closeEvent(QCloseEvent *event)
{
writeSettings();
event->accept();
}
label.cpp
#include "label.h"
//---------------------------------------
// Deconstructor
//---------------------------------------
Label::~Label()
{
}
void Label::mousePressEvent(QMouseEvent *event)
{
// Move the coordinates on the main window
m_nMouseClick_X_Coordinate = event->x();
m_nMouseClick_Y_Coordinate = event->y();
}
void Label::mouseMoveEvent(QMouseEvent *event)
{
//-------------------------------------------------------------
// Allow the user to drag the graphics on the Display
//-------------------------------------------------------------
move(event->globalX()-m_nMouseClick_X_Coordinate-m_pParentWidget->geometry().x(),
event->globalY()-m_nMouseClick_Y_Coordinate-m_pParentWidget->geometry().y());
}
void Label::mouseDoubleClickEvent(QMouseEvent *event)
{
//QByteArray bArray;
//QBuffer buffer(&bArray);
//buffer.open(QIODevice::WriteOnly);
//--------------------------------
// Open file dialog
//--------------------------------
QFileDialog dialog(this);
dialog.setNameFilter(tr("Images(*.png, *.dxf, *.jpg"));
dialog.setViewMode(QFileDialog::Detail);
QString fileName = QFileDialog::getOpenFileName(this,
tr("Open Images"),
"/home",
tr("Image Files (*.png *.jpg *.bmp)"));
if (!fileName.isEmpty())
{
QImage image(fileName);
Label::setPixmap(fileName);
Label::adjustSize();
}
}
QLabel::pixmap
returns 如果没有设置像素图,则为空指针。同样,您应该检查您的属性文件是否设置了 image
条目,只有在这种情况下才恢复图像。
void MainWindow::writeSettings()
{
if (this->label->pixmap() != nullptr) {
QByteArray bArray;
QBuffer buffer(&bArray);
buffer.open(QIODevice::WriteOnly);
this->label->pixmap()->save(&buffer, "PNG");
QSettings settings("Save state", "GUIApp");
settings.beginGroup("MainWindow");
settings.setValue("image", bArray);
}
}
void MainWindow::readSettings()
{
QSettings settings("Save state", "GUIApp");
settings.beginGroup("MainWindow");
QByteArray image = settings.value("image").toByteArray();
if (!image.isNull()) {
QPixmap pixmap;
if (pixmap.loadFromData(image)) {
this->label->setPixmap(pixmap);
}
}
}
更新
当您创建 QLabel
时,您将其存储在局部变量中,但它从未分配给 this->label
,因此您在执行任何 this->label->...
操作时可能正在访问垃圾.
void MainWindow::input_label()
{
Label *label = new Label(this);
label->setText("New Graphic");
label->show();
this->label = label; // try with this
}
这是一种解决方法,如果可行,您必须检查其余逻辑,然后您可以添加多个 QLabel
,但只保存最后一个...恢复状态时相同: this->label
可能没有创建,所以你必须创建它,以及在构造函数中将this->label
初始化为nullptr
。
几个标签
对于多个标签,我建议使用 QList<QLabel*>
容器而不是单个 QLabel
成员,并保存所有这些标签。恢复时,只需在恢复图像之前以编程方式插入新标签即可。
class MainWindow ... {
// ...
QList<QLabel*> labels;
// ...
}
void MainWindow::input_label()
{
QLabel *label = new QLabel(this);
label->setText("New Graphic");
label->show();
this->labels.append(label);
}
void MainWindow::writeSettings()
{
int i = 1;
Q_FOREACH(auto label, labels) { // save all existing labels with an image
if (label->pixmap() != nullptr) {
QByteArray bArray;
QBuffer buffer(&bArray);
buffer.open(QIODevice::WriteOnly);
label->pixmap()->save(&buffer, "PNG");
QSettings settings("Save state", "GUIApp");
settings.beginGroup("MainWindow");
settings.setValue(QString("image-%1").arg(i), bArray);
++i;
}
}
}
void MainWindow::readSettings()
{
QSettings settings("Save state", "GUIApp");
settings.beginGroup("MainWindow");
int i = 1;
while (true) {
QByteArray image = settings.value(QString("image-%1").arg(i)).toByteArray();
if (!image.isNull()) {
QPixmap pixmap;
if (pixmap.loadFromData(image)) {
input_label(); // add new label
this->labels.back()->setPixmap(pixmap);
}
} else break; // no more images
++i;
}
}
目前我正在使用 QLabel
s 在我正在开发的 GUI 应用程序上显示图像。它的工作原理是当用户单击 "Add Graphic" 按钮时,将创建一个新的动态标签并显示在 window 上。当用户双击标签时,文件对话框打开,用户可以 select 要显示的图像,效果很好。
应用的要求是在应用关闭时恢复图像,这样用户就不用再输入图像了,我正在苦苦思索解决方案。我正在尝试使用 QBuffer
s 和 QSettings
来恢复图像,但有一行代码使应用程序崩溃。
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
readSettings();
ui->setupUi(this);
// Set up the window size
this->setWindowTitle(QString::fromUtf8("Raspberry PI GUI v1.0"));
this->resize(800, 400);
// Add label Button
button = new QPushButton("Add Graphic", this);
button->setGeometry(QRect(QPoint(10, 20), QSize(200, 50)));
button->show();
QObject::connect(button, SIGNAL(pressed()), this, SLOT(input_label()));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::input_label()
{
Label *label = new Label(this);
label->setText("New Graphic");
label->show();
}
void MainWindow::writeSettings()
{
QByteArray bArray;
QBuffer buffer(&bArray);
buffer.open(QIODevice::WriteOnly);
this->label->pixmap()->save(&buffer, "PNG"); // This line of code is crashing everything
QSettings settings("Save state", "GUIApp");
settings.beginGroup("MainWindow");
settings.setValue("image", bArray);
}
void MainWindow::readSettings()
{
QSettings settings("Save state", "GUIApp");
settings.beginGroup("MainWindow");
QByteArray image = settings.value("image", QByteArray()).toByteArray();
}
void MainWindow::closeEvent(QCloseEvent *event)
{
writeSettings();
event->accept();
}
label.cpp
#include "label.h"
//---------------------------------------
// Deconstructor
//---------------------------------------
Label::~Label()
{
}
void Label::mousePressEvent(QMouseEvent *event)
{
// Move the coordinates on the main window
m_nMouseClick_X_Coordinate = event->x();
m_nMouseClick_Y_Coordinate = event->y();
}
void Label::mouseMoveEvent(QMouseEvent *event)
{
//-------------------------------------------------------------
// Allow the user to drag the graphics on the Display
//-------------------------------------------------------------
move(event->globalX()-m_nMouseClick_X_Coordinate-m_pParentWidget->geometry().x(),
event->globalY()-m_nMouseClick_Y_Coordinate-m_pParentWidget->geometry().y());
}
void Label::mouseDoubleClickEvent(QMouseEvent *event)
{
//QByteArray bArray;
//QBuffer buffer(&bArray);
//buffer.open(QIODevice::WriteOnly);
//--------------------------------
// Open file dialog
//--------------------------------
QFileDialog dialog(this);
dialog.setNameFilter(tr("Images(*.png, *.dxf, *.jpg"));
dialog.setViewMode(QFileDialog::Detail);
QString fileName = QFileDialog::getOpenFileName(this,
tr("Open Images"),
"/home",
tr("Image Files (*.png *.jpg *.bmp)"));
if (!fileName.isEmpty())
{
QImage image(fileName);
Label::setPixmap(fileName);
Label::adjustSize();
}
}
QLabel::pixmap
returns 如果没有设置像素图,则为空指针。同样,您应该检查您的属性文件是否设置了 image
条目,只有在这种情况下才恢复图像。
void MainWindow::writeSettings()
{
if (this->label->pixmap() != nullptr) {
QByteArray bArray;
QBuffer buffer(&bArray);
buffer.open(QIODevice::WriteOnly);
this->label->pixmap()->save(&buffer, "PNG");
QSettings settings("Save state", "GUIApp");
settings.beginGroup("MainWindow");
settings.setValue("image", bArray);
}
}
void MainWindow::readSettings()
{
QSettings settings("Save state", "GUIApp");
settings.beginGroup("MainWindow");
QByteArray image = settings.value("image").toByteArray();
if (!image.isNull()) {
QPixmap pixmap;
if (pixmap.loadFromData(image)) {
this->label->setPixmap(pixmap);
}
}
}
更新
当您创建 QLabel
时,您将其存储在局部变量中,但它从未分配给 this->label
,因此您在执行任何 this->label->...
操作时可能正在访问垃圾.
void MainWindow::input_label()
{
Label *label = new Label(this);
label->setText("New Graphic");
label->show();
this->label = label; // try with this
}
这是一种解决方法,如果可行,您必须检查其余逻辑,然后您可以添加多个 QLabel
,但只保存最后一个...恢复状态时相同: this->label
可能没有创建,所以你必须创建它,以及在构造函数中将this->label
初始化为nullptr
。
几个标签
对于多个标签,我建议使用 QList<QLabel*>
容器而不是单个 QLabel
成员,并保存所有这些标签。恢复时,只需在恢复图像之前以编程方式插入新标签即可。
class MainWindow ... {
// ...
QList<QLabel*> labels;
// ...
}
void MainWindow::input_label()
{
QLabel *label = new QLabel(this);
label->setText("New Graphic");
label->show();
this->labels.append(label);
}
void MainWindow::writeSettings()
{
int i = 1;
Q_FOREACH(auto label, labels) { // save all existing labels with an image
if (label->pixmap() != nullptr) {
QByteArray bArray;
QBuffer buffer(&bArray);
buffer.open(QIODevice::WriteOnly);
label->pixmap()->save(&buffer, "PNG");
QSettings settings("Save state", "GUIApp");
settings.beginGroup("MainWindow");
settings.setValue(QString("image-%1").arg(i), bArray);
++i;
}
}
}
void MainWindow::readSettings()
{
QSettings settings("Save state", "GUIApp");
settings.beginGroup("MainWindow");
int i = 1;
while (true) {
QByteArray image = settings.value(QString("image-%1").arg(i)).toByteArray();
if (!image.isNull()) {
QPixmap pixmap;
if (pixmap.loadFromData(image)) {
input_label(); // add new label
this->labels.back()->setPixmap(pixmap);
}
} else break; // no more images
++i;
}
}