Bienvenue sur le forum !

Si vous souhaitez rejoindre la communauté, cliquez sur l'un de ces boutons !

Qt 5 : 5.7.1 - Qt Creator : 4.2.0 - Qt Installer : 2.0.3 - JOM : 1.1.2 - Qt Build suite : 1.7.0 - VS Qt 5 : 2.0.0

Redimensionner une image affichée dans un label...

9 Mar modifié dans Qt / Langage C++
Bonjour,
Je teste actuellement un code pour afficher avec QPixmap une image dans un label; dans la fenêtre en question, j'ai le label image et un QTextEdit texte dans deux cadres en splitter pour permettre l'ajustement. cf IM1.jpg

Le label est une sous-classe de QLabel, le texte un QTextEdit.
L'image à afficher dans le label est issue soit d'un glissé/déposé sur ce dernier, d'une image extérieure (depuis Firefox par ex.), soit du glissé/déposé d'un fichier jpg/png ou tif.
Jusque là pas de problème.
Pour assurer le redimensionnement de l'image, je peux agir avec le bouton gauche de la souris soit sur l'intervalle séparant les deux cadres du splitter, soit sur la fenêtre elle-même. (je teste en affichant la dimension du cadre dans le QTextEdit).

la méthode resizeEvent() a été implémentée dans la classe MyLabel à cet effet.
Ca fonctionne a peu près comme souhaité, hormis deux petits soucis:
- quand je glisse doucement avec le curseur sur le splitter, il y a parfois "un retard à l'allumage": le cadre s'agrandit bien mais l'image ne suit pas! Et il faut que je donne un grand coup au curseur pour que ça se rétablisse... cf IM2.jpg
- avec le redimensionnement de la fenêtre, ça suit bien cette fois, sauf que, lorsque je relâche le bouton souris, la fenêtre reprend parfois une taille différente et impossible de réduire (on dirait un 'élastique'!)

/* mylabel.h */
#ifndef MYLABEL_H
#define MYLABEL_H

#include <QLabel>
#include <QMessageBox>
#include <QUrl>

class MyLabel :public QLabel
{
Q_OBJECT

public:
MyLabel(QWidget *parent = 0);

private:
QPixmap m_pix;

signals:
void zoom();

protected:
void resizeEvent(QResizeEvent * event);
void dragEnterEvent(QDragEnterEvent *e);
};
#endif // MYLABEL_H

/* mylabel.cpp */
#include "mylabel.h"
#include "dialog.h"

MyLabel::MyLabel(QWidget *parent):QLabel (parent)
{
if (m_pix.load("D:/Devpts/_Tests/NonModal/Fond.jpg")) //fond blanc 254x127 pixels
{
m_pix.scaled(width(),height(),Qt::KeepAspectRatio, Qt::SmoothTransformation);
setPixmap(m_pix);
}
else
QMessageBox::warning(this,"","Pas d'image");

setAcceptDrops(true);
}

void MyLabel::dragEnterEvent(QDragEnterEvent *e)
{
if (e->mimeData()->hasImage())
{
QPixmap pix = qvariant_cast<QPixmap>(e->mimeData()->imageData());
m_pix = pix;
setPixmap(pix.scaled(this->width(),this->height(),
Qt::KeepAspectRatio, Qt::SmoothTransformation));
e->accept();
}
if (e->mimeData()->hasFormat("text/uri-list"))//fichier image
{
QString fichier = qvariant_cast<QString>(e->mimeData()->urls().at(0));//nom de l'élement déposé
fichier.remove(0, 8);//enlève file:///

//voir si image?
if (fichier.contains(QRegExp(".jpg|.bmp|.png")))//fichiers image
{
if (!m_pix.load(fichier))
{
QMessageBox::about(this,"",fichier);
e->ignore();
}
QPixmap pix = m_pix;
setPixmap(pix.scaled(this->width(),this->height(),
Qt::KeepAspectRatio, Qt::SmoothTransformation));
e->accept();
}
else e->ignore();
}
else e->ignore();
}

void MyLabel::resizeEvent(QResizeEvent * event)
{
if(event->oldSize().width() == -1 || event->oldSize().height() == -1)
return;//1er appel, inchangé

if(event->size().width() - event->oldSize().width() > 2 || event->size().height() - event->oldSize().height() > 2 )
{
Dialog::setSize(event->size());//pour afficher dans texte la taille du cadre
emit zoom();//il y a eu modif

QPixmap pix = m_pix;
this->setPixmap(pix.scaled(event->size().width(),event->size().height(),
Qt::KeepAspectRatio, Qt::SmoothTransformation));
}
if(event->oldSize().width() - event->size().width() > 2 || event->oldSize().height() - event->size().height() > 2 )
{
Dialog::setSize(event->size());//affiche dans texte la taille du cadre
emit zoom();

QPixmap pix = m_pix;
this->setPixmap(pix.scaled(event->size().width(),event->size().height(),
Qt::KeepAspectRatio, Qt::SmoothTransformation));
}
}
/* dialog.h - le widget contenant le label et le texte */
#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QPixmap>
#include "mylabel.h"

namespace Ui {
class Dialog;
}

class Dialog : public QDialog
{
Q_OBJECT

public:
explicit Dialog(QWidget *parent = 0);
~Dialog();
static void setSize(QSize st);

private:
Ui::Dialog *ui;
static int m_w, m_h;//taille du cadre du label

public slots:
void affi();//affiche la taille du cadre du label

};
#endif // DIALOG_H

