For this exercise we will use QtCreator to design a simple image viewer. Make sure you have a qtImage directory in your w01-intro folder.
Complete the QtCreator Initial Setup if you have not already done so.
Run qtcreator then File->Open File or Project select the file ~/cs40/examples/CMakeLists.txt
Click on the computer icon in the lower left and set the running application to qtimgtest. Click the green arrow to build and run this application. A simple window should pop up.
click on mainwindow.ui in w01-intro/qtimage directory in QtCreator. The UI editor will open. Here you can add widgets and adjust the layout.
In the upper right corner, select the MainWindow widget. You can edit this widget's properties in the lower right menu. Find the windowTitle property and change it to "My First Qt App". Run the question green arrow again and see that the title has changed.
Window to something visible (I use green in this example)
MyImageBox and have it inherit from QWidget
None for version control. We'll do this manually later.
myimagebox.h and myimagebox.cpp to the qtimage/CMakeLists.txt file with the other filenames in target_sources
MyImageBox
Graphical user interfaces such as Qt have event handling mechanisms to process events like keypresses, mouse clicks, and menu selection. In Qt, this mechanism uses slots and signals. Events emit signals which can then be sent to slots.
open() slot to the green widget.
clicked() signal to the open() slot.
clicked() signal to the close() slot. You may need to click the "Show signals and slots inherited from QWidget" box to see the close() slot for the MainWindow.
Add functionality to myimagebox.h
#include <QtWidgets>
...
public slots:
    void open();
private:
    QLabel *imageLabel;
    QScrollArea *scrollArea;
    QGridLayout *layout;
Implement in myimagebox.cpp
MyImageBox::MyImageBox(QWidget *parent) :
    QWidget(parent)
{
   imageLabel = new QLabel();
   scrollArea = new QScrollArea(this);
   scrollArea->setWidget(imageLabel);
   layout = new QGridLayout();
   layout->setContentsMargins(0,0,0,0);
   layout->addWidget(scrollArea);
   setLayout(layout);
}
void MyImageBox::open() {
  QString fileName = QFileDialog::getOpenFileName(this,
                                   "Open File", QDir::currentPath());
   if (!fileName.isEmpty()) {
     QImage image(fileName);
     if (image.isNull()) {
       QMessageBox msgBox;
       msgBox.setText(QString("Cannot load %1.").arg(fileName));
       msgBox.setIcon(QMessageBox::Information);
       msgBox.setWindowTitle("Image Viewer Load Error");
       msgBox.exec();
       return;
     }
     imageLabel->setPixmap(QPixmap::fromImage(image));
     imageLabel->adjustSize();
   }
}
Compile, Debug, Run, Test, Ponies!
Check the status of your source in git and update/commit and push your changes
Don't worry about understanding every single line of code at this point. There are a few main takeaways to focus on at this point.
signal and public slots: code in Qt C++ programs, this is not standard C++, and some special Qt and compiler magic happens behind the scenes to make this work.  The strange floating Q_OBJECT is also part of this magic.
Below are some of the classes used in this demo. You don't need to memorize any of these as you can always refer back to the documentation, but some we will be using more often than others.