QGraphicsView scorrimento e una scalatura delle immagini / ritaglio
-
21-09-2019 - |
Domanda
Mi piacerebbe avere un'immagine di sfondo nel mio QGraphicsView che è sempre in scala (e ritagliata se necessario) per la dimensione della finestra, senza barre di scorrimento e senza dover scorrere con la tastiera e il mouse. L'esempio che segue è quello che sto facendo per scalare e ritagliare un'immagine nella finestra, ma io sto usando valori casuali per il ritaglio che sono tirato fuori dell'etere. Vorrei una soluzione logica?
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
scene = new QGraphicsScene(this);
ui->graphicsView->resize(800, 427);
// MainWindow is 800x480, GraphicsView is 800x427. I want an image that
// is the size of the graphicsView.
ui->graphicsView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
ui->graphicsView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
// the graphicsView still scrolls if the image is too large, but
// displays no scrollbars. I would like it not to scroll (I want to
// add a scrolling widget into the QGraphicsScene later, on top of
// the background image.)
QPixmap *backgroundPixmap = new QPixmap(":/Valentino_Bar_Prague.jpg");
QPixmap sized = backgroundPixmap->scaled(
QSize(ui->graphicsView->width(),
ui->graphicsView->height()),
Qt::KeepAspectRatioByExpanding); // This scales the image too tall
QImage sizedImage = QImage(sized.toImage());
QImage sizedCroppedImage = QImage(sizedImage.copy(0,0,
(ui->graphicsView->width() - 1.5),
(ui->graphicsView->height() + 19)));
// so I try to crop using copy(), and I have to use these values
// and I am unsure why.
QGraphicsPixmapItem *sizedBackground = scene->addPixmap(
QPixmap::fromImage(sizedCroppedImage));
sizedBackground->setZValue(1);
ui->graphicsView->setScene(this->scene);
}
Mi piacerebbe conoscere un modo per scalare e ritagliare un'immagine alle dimensioni del QGraphicsView che funziona anche quando ho ridimensionare il QGraphicsView. Dove sono i 1,5 e 19 provenienti da?
EDIT; Ho anche tentato di usare setBackgroundBrush, ma ottengo uno sfondo in maiolica, anche quando si utilizza la scalata / cropped QImage / QPixmap.
EDIT; La mia soluzione finora è stata quella di ignorare drawBackground () per ottenere il risultato che volevo, ma questo ancora non aiutarmi ad imparare come dimensione di un'immagine alle dimensioni viewport di una QGraphicsView. Eventuali ulteriori risposte sarebbe molto apprezzato.
void CustomGraphicsView::drawBackground( QPainter * painter, const QRectF & rect )
{
qDebug() << "background rect: " << rect << endl;
QPixmap *backgroundPixmap = new QPixmap(":/Valentino_Bar_Prague.jpg");
QPixmap sized = backgroundPixmap->scaled(QSize(rect.width(), rect.height()), Qt::KeepAspectRatioByExpanding);
painter->drawPixmap(rect, sized, QRect(0.0, 0.0, sized.width(), sized.height()));
}
Soluzione
Si vuole sceneRect
non solo width
e height
. Per la scala sul ridimensionamento si desidera collegare uno slot per sceneRectChanged
in modo da poter ridimensionare l'immagine ogni volta che la scena cambia dimensione.
In alternativa, è possibile derivare un QGraphicsView
con una updateSceneRect
che cambia il dimensioni dell'immagine, o meglio ancora, basta ignorare drawBackground
.
Altri suggerimenti
Ho trovato ui->graphicsView->viewport()->size()
per ottenere le dimensioni della finestra. Funziona solo dopo il widget è stato disegnato però.
Il QGraphicsView::fitInView
fa esattamente questo. Secondo la documentazione, è comunemente messo in una resizeEvent
. Utilizzando sceneRects
rende l'intera forma scena nella vista:
void CustomGraphicsView::resizeEvent(QResizeEvent *)
{
this->fitInView(this->sceneRect());
}