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

Preview:

Citation preview

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();}

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!

Create an Qt Application

XScribble

Subclassing QMainWindow

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.

Add Resources

Add Icon to Menu Item / Action

Creating Toolbar

Drag and Drop

Behind the Designer

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

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

public slots:

More Actions

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()) );

Current GUI

Where to Scribble?

Promotion

Scribble!!

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

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;

}    }}

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

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;}

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;}

Finally worked, but?

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

More

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

Shortcut key

Key & Action

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);

}

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

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

}

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); }}

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;}

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;}

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;

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);}

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);    }}

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;    }}

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();

}

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();

}

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;}

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);...}

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);}

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);

} }

More Widgets on Toolbar

• todo

References

• C++ GUI Programming with Qt4

Recommended