Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: Hort от Октябрь 19, 2008, 12:37



Название: Подгонка QScrollArea под контент
Отправлено: Hort от Октябрь 19, 2008, 12:37
Есть такой класс
Код:
class ImageViewDialog : public QDialog
{
Q_OBJECT

// Member Variables
private:
double scaleFactor;
QLabel* imageLabel;
QScrollArea* scrollArea;
QPushButton* buttonZoomIn;
QPushButton* buttonZoomOut;

// Constructor & Destructor
public:
ImageViewDialog(const QString& image, QWidget* parent=0);

// Member Functions
private:
void scaleImage(double factor);
void adjustScrollBar(QScrollBar* scrollBar, double factor);
private slots:
void slotZoomIn();
void slotNormalSize();
void slotZoomOut();
};
Код:
ImageViewDialog::ImageViewDialog(const QString& fileName, QWidget* parent) : QDialog(parent)
{
setWindowFlags(windowFlags()|Qt::WindowMaximizeButtonHint);
QImage image(fileName);
if(image.isNull()){
QMessageBox::information(this, tr("Show image"), tr("Cannot load %1.").arg(fileName));
}

imageLabel=new QLabel;
imageLabel->setBackgroundRole(QPalette::Base);
imageLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
imageLabel->setScaledContents(true);
imageLabel->setPixmap(QPixmap::fromImage(image));
scaleFactor=1.0;

scrollArea=new QScrollArea;
scrollArea->setBackgroundRole(QPalette::Dark);
scrollArea->setWidget(imageLabel);

buttonZoomIn=new QPushButton(tr("Zoom &In"));
QPushButton* buttonNormalSize=new QPushButton(tr("&Normal Size"));
buttonZoomOut=new QPushButton(tr("Zoom &Out"));
QPushButton* buttonClose=new QPushButton(tr("&Close"));
connect(buttonZoomIn, SIGNAL(clicked()), SLOT(slotZoomIn()));
connect(buttonNormalSize, SIGNAL(clicked()), SLOT(slotNormalSize()));
connect(buttonZoomOut, SIGNAL(clicked()), SLOT(slotZoomOut()));
connect(buttonClose, SIGNAL(clicked()), SLOT(accept()));
QHBoxLayout* buttonLayout=new QHBoxLayout;
buttonLayout->setMargin(5);
buttonLayout->addStretch(1);
buttonLayout->addWidget(buttonZoomIn);
buttonLayout->addWidget(buttonNormalSize);
buttonLayout->addWidget(buttonZoomOut);
buttonLayout->addStretch(1);
buttonLayout->addWidget(buttonClose);

QVBoxLayout* layout=new QVBoxLayout;
layout->setSpacing(5); layout->setMargin(5);
layout->addWidget(scrollArea);
layout->addLayout(buttonLayout);
setLayout(layout);
}

void ImageViewDialog::scaleImage(double factor)
{
scaleFactor*=factor;
imageLabel->resize(scaleFactor * imageLabel->pixmap()->size());

adjustScrollBar(scrollArea->horizontalScrollBar(), factor);
adjustScrollBar(scrollArea->verticalScrollBar(), factor);

buttonZoomIn->setEnabled(scaleFactor < 3.0);
buttonZoomOut->setEnabled(scaleFactor > 0.333);
}

void ImageViewDialog::adjustScrollBar(QScrollBar* scrollBar, double factor)
{
scrollBar->setValue(int(factor * scrollBar->value() + ((factor - 1) * scrollBar->pageStep()/2)));
}

void ImageViewDialog::slotZoomIn()
{
scaleImage(1.25);
}

void ImageViewDialog::slotNormalSize()
{
imageLabel->adjustSize();
scaleFactor=1.0;
buttonZoomIn->setEnabled(true);
buttonZoomOut->setEnabled(true);
}

void ImageViewDialog::slotZoomOut()
{
scaleImage(0.8);
}
надо чтобы при вызове диалога картинка гарантрованно помещалась в окне, т.е. чтобы небыло полос прокрутки QScrollArea. Пытался изменять размер и QScrollArea и QScrollArea::viewport() под размер QLabel в конструкторе - ничего не получалось.
Код:
scrollArea->resize(imageLabel->size());
Внизу картинки как есть и как должно быть


