45
Introduction to C & C+ + Lecture 8 – GUI -- QT JJCAO

Introduction to C & C++ Lecture 8 – GUI -- QT JJCAO

Embed Size (px)

Citation preview

Page 1: Introduction to C & C++ Lecture 8 – GUI -- QT JJCAO

Introduction to C & C++

Lecture 8 – GUI -- QT

JJCAO

Page 2: Introduction to C & C++ Lecture 8 – GUI -- QT JJCAO

Hello world

• L1: The ideas behind Qt and live demo of Qt in Education

#include <QApplication>#include <QLabel>

int main( int argc, char **argv ){ QApplication app( argc, argv ); QLabel l( "Hello World!" ); l.show(); return app.exec();}

Page 3: Introduction to C & C++ Lecture 8 – GUI -- QT JJCAO

Scribble – a “Complete” app

• Subclassing QMainWindow• Creating Menus and Toolbars• Implementing the File Menu• Using Dialogs• Splash Screens• Storing Settings• Status Bar

A live demo!

Page 4: Introduction to C & C++ Lecture 8 – GUI -- QT JJCAO

Create an Qt Application

XScribble

Page 5: Introduction to C & C++ Lecture 8 – GUI -- QT JJCAO
Page 6: Introduction to C & C++ Lecture 8 – GUI -- QT JJCAO
Page 7: Introduction to C & C++ Lecture 8 – GUI -- QT JJCAO

Subclassing QMainWindow

Page 8: Introduction to C & C++ Lecture 8 – GUI -- QT JJCAO

Creating Menus

Double click “xscribble.ui” in the “Solution Explorer”Press Return or Enter to accept the new text, or press Escape to reject it.

Page 9: Introduction to C & C++ Lecture 8 – GUI -- QT JJCAO
Page 10: Introduction to C & C++ Lecture 8 – GUI -- QT JJCAO

Add Resources

Page 11: Introduction to C & C++ Lecture 8 – GUI -- QT JJCAO

Add Icon to Menu Item / Action

Page 12: Introduction to C & C++ Lecture 8 – GUI -- QT JJCAO

Creating Toolbar

Drag and Drop

Page 13: Introduction to C & C++ Lecture 8 – GUI -- QT JJCAO

Behind the Designer

Page 14: Introduction to C & C++ Lecture 8 – GUI -- QT JJCAO

Implementing the File Menu “actionSave”--Signals & Slots

If the slot you wanted is a default slot of the recever

public slots:

Page 15: Introduction to C & C++ Lecture 8 – GUI -- QT JJCAO

More Actions

Page 16: Introduction to C & C++ Lecture 8 – GUI -- QT JJCAO

Implement Action - actionLine

enum DrawFlag { NONE, LINE, CIRCLE};public slots:void saveFile();void flagLine(){m_drawFlag=LINE; }void flagCircle(){ m_drawFlag=CIRCLE; }

connect( ui.actionLine, SIGNAL(triggered()), this, SLOT(flagLine()) );connect( ui.actionCircle, SIGNAL(triggered()), this, SLOT(flagCircle()) );

Page 17: Introduction to C & C++ Lecture 8 – GUI -- QT JJCAO

Current GUI

Page 18: Introduction to C & C++ Lecture 8 – GUI -- QT JJCAO

Where to Scribble?

Page 19: Introduction to C & C++ Lecture 8 – GUI -- QT JJCAO

Promotion

Page 20: Introduction to C & C++ Lecture 8 – GUI -- QT JJCAO

Scribble!!

protected: void mousePressEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); void paintEvent(QPaintEvent *event);

Page 21: Introduction to C & C++ Lecture 8 – GUI -- QT JJCAO

Mouse Eventsvoid ScribbleArea::mousePressEvent(QMouseEvent *event){    if (event->button() == Qt::LeftButton) {        m_lastPoint = event->pos();    }}void ScribbleArea::mouseMoveEvent(QMouseEvent *event){    if ((event->buttons() & Qt::LeftButton) )    {

switch (m_drawFlag){case FREE:

drawFree( event->pos());break;

}    }}

