450 likes | 533 Views
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!" );
E N D
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( intargc, char **argv ) { QApplication app( argc, argv ); QLabel l( "Hello World!" ); l.show(); return app.exec(); }
Scribble – a “Complete” app • SubclassingQMainWindow • Creating Menus and Toolbars • Implementing the File Menu • Using Dialogs • Splash Screens • Storing Settings • Status Bar A live demo!
Create an Qt Application XScribble
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.
Creating Toolbar Drag and Drop
Implementing the File Menu “actionSave”--Signals & Slots public slots: If the slot you wanted is a default slot of the recever
Implement Action - actionLine enumDrawFlag { NONE, LINE, CIRCLE }; public slots: voidsaveFile(); voidflagLine(){m_drawFlag=LINE; } voidflagCircle(){ m_drawFlag=CIRCLE; } connect( ui.actionLine, SIGNAL(triggered()), this, SLOT(flagLine()) ); connect( ui.actionCircle, SIGNAL(triggered()), this, SLOT(flagCircle()) );
Scribble!! protected: voidmousePressEvent(QMouseEvent *event); voidmouseMoveEvent(QMouseEvent *event); voidmouseReleaseEvent(QMouseEvent *event); voidpaintEvent(QPaintEvent *event);
Mouse Events voidScribbleArea::mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { m_lastPoint = event->pos(); } } voidScribbleArea::mouseMoveEvent(QMouseEvent *event) { if ((event->buttons() & Qt::LeftButton) ) { switch(m_drawFlag) { case FREE: drawFree( event->pos()); break; } } }
drawFree( constQPoint& pt) voidScribbleArea::paintEvent(QPaintEvent *event) { QPainter painter(this); QRectdirtyRect = event->rect(); painter.drawImage(dirtyRect, m_image, dirtyRect); } voidScribbleArea::drawFree(constQPoint& 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 properly voidScribbleArea::resizeEvent(QResizeEvent *event){ if (width() > m_image.width() || height() > m_image.height()) { intnewWidth = qMax(width() + 128, m_image.width()); intnewHeight = qMax(height() + 128, m_image.height()); resizeImage(&m_image, QSize(newWidth, newHeight)); update(); } QWidget::resizeEvent(event); } voidScribbleArea::resizeImage(QImage *image, constQSize &newSize){ if (image->size() == newSize) return; QImagenewImage(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? voidScribbleArea::drawFree(constQPoint& 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
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 pen void ScribbleArea::setPenColor() { QColoroldColor = m_pen.color(); QColor color = QColorDialog::getColor(oldColor, this); m_pen.setColor(color); }
Open an Image 1 XScribble::XScribble(QWidget *parent, Qt::WFlags flags) { … connect( ui.actionOpen, SIGNAL(triggered()), this, SLOT(openFile())); … } void XScribble::openFile(){ if (maybeSave()) { QStringfileName = QFileDialog::getOpenFileName(this, tr("Open File"), QDir::currentPath()); if (!fileName.isEmpty()) ui.centralWidget->openImage(fileName); } }
Open an Image 2 boolXScribble::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 3 boolScribbleArea::openImage(constQString &fileName) { QImageloadedImage; if (!loadedImage.load(fileName)) return false; // union of loadedImage.size() & ScribbleArea's size. QSizenewSize = 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(QByteArrayformat, 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()); QByteArrayfileFormat = action->data().toByteArray(); saveFile(fileFormat); }
Save Your Scribble 3 boolXScribble::saveFile(constQByteArray &fileFormat) { QStringinitialPath = QDir::currentPath() + "/untitled." + fileFormat; QStringfileName = 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 boolScribbleArea::saveImage(constQString &fileName, const char *fileFormat) { if (m_image.save(fileName, fileFormat)) { m_modified = false; return true; } else { return false; } }
Splash Screens Add splash.png into the resource by QT Designer intmain(intargc, char *argv[]){ QApplication a(argc, argv); QPixmappixmap(":/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 settings void XScribble::readSettings() { QSettings settings("Ability Co.Ltd.", "XScribble"); QRectrect = 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(); }
boolisNotExists(constQString& elem) //functor { bool result = QFile::exists(elem); return !result; } • 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()); • }
void XScribble::open(){ … m_recentFiles.removeAll(fileName); ... } void XScribble::openRecentFile(){ if (maybeSave()) { QAction *action = qobject_cast<QAction *>(sender()); if (action) { QStringfileName(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())); } … }
Storing Settings – write settings protected: 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 Bar • void 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) • { • QStringtmp = "scribble tools changed to: " + action->data().toString(); • m_statusLabel->setText( tmp); • } • }
More Widgets on Toolbar • todo
References • C++ GUI Programming with Qt4