Название: Re: Подгонка QScrollArea под контент
Отправлено: shadone от Октябрь 19, 2008, 14:59
мне кажется что простейший вариант - вообще не использовать QScrollArea в данном случае - когда нужно отобразить картинку в реальном масштабе, без полос прокрутки просто использовать потомка QWidget, а когда пользователь хочет увеличить масштаб - добавить QScrollArea и переназначить родителя виджета.

По идее изменение размера виджета QScrollArea под размер viewport также должно работать, но надо пробовать. Что-то вроде scrollArea->resize(scrollArea->viewport()->size())

Кстати Cancel пишется так.


Название: Re: Подгонка QScrollArea под контент
Отправлено: Hort от Октябрь 19, 2008, 18:18
Оно то может и работает, но я так понимаю после вызова метода exec() все равно все выстраивается по своему.
Вот что я придумал:
Код:
	QSize size=imageLabel->size();
size.rheight()+=2*QApplication::style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
size.rwidth()+=2*QApplication::style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
scrollArea->setMinimumSize(size);
теперь все работает корректно, но надо теперь чтобы после вызова exec() minimumSize снимался, чтобы дать пользователю возможность уменьшить окно. Может кто-нибуть подскажет как это реализовать лучше всего?
ЗЫ спасибо за Cancel


Название: Re: Подгонка QScrollArea под контент
Отправлено: pastor от Октябрь 19, 2008, 18:35
2 Hort: Ты непробывал устанавливать свойство widgetResizable в true? Может подойдет такой вариант?

Цитировать
If this property is set to true, the scroll area will automatically resize the widget in order to avoid scroll bars where they can be avoided, or to take advantage of extra space


Название: Re: Подгонка QScrollArea под контент
Отправлено: Hort от Октябрь 19, 2008, 18:45
2 Hort: Ты непробывал устанавливать свойство widgetResizable в true? Может подойдет такой вариант?

Цитировать
If this property is set to true, the scroll area will automatically resize the widget in order to avoid scroll bars where they can be avoided, or to take advantage of extra space
не подходит - у меня изменяется размер виджета с рисунком (QLabel) при клацаньи на увеличить/уменьшить. при widgetResizable он будет уменьшаться до размерв QScrollArea и при этом не факт, что сохраняться пропорции картинки.
ключевой момент тут imageLabel->setScaledContents(true);
ЗЫ кто знает эвент какой или сигнал чтобы отловить виджет после exec()? или отлавливать наведение на окно мыши?


Название: Re: Подгонка QScrollArea под контент
Отправлено: EhTemka от Октябрь 20, 2008, 13:09
Цитировать
отлавливать наведение на окно мыши?
void QWidget::focusInEvent ( QFocusEvent * event )


Цитировать
чтобы после вызова exec() minimumSize снимался, чтобы дать пользователю возможность уменьшить окно. Может кто-нибуть подскажет как это реализовать лучше всего?

А почему бы после вызова ехес не вызывать функцию "съема" minimumSize?
Ведь ехес то известно где происходит...


Название: Re: Подгонка QScrollArea под контент
Отправлено: Alex Custov от Октябрь 20, 2008, 13:16
Цитировать
отлавливать наведение на окно мыши?
void QWidget::focusInEvent ( QFocusEvent * event )

focusInEvent - это клавиатурный фокус, а надо

void QWidget::enterEvent ( QEvent * event )


Название: Re: Подгонка QScrollArea под контент
Отправлено: EhTemka от Октябрь 20, 2008, 14:18
Цитировать
отлавливать наведение на окно мыши?
void QWidget::focusInEvent ( QFocusEvent * event )

focusInEvent - это клавиатурный фокус, а надо

void QWidget::enterEvent ( QEvent * event )

Ваша правда, извиняюсь  :)


Название: Re: Подгонка QScrollArea под контент
Отправлено: Hort от Октябрь 20, 2008, 14:36
А почему бы после вызова ехес не вызывать функцию "съема" minimumSize?
Ведь ехес то известно где происходит...
метод ехес останавлтвает выполнение кода пока не закроется окно. следовательно если выполнять после него - уже поздно, а если поставить перед - еще рано.
решил я это путем перегрузки для диалога showEvent( QShowEvent * )