Page 22: Introduction to C & C++ Lecture 8 – GUI -- QT JJCAO

drawFree( const QPoint& pt)void ScribbleArea::paintEvent(QPaintEvent *event){    QPainter painter(this);    QRect dirtyRect = event->rect();    painter.drawImage(dirtyRect, m_image, dirtyRect);}void ScribbleArea::drawFree(const QPoint& pt){    QPainter painter(&m_image);    painter.setPen(QPen(m_penColor, m_penWidth, Qt::SolidLine, Qt::RoundCap,                        Qt::RoundJoin));    painter.drawLine(m_lastPoint, pt);    m_lastPoint = pt;}

// Local re-paint to decrease flickering

Page 23: Introduction to C & C++ Lecture 8 – GUI -- QT JJCAO

The m_image is not initialized properlyvoid ScribbleArea::resizeEvent(QResizeEvent *event){    if (width() > m_image.width() || height() > m_image.height()) {        int newWidth = qMax(width() + 128, m_image.width());        int newHeight = qMax(height() + 128, m_image.height());        resizeImage(&m_image, QSize(newWidth, newHeight));        update();    }    QWidget::resizeEvent(event);}void ScribbleArea::resizeImage(QImage *image, const QSize &newSize){    if (image->size() == newSize)        return;    QImage newImage(newSize, QImage::Format_RGB32);    newImage.fill(qRgb(255, 255, 255));    QPainter painter(&newImage);    painter.drawImage(QPoint(0, 0), *image);    *image = newImage;}

Page 24: Introduction to C & C++ Lecture 8 – GUI -- QT JJCAO

Try! But nothing happens?

• However if you switch the screen back from minimization, you find what you drew.

• What happened?void ScribbleArea::drawFree(const QPoint& pt){    QPainter painter(&m_image);    painter.setPen(QPen(m_penColor, m_penWidth, Qt::SolidLine, Qt::RoundCap,                        Qt::RoundJoin));    painter.drawLine(m_lastPoint, pt);   // update what you just drew    int rad = (m_penWidth / 2) + 2;    update(QRect(m_lastPoint, pt).normalized().adjusted(-rad, -rad, +rad, +rad));

    m_lastPoint = pt;}

Page 25: Introduction to C & C++ Lecture 8 – GUI -- QT JJCAO

Finally worked, but?

actionFreeHand->setCheckable(true);actionFreeHand->setChecked(true);

Page 26: Introduction to C & C++ Lecture 8 – GUI -- QT JJCAO

More

• Shortcut key• Using Dialogs• Splash Screens• Storing Settings

Page 27: Introduction to C & C++ Lecture 8 – GUI -- QT JJCAO

Shortcut key

Page 28: Introduction to C & C++ Lecture 8 – GUI -- QT JJCAO

Key & Action

Page 29: Introduction to C & C++ Lecture 8 – GUI -- QT JJCAO

Setting the color of the pen

ScribbleArea::ScribbleArea(QWidget *parent): QWidget(parent), m_drawFlag(FREE){

ui.setupUi(this);

setAttribute(Qt::WA_StaticContents);

m_pen = QPen(Qt::blue, 1, Qt::SolidLine, Qt::RoundCap,Qt::RoundJoin);

}

Page 30: Introduction to C & C++ Lecture 8 – GUI -- QT JJCAO

Setting the color of the penvoid ScribbleArea::setPenColor(){

QColor oldColor = m_pen.color();QColor color = QColorDialog::getColor(oldColor, this);m_pen.setColor(color);

}

Page 31: Introduction to C & C++ Lecture 8 – GUI -- QT JJCAO

Open an Image 1XScribble::XScribble(QWidget *parent, Qt::WFlags flags) {

connect( ui.actionOpen, SIGNAL(triggered()), this, SLOT(openFile()));…

}