/*dialog.cpp */
#include "dialog.h"
#include "ui_dialog.h"

int Dialog::m_h, Dialog::m_w;

Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
connect(ui->image, SIGNAL(zoom()),this,SLOT(affi()));//affiche la taille si changement
}

Dialog::~Dialog()
{
delete ui;
}

void Dialog::setSize(QSize st)
{
m_w = st.width();
m_h = st.height();
}

void Dialog::affi()
{
ui->texte->append(QString("%1x%2").arg(m_w).arg(m_h));
}

jpg
jpg
IM1.jpg
39K
jpg
jpg
IM2.jpg
31K

Réponses

  • 9 Mar modifié
    Salut,
    je ne sais pas trop où tu en es avec l'installation de Qt5 , mais le projet que je t'avais mis ici : forum.qtfr.org/discussion/comment/122722/#Comment_122722
    évite tous ces problèmes, sans avoir besoin de gérer le resizeEvent, pas besoin non plus de scaler les pixmap dans le drag&drop.
    Tout est réalisé dans le paintEvent du label. D'ailleurs j'ai pris le code de Qt, puis j'ai enlevé tout ce qui ne servait à rien dans ton cas, et remplacé le scale qui ne garde pas l' aspect ratio dans leur code.
  • @babaOroms pour le moment, j'en suis resté à Qt 4.8, hésitant à installer Qt 5(un tiens vaut mieux que deux tu l'auras dit le proverbe...) et ne voulant surtout pas perdre Qt 4.8 car tous mes projets ont été compilés avec.
    Je vais revoir le code que tu m'avais envoyé précédemment si ça compile bien avec ma version.
    Si ça simplifie la gestion du redimensionnement, en effet.
    Mais j'aurais quand même bien voulu savoir d'où pouvait venir les petits problèmes rencontrés...
    En tout cas merci!
  • 9 Mar modifié
    @babaOrums j'ai repris le code que tu m'avais soumis, qui ne compile pas tel quel avec Qt 4.8:
    j'ai 2 erreurs dues à
    'devicePixelRatioF()'  et à 'setDevicePixelRatio(devicePixelRatioF())' ainsi que QSize scaledSize; non déclaré (?)

    Pour essayer de voir quand même ce qu'il en est, j'ai modifié les lignes où apparaissent les erreurs, cf:

    QSize scaledSize;
    if (pixmap() && !pixmap()->isNull()) {
    QPixmap pix;
    if (hasScaledContents()) {
    scaledSize = cr.size();//QSize scaledSize = cr.size() * devicePixelRatioF();
    if (!p_scaledpixmap ||
    (p_scaledpixmap->size().width() != scaledSize.width() && p_scaledpixmap->size().height() != scaledSize.height())) {
    if (!p_rescaleImage)
    p_rescaleImage = new QImage(pixmap()->toImage());
    delete p_scaledpixmap;
    QImage scaledImage =
    p_rescaleImage->scaled(scaledSize,
    Qt::KeepAspectRatio, Qt::SmoothTransformation);
    p_scaledpixmap = new QPixmap(QPixmap::fromImage(scaledImage));
    //p_scaledpixmap->setDevicePixelRatio(devicePixelRatioF());
    }
    pix = *p_scaledpixmap;
    }
    Ca compile et s'exécute!

    Le test de redimensionnement avec les 2 splitters ainsi que la fenêtre les contenant fonctionnent comme souhaité; par contre:
    - 1ère surprise, l'image couleur apparait ici en N&B (mais pas tout le temps car j'ai eu furtivement une image couleur)
    cf IM1, IM2, IM3
    - et il semble que l'image soit dégradée quant à sa résolution...
    cf IM2
    jpg
    jpg
    IM1.jpg
    12K
    jpg
    jpg
    IM2.jpg
    23K
    jpg
    jpg
    IM3.jpg
    9K
  • Re,
    je ne reproduis pas le problème de couleur, j'ai testé en Qt4.8.7 + mingw
    et en Qt5
    Pour le problème de résolution, c'est peut-être dû à la résolution de l'image de départ.
  • @babaOroms
    OK, pour la compilation avec Qt4.8 + ming (que j'utilise aussi) as-tu utilisé le code sans modification cad tel que tu me l'avais soumis ou as-tu modifié pour que ça compile?

    J'ai ressayé, en changeant d'image (cf Image.jpg, celle-ci fait 1458x2352): à nouveau, l'image est en N&B et peu résolue... j'ai capturé l'écran de l'image affichée dans le label et via la visionneuse de Windows en m'arrangeant pou avoir le même grandissement.
    voir IM4 et IM5. Comprends pas...
    Serait-ce dû à ce que j'ai été obligé de modifier pour que ça compile? (cf devicePixelRatioF)
    jpg
    jpg
    IM4.jpg
    28K
    jpg
    jpg
    IM5.jpg
    12K
    jpg
    jpg
    Image.jpg
    482K
  • Alors pour compiler avec Qt4, j'ai dû bien sûr modifier le code où j'ai juste retirer
    * devicePixelRatioF()
    et
    p_scaledpixmap->setDevicePixelRatio(devicePixelRatioF());
    pour le reste j'ai tout laissé tel quel.

    Bizarre tout ça.

    Je testerai un peu plus tard l'histoire de la résolution
Connectez-vous ou Inscrivez-vous pour répondre.