Qt 中的 QGraphicsScene 是否有 QLabel::setScaledContents 等效函数?
Is there QLabel::setScaledContents equivalent function for QGraphicsScene in Qt?
我正在使用 QGraphicsView 和 QGraphicsScene 来显示上传的图像,然后在其上显示一些绘图。我正在上传和图像:
void MeasuresWidget::on_openAction_triggered()
{
QString fileName = QFileDialog::getOpenFileName(this,tr("Open File"), QDir::currentPath());
if (!fileName.isEmpty())
{
QImage image(fileName);
if (image.isNull())
{
QMessageBox::information(this, tr("Measures Application"), tr("Cannot load %1.").arg(fileName));
return;
}
scene->clear();
scene->addPixmap(QPixmap::fromImage(image).scaledToWidth(w, Qt::SmoothTransformation));
}
}
我面临的问题是,如果我上传的图片比之前上传的图片小,那里似乎是空的 space,即场景保持上一张图片的大小(更大的)并且比当前的更大。我尝试在单个变量中保持场景的原始大小,并在每个上传操作中使用 setSceneRect()
:
//in constructor
originalRect = ui->graphicsView->rect();
//in upload action
scene->setSceneRect(originalRect);
但结果是场景的大小始终保持不变,如果它比实际图像大,则将其剪切。我之前使用 QLabel 显示图像,我使用 QLabel::setScaledContents()
函数,它对我来说效果很好。所以,我的问题是我可以使用 QGraphicsScene 实现相同的行为吗?
更新 1:
如果我在每次上传操作时都创建新场景,应用程序就会按照我想要的方式运行。代码现在看起来像:
void MeasuresWidget::on_openAction_triggered()
{
scene = new QGraphicsScene(this);
ui->graphicsView->setScene(scene);
QString fileName = QFileDialog::getOpenFileName(this,tr("Open File"), QDir::currentPath());
if (!fileName.isEmpty())
{
QImage image(fileName);
if (image.isNull())
{
QMessageBox::information(this, tr("Image Viewer"), tr("Cannot load %1.").arg(fileName));
return;
}
scene->clear();
scene->addPixmap(QPixmap::fromImage(image).scaledToWidth(w, Qt::SmoothTransformation));
}
}
这样可以吗?我可以实现我想要的行为而不需要在每次上传操作时都创建新场景吗?
插入像素图时,只需根据场景大小调整场景大小即可。
如果你定义一个新的class继承自QGraphicsScene
,你可以轻松处理:
class GraphicsScene: public QGraphicsScene
{
public:
GraphicsScene(QRect const& rect, QObject* parent=nullptr): QGraphicsScene(rect, parent),
background(nullptr)
{}
QGraphicsPixmapItem *addPixmap(const QPixmap &pixmap)
{
// We already have a background. Remove it
if (background)
{
removeItem(background);
delete background;
}
background = QGraphicsScene::addPixmap(pixmap);
// Move the pixmap
background->setPos(0, 0);
// Change the scene rect based on the size of the pixmap
setSceneRect(background->boundingRect());
return background;
}
private:
QGraphicsPixmapItem* background;
};
GraphicsScene* scene = new GraphicsScene(QRect());
QGraphicsView* view = new QGraphicsView();
view->setScene(scene);
view->show();
QPixmap pix1(QSize(2000, 2000));
pix1.fill(Qt::red);
QPixmap pix2(QSize(100, 300));
pix2.fill(Qt::green);
// The scene will be 2000x2000
QTimer::singleShot(1000, [=]() { scene->addPixmap(pix1); });
// The scene will be 100x300
QTimer::singleShot(10000, [=]() { scene->addPixmap(pix2); });
我正在使用 QGraphicsView 和 QGraphicsScene 来显示上传的图像,然后在其上显示一些绘图。我正在上传和图像:
void MeasuresWidget::on_openAction_triggered()
{
QString fileName = QFileDialog::getOpenFileName(this,tr("Open File"), QDir::currentPath());
if (!fileName.isEmpty())
{
QImage image(fileName);
if (image.isNull())
{
QMessageBox::information(this, tr("Measures Application"), tr("Cannot load %1.").arg(fileName));
return;
}
scene->clear();
scene->addPixmap(QPixmap::fromImage(image).scaledToWidth(w, Qt::SmoothTransformation));
}
}
我面临的问题是,如果我上传的图片比之前上传的图片小,那里似乎是空的 space,即场景保持上一张图片的大小(更大的)并且比当前的更大。我尝试在单个变量中保持场景的原始大小,并在每个上传操作中使用 setSceneRect()
:
//in constructor
originalRect = ui->graphicsView->rect();
//in upload action
scene->setSceneRect(originalRect);
但结果是场景的大小始终保持不变,如果它比实际图像大,则将其剪切。我之前使用 QLabel 显示图像,我使用 QLabel::setScaledContents()
函数,它对我来说效果很好。所以,我的问题是我可以使用 QGraphicsScene 实现相同的行为吗?
更新 1: 如果我在每次上传操作时都创建新场景,应用程序就会按照我想要的方式运行。代码现在看起来像:
void MeasuresWidget::on_openAction_triggered()
{
scene = new QGraphicsScene(this);
ui->graphicsView->setScene(scene);
QString fileName = QFileDialog::getOpenFileName(this,tr("Open File"), QDir::currentPath());
if (!fileName.isEmpty())
{
QImage image(fileName);
if (image.isNull())
{
QMessageBox::information(this, tr("Image Viewer"), tr("Cannot load %1.").arg(fileName));
return;
}
scene->clear();
scene->addPixmap(QPixmap::fromImage(image).scaledToWidth(w, Qt::SmoothTransformation));
}
}
这样可以吗?我可以实现我想要的行为而不需要在每次上传操作时都创建新场景吗?
插入像素图时,只需根据场景大小调整场景大小即可。
如果你定义一个新的class继承自QGraphicsScene
,你可以轻松处理:
class GraphicsScene: public QGraphicsScene
{
public:
GraphicsScene(QRect const& rect, QObject* parent=nullptr): QGraphicsScene(rect, parent),
background(nullptr)
{}
QGraphicsPixmapItem *addPixmap(const QPixmap &pixmap)
{
// We already have a background. Remove it
if (background)
{
removeItem(background);
delete background;
}
background = QGraphicsScene::addPixmap(pixmap);
// Move the pixmap
background->setPos(0, 0);
// Change the scene rect based on the size of the pixmap
setSceneRect(background->boundingRect());
return background;
}
private:
QGraphicsPixmapItem* background;
};
GraphicsScene* scene = new GraphicsScene(QRect());
QGraphicsView* view = new QGraphicsView();
view->setScene(scene);
view->show();
QPixmap pix1(QSize(2000, 2000));
pix1.fill(Qt::red);
QPixmap pix2(QSize(100, 300));
pix2.fill(Qt::green);
// The scene will be 2000x2000
QTimer::singleShot(1000, [=]() { scene->addPixmap(pix1); });
// The scene will be 100x300
QTimer::singleShot(10000, [=]() { scene->addPixmap(pix2); });