Пример "Image Viewer"
|
![]() | ![]() | ![]() |
void ImageViewer::normalSize() { imageLabel->adjustSize(); scaleFactor = 1.0; }
При изменении масштаба мы используем возможность QLabel'а по масштабированию своего содержимого. Такое масштабирование не изменяет действующую подсказку размера содержимого. А поскольку функция adjustSize() использует эту подсказку размер, для восстановления обычного размера отображаемого в настоящий момент времени изображения на нужно только вызвать adjustSize() и сбросить коэффициент масштабирования в значение 1.0.
void ImageViewer::fitToWindow() { bool fitToWindow = fitToWindowAct->isChecked(); scrollArea->setWidgetResizable(fitToWindow); if (!fitToWindow) { normalSize(); } updateActions(); }
Слот fitToWindow() вызывается каждый раз, когда пользователь переключает опцию Fit to Window. Если слоты вызывается для включения опции, то мы сообщаем области прокрутки о необходимости изменить размер его дочернего виджета с помощью функции QScrollArea::setWidgetResizable(). Затем мы отключаем пункты меню Zoom In, Zoom Out и Normal Size, используя закрытую функцию updateActions().
Если свойство QScrollArea::widgetResizable имеет значение false (по умолчанию), область прокрутки соблюдает размер дочернего виджета. Если это свойство имеет значение true, область прокрутки будет автоматически изменять размер виджета с тем, чтобы избежать появления полос прокрутки там, где они не нужны, или для получения выгоды от дополнительного пространства. Но область прокрутки будет соблюдать минимальную подсказку размера дочернего виджета независимо от свойства изменения размера виджета. В этом примере мы установили политику размера imageLabel'а в значение ignored в конструкторе, чтобы избежать появления полос прокрутки когда область прокручивания становится меньше, чем минимальная подсказка размера метки.
Снимки экрана ниже показывают изображение обычного размера, а также несколько изображений с включённой опцией Fit to window. Увеличение размера окна растянет изображение, как показано на третьем снимке экрана.
![]() | ![]() | ![]() |
Если слот вызывается для отключения опции, свойство {QScrollArea::setWidgetResizable} примет значение false. Также мы восстановили исходный размер растрового изображения, подогнав размеры метки под её содержимое. И в заключение обновили пункты меню вид.
void ImageViewer::about() { QMessageBox::about(this, tr("About Image Viewer"), tr("<p>The <b>Image Viewer</b> example shows how to combine QLabel " "and QScrollArea to display an image. QLabel is typically used " "for displaying a text, but it can also display an image. " "QScrollArea provides a scrolling view around another widget. " "If the child widget exceeds the size of the frame, QScrollArea " "automatically provides scroll bars. </p><p>The example " "demonstrates how QLabel's ability to scale its contents " "(QLabel::scaledContents), and QScrollArea's ability to " "automatically resize its contents " "(QScrollArea::widgetResizable), can be used to implement " "zooming and scaling features. </p><p>In addition the example " "shows how to use QPainter to print an image.</p>")); }
Мы реализовали слот about() для создания окна сообщения, описывающего для чего спроектирован пример.
void ImageViewer::createActions() { openAct = new QAction(tr("&Open..."), this); openAct->setShortcut(tr("Ctrl+O")); connect(openAct, SIGNAL(triggered()), this, SLOT(open())); printAct = new QAction(tr("&Print..."), this); printAct->setShortcut(tr("Ctrl+P")); printAct->setEnabled(false); connect(printAct, SIGNAL(triggered()), this, SLOT(print())); exitAct = new QAction(tr("E&xit"), this); exitAct->setShortcut(tr("Ctrl+Q")); connect(exitAct, SIGNAL(triggered()), this, SLOT(close())); zoomInAct = new QAction(tr("Zoom &In (25%)"), this); zoomInAct->setShortcut(tr("Ctrl++")); zoomInAct->setEnabled(false); connect(zoomInAct, SIGNAL(triggered()), this, SLOT(zoomIn())); zoomOutAct = new QAction(tr("Zoom &Out (25%)"), this); zoomOutAct->setShortcut(tr("Ctrl+-")); zoomOutAct->setEnabled(false); connect(zoomOutAct, SIGNAL(triggered()), this, SLOT(zoomOut())); normalSizeAct = new QAction(tr("&Normal Size"), this); normalSizeAct->setShortcut(tr("Ctrl+S")); normalSizeAct->setEnabled(false); connect(normalSizeAct, SIGNAL(triggered()), this, SLOT(normalSize())); fitToWindowAct = new QAction(tr("&Fit to Window"), this); fitToWindowAct->setEnabled(false); fitToWindowAct->setCheckable(true); fitToWindowAct->setShortcut(tr("Ctrl+F")); connect(fitToWindowAct, SIGNAL(triggered()), this, SLOT(fitToWindow())); aboutAct = new QAction(tr("&About"), this); connect(aboutAct, SIGNAL(triggered()), this, SLOT(about())); aboutQtAct = new QAction(tr("About &Qt"), this); connect(aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt())); }
В закрытой функции createAction() мы создали действия, предоставляющие возможности приложения.
Мы назначили "быстрые" клавиши для всех действий и соединили их с соответствующими слотами. Включили только openAct и exitAxt во время создания, остальные обновили один раз после загрузки изображения в приложение. В дополнение мы сделали fitToWindowAct отмечаемым.
void ImageViewer::createMenus() { fileMenu = new QMenu(tr("&File"), this); fileMenu->addAction(openAct); fileMenu->addAction(printAct); fileMenu->addSeparator(); fileMenu->addAction(exitAct); viewMenu = new QMenu(tr("&View"), this); viewMenu->addAction(zoomInAct); viewMenu->addAction(zoomOutAct); viewMenu->addAction(normalSizeAct); viewMenu->addSeparator(); viewMenu->addAction(fitToWindowAct); helpMenu = new QMenu(tr("&Help"), this); helpMenu->addAction(aboutAct); helpMenu->addAction(aboutQtAct); menuBar()->addMenu(fileMenu); menuBar()->addMenu(viewMenu); menuBar()->addMenu(helpMenu); }
В закрытой функции createMenu(), добавили предварительно созданные действия для меню File, View и Help.
Класс QMenu предоставляет виджет меню для использования в панелях меню, контекстных меню и других всплывающих меню. Класс QMenuBar предоставляет панель горизонтального меню, содержащее список пунктов выпадающих меню. Поэтому в конце мы поместим меню в панель меню ImageViewer'а, который находим с помощью функции QMainWindow::menuBar().
void ImageViewer::updateActions() { zoomInAct->setEnabled(!fitToWindowAct->isChecked()); zoomOutAct->setEnabled(!fitToWindowAct->isChecked()); normalSizeAct->setEnabled(!fitToWindowAct->isChecked()); }
Закрытая функция updateActions() включает или выключает пункты меню Zoom In, Zoom Out и Normal Size, в зависимости от того, включена или отключена опция Fit to Window.
void ImageViewer::scaleImage(double factor) { Q_ASSERT(imageLabel->pixmap()); scaleFactor *= factor; imageLabel->resize(scaleFactor * imageLabel->pixmap()->size()); adjustScrollBar(scrollArea->horizontalScrollBar(), factor); adjustScrollBar(scrollArea->verticalScrollBar(), factor); zoomInAct->setEnabled(scaleFactor < 3.0); zoomOutAct->setEnabled(scaleFactor > 0.333); }
В scaleImage() используем параметр factor для вычисления нового коэффициента масштабирования для выводимого на экран изображения, и изменяем размер imageLabel. Так как в конструкторе установили свойство scaledContents в значение true, то вызов QWidget::resize() изменит масштаб изображения отображаемого в метке. Также мы подгоняем полосы прокрутки так, чтобы сохранить фокус на изображении.
В заключение, если коэффициент масштабирования меньше чем 33.3% или больше чем 300%, отключаем соответствующий пункт меню чтобы предотвратить излишнее увеличение растрового изображения, захватывающего слишком много ресурсов в оконной системе.
void ImageViewer::adjustScrollBar(QScrollBar *scrollBar, double factor) { scrollBar->setValue(int(factor * scrollBar->value() + ((factor - 1) * scrollBar->pageStep()/2))); }
Всякий раз когда увеличивается или уменьшается масштаб нам в результате нужно подгонять полосы прокрутки. Заманчиво делать это простым вызовом
scrollBar->setValue(int(factor * scrollBar->value()));
но это сделает точкой фокуса верхний левый угол, а не центр. По этой причине нам нужно принимать во внимание размер метки-манипулятор полосы прокрутки (прокрутка на страницу).
Copyright © 2009 Nokia Corporation and/or its subsidiary(-ies) | Торговые марки | Qt 4.5.3 |
Попытка перевода Qt документации. Если есть желание присоединиться, или если есть замечания или пожелания, то заходите на форум: Перевод Qt документации на русский язык... Люди внесшие вклад в перевод: Команда переводчиков |