不知道你有沒有發現,我們這個看圖軟體目前有個使用體驗上的問題?
就是這個看圖軟體的「視窗尺寸」是跟著「圖片尺寸」變動的。圖片很大的時候,視窗尺寸就變很大,圖片很小張的時候,視窗尺寸就變很小。
如果載入了一張超級大的圖片,比螢幕的尺寸還要大,視窗也會變得超大,邊緣超出螢幕的可視範圍,很麻煩!
我們今天就來實現「捲動區域 ScrollArea」這個功能。當視窗需要顯示的內容過長、過大時,兩旁會顯示出「滾動條 ScrollBar」,這樣,視窗就不需要超出螢幕範圍,使用者也可適當的調整他想瀏覽的圖片區域囉!
捲動區域在 Qt 裡面叫做 QScrollBar。QScrollArea 也是個 QWidget,只是它本身不顯示東西,相對的,它有一個成員函數叫做 QScrollBar::setWidget()
可以設置內部圖形元件。
當內部圖形元件的內容尺寸大於它的父元件尺寸時,ScrollArea 就會自動秀出垂直或水平捲動條,讓使用者可以在比較小的空間瀏覽部份內容。
接下來就來寫程式吧!請打開昨天的專案:
我們先到 MainWindow 增加一個成員變數 QScrollArea* m_scrollArea
(別忘了引入 #include<QScrollArea>
標頭檔)
class MainWindow : public QMainWindow
{
...
QLabel* m_imageLabel = nullptr;
QScrollArea* m_scrollArea = nullptr; // 增加 ScrollArea
接著我們到 MainWindow 的建構子,把開頭改寫如下。把 Central Widget 由原本的 m_imageLabel 改成 m_scrollArea,然後再把圖片標籤 m_imageLabel 設置成捲動區域的內部圖形元件:
MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent)
{
m_imageLabel = new QLabel(this);
m_imageLabel->setBackgroundRole(QPalette::Base);
m_scrollArea = new QScrollArea(this);
m_scrollArea->setBackgroundRole(QPalette::Dark);
m_scrollArea->setWidget(m_imageLabel);
setCentralWidget(m_scrollArea);
...
resize(QGuiApplication::primaryScreen()->availableSize() * 3 / 5);
}
最後我們加上一行resize(QGuiApplication::primaryScreen()->availableSize() * 3 / 5);
調整一下看圖軟體的視窗初始大小,佔螢幕的五分之三尺寸這麼大。
捲動區域的初始設定就做好了。
接著我們還需要做一件事。在讀取圖片時,設定 m_imageLabel 的尺寸:
void MainWindow::loadImage(const QString& fileName)
{
QImageReader reader(fileName);
reader.setAutoTransform(true);
const QImage newImage = reader.read();
Q_ASSERT(!newImage.isNull());
m_imageLabel->setPixmap(QPixmap::fromImage(newImage));
m_imageLabel->resize(newImage.size()); // <= 加上這一行!
...
因為 m_imageLabel 位於捲動區域內的關係,它已經沒辦法根據父元件自動適應視窗大小(畢竟捲動區域內可以是無限大嘛), 所以我們需要手動指定圖片標籤的尺寸 m_imageLabel->resize(newImage.size());
這樣子就完成囉,試著讀取一張超大圖片,你看到捲動條了嗎?