void XScribble::openFile(){ if (maybeSave()) { QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"), QDir::currentPath()); if (!fileName.isEmpty()) ui.centralWidget->openImage(fileName); }}

Page 32: Introduction to C & C++ Lecture 8 – GUI -- QT JJCAO

Open an Image 2bool XScribble::maybeSave(){ if (ui.centralWidget->isModified()) { QMessageBox::StandardButton ret; ret = QMessageBox::warning(this, tr("Scribble"), tr("The image has been modified.\n" "Do you want to save your changes?"), QMessageBox::Save | QMessageBox::Discard| QMessageBox::Cancel); if (ret == QMessageBox::Save) { return saveFile("png"); } else if (ret == QMessageBox::Cancel) { return false; } } return true;}

Page 33: Introduction to C & C++ Lecture 8 – GUI -- QT JJCAO

Open an Image 3bool ScribbleArea::openImage(const QString &fileName){ QImage loadedImage; if (!loadedImage.load(fileName)) return false;

// union of loadedImage.size() & ScribbleArea's size. QSize newSize = loadedImage.size().expandedTo(size()); resizeImage(&loadedImage, newSize); m_image = loadedImage; m_modified = false; update(); return true;}

Page 34: Introduction to C & C++ Lecture 8 – GUI -- QT JJCAO

Save Your Scribble 1

void XScribble::createActions(){connect( ui.actionOpen, SIGNAL(triggered()), this, SLOT(open()));

foreach (QByteArray format, QImageWriter::supportedImageFormats()) {QString text = tr("%1...").arg(QString(format).toUpper());

QAction *action = new QAction(text, this);action->setData(format);connect(action, SIGNAL(triggered()), this, SLOT(save()));m_saveAsActs.append(action);

}…}

QList<QAction *> m_saveAsActs;

Page 35: Introduction to C & C++ Lecture 8 – GUI -- QT JJCAO

Save Your Scribble 2

void XScribble::createMenus(){    m_saveAsMenu = new QMenu(tr("&Save As"), this);    foreach (QAction *action, m_saveAsActs)        m_saveAsMenu->addAction(action);        ui.menuFile->addMenu(m_saveAsMenu); // menuFile is Qmenu*}

void XScribble::save(){    QAction *action = qobject_cast<QAction *>(sender());    QByteArray fileFormat = action->data().toByteArray();    saveFile(fileFormat);}

Page 36: Introduction to C & C++ Lecture 8 – GUI -- QT JJCAO

Save Your Scribble 3

bool XScribble::saveFile(const QByteArray &fileFormat){    QString initialPath = QDir::currentPath() + "/untitled." + fileFormat;

    QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"),                               initialPath,                               tr("%1 Files (*.%2);;All Files (*)")                               .arg(QString(fileFormat.toUpper()))                               .arg(QString(fileFormat)));    if (fileName.isEmpty()) {        return false;    } else {        return ui.centralWidget->saveImage(fileName, fileFormat);    }}

Page 37: Introduction to C & C++ Lecture 8 – GUI -- QT JJCAO

Save Your Scribble 4

bool ScribbleArea::saveImage(const QString &fileName, const char *fileFormat){    if (m_image.save(fileName, fileFormat)) {        m_modified = false;        return true;    } else {        return false;    }}

Page 38: Introduction to C & C++ Lecture 8 – GUI -- QT JJCAO

Splash ScreensAdd splash.png into the resource by QT Designer

int main(int argc, char *argv[]){QApplication a(argc, argv);

QPixmap pixmap(":/XScribble/Resources/splash.png");QSplashScreen *splash = new QSplashScreen(pixmap);splash->show();splash->showMessage("Loaded modules");qApp->processEvents();splash->showMessage("Established connections");qApp->processEvents();

XScribble w;w.show();return a.exec();

}

Page 39: Introduction to C & C++ Lecture 8 – GUI -- QT JJCAO

Storing Settings – read settingsvoid XScribble::readSettings(){ QSettings settings("Ability Co.Ltd.", "XScribble"); QRect rect = settings.value("geometry", QRect(200,200, 400, 400)).toRect();

move(rect.topLeft()); resize(rect.size());

m_recentFiles=settings.value("recentFiles").toStringList(); updateRecentFileActions();}

XScribble::XScribble(QWidget *parent, Qt::WFlags flags): QMainWindow(parent, flags){ui.setupUi(this);createActions();createMenus();readSettings();

}

Page 40: Introduction to C & C++ Lecture 8 – GUI -- QT JJCAO

void XScribble::updateRecentFileActions(){ m_recentFiles.erase(

std::remove_if(m_recentFiles.begin(), m_recentFiles.end(), isNotExists), m_recentFiles.end()

); for (int j = 0; j < MaxRecentFiles; ++j) { if (j < m_recentFiles.count()) { QString text = tr("&%1 %2") .arg(j+1).arg(QFileInfo( m_recentFiles[j] ).fileName()); m_recentFileActions[j]->setText(text); m_recentFileActions[j]->setData(m_recentFiles[j]); m_recentFileActions[j]->setVisible(true); } else { m_recentFileActions[j]->setVisible(false); } } m_separatorAction->setVisible(!m_recentFiles.isEmpty());}

bool isNotExists(const QString& elem) //functor{bool result = QFile::exists(elem);return !result;}

Page 41: Introduction to C & C++ Lecture 8 – GUI -- QT JJCAO

void XScribble::openRecentFile(){ if (maybeSave()) { QAction *action = qobject_cast<QAction *>(sender()); if (action) {

QString fileName(action->data().toString());ui.centralWidget->openImage(fileName);

m_recentFiles.removeAll(fileName);m_recentFiles.prepend(fileName);updateRecentFileActions();setWindowTitle(tr("%1[*] - %2").arg(QFileInfo(fileName).fileName()).arg(tr("Scribble")));

} }} void XScribble::createActions(){

…for (int i = 0; i < MaxRecentFiles; ++i) { m_recentFileActions[i] = new QAction(this); m_recentFileActions[i]->setVisible(false); connect (m_recentFileActions[i], SIGNAL(triggered()), this, SLOT(openRecentFile())); }…}

void XScribble::open(){…m_recentFiles.removeAll(fileName);...}

Page 42: Introduction to C & C++ Lecture 8 – GUI -- QT JJCAO

Storing Settings – write settingsprotected: void closeEvent(QCloseEvent *event); // overriding 覆盖void XScribble::closeEvent(QCloseEvent *event){ if (maybeSave()) { writeSettings(); event->accept(); } else { event->ignore(); }}

void XScribble::writeSettings(){ QSettings settings("Ability Co.Ltd.", "XScribble");

settings.setValue("geometry", geometry()); settings.setValue("recentFiles", m_recentFiles);}

Page 43: Introduction to C & C++ Lecture 8 – GUI -- QT JJCAO

Status Barvoid XScribble::createStatusBar(){ m_statusLabel = new QLabel("Ready!"); m_statusLabel->setAlignment(Qt::AlignHCenter); m_statusLabel->setMinimumSize(m_statusLabel->sizeHint());

ui.statusBar->addWidget( m_statusLabel);

connect( ui.actionLine, SIGNAL(triggered()), this, SLOT(updateStatusBar()) ); connect( ui.actionCircle, SIGNAL(triggered()), this, SLOT(updateStatusBar()) );

updateStatusBar();}void XScribble::updateStatusBar(){

QAction *action = qobject_cast<QAction *>(sender());if (action){

QString tmp = "scribble tools changed to: " + action->data().toString();m_statusLabel->setText( tmp);

} }

Page 44: Introduction to C & C++ Lecture 8 – GUI -- QT JJCAO

More Widgets on Toolbar

• todo

Page 45: Introduction to C & C++ Lecture 8 – GUI -- QT JJCAO

References

• C++ GUI Programming with Qt4