Introduction to C C Lecture 8 GUI QT













































- Slides: 45
Introduction to C & C++ Lecture 8 – GUI -- QT JJCAO
Hello world • L 1: 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 QMain. Window 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 QMain. Window
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 “action. Save” --Signals & Slots public slots: If the slot you wanted is a default slot of the recever
More Actions
Implement Action - action. Line enum Draw. Flag { NONE, LINE, CIRCLE }; public slots: void save. File(); void flag. Line(){m_draw. Flag=LINE; } void flag. Circle(){ m_draw. Flag=CIRCLE; } connect( ui. action. Line, SIGNAL(triggered()), this, SLOT(flag. Line()) ); connect( ui. action. Circle, SIGNAL(triggered()), this, SLOT(flag. Circle()) );
Current GUI
Where to Scribble?
Promotion
Scribble!! protected: void mouse. Press. Event(QMouse. Event *event); void mouse. Move. Event(QMouse. Event *event); void mouse. Release. Event(QMouse. Event *event); void paint. Event(QPaint. Event *event);
Mouse Events void Scribble. Area: : mouse. Press. Event(QMouse. Event *event) { if (event->button() == Qt: : Left. Button) { m_last. Point = event->pos(); } } void Scribble. Area: : mouse. Move. Event(QMouse. Event *event) { if ((event->buttons() & Qt: : Left. Button) ) { switch (m_draw. Flag) { case FREE: draw. Free( event->pos()); break; } } }
draw. Free( const QPoint& pt) void Scribble. Area: : paint. Event(QPaint. Event *event) { QPainter painter(this); QRect dirty. Rect = event->rect(); // Local re-paint to decrease flickering painter. draw. Image(dirty. Rect, m_image, dirty. Rect); } void Scribble. Area: : draw. Free(const QPoint& pt) { QPainter painter(&m_image); painter. set. Pen(QPen(m_pen. Color, m_pen. Width, Qt: : Solid. Line, Qt: : Round. Cap, Qt: : Round. Join)); painter. draw. Line(m_last. Point, pt); m_last. Point = pt; }
The m_image is not initialized properly void Scribble. Area: : resize. Event(QResize. Event *event){ if (width() > m_image. width() || height() > m_image. height()) { int new. Width = q. Max(width() + 128, m_image. width()); int new. Height = q. Max(height() + 128, m_image. height()); resize. Image(&m_image, QSize(new. Width, new. Height)); update(); } QWidget: : resize. Event(event); } void Scribble. Area: : resize. Image(QImage *image, const QSize &new. Size){ if (image->size() == new. Size) return; QImage new. Image(new. Size, QImage: : Format_RGB 32); new. Image. fill(q. Rgb(255, 255)); QPainter painter(&new. Image); painter. draw. Image(QPoint(0, 0), *image); *image = new. Image; }
Try! But nothing happens? • However if you switch the screen back from minimization, you find what you drew. • What happened? void Scribble. Area: : draw. Free(const QPoint& pt) { QPainter painter(&m_image); painter. set. Pen(QPen(m_pen. Color, m_pen. Width, Qt: : Solid. Line, Qt: : Round. Cap, Qt: : Round. Join)); painter. draw. Line(m_last. Point, pt); // update what you just drew int rad = (m_pen. Width / 2) + 2; update(QRect(m_last. Point, pt). normalized(). adjusted(-rad, +rad, +rad)); m_last. Point = pt; }
Finally worked, but? action. Free. Hand->set. Checkable(true); action. Free. Hand->set. Checked(true);
More • • Shortcut key Using Dialogs Splash Screens Storing Settings
Shortcut key
Key & Action
Setting the color of the pen Scribble. Area: : Scribble. Area(QWidget *parent) : QWidget(parent), m_draw. Flag(FREE) { ui. setup. Ui(this); set. Attribute(Qt: : WA_Static. Contents); } m_pen = QPen(Qt: : blue, 1, Qt: : Solid. Line, Qt: : Round. Cap, Qt: : Round. Join);
Setting the color of the pen void Scribble. Area: : set. Pen. Color() { QColor old. Color = m_pen. color(); QColor color = QColor. Dialog: : get. Color(old. Color, this); m_pen. set. Color(color); }
Open an Image 1 XScribble: : XScribble(QWidget *parent, Qt: : WFlags flags) { … connect( ui. action. Open, SIGNAL(triggered()), this, SLOT(open. File())); … } void XScribble: : open. File(){ if (maybe. Save()) { QString file. Name = QFile. Dialog: : get. Open. File. Name(this, tr("Open File"), QDir: : current. Path()); if (!file. Name. is. Empty()) ui. central. Widget->open. Image(file. Name); } }
Open an Image 2 bool XScribble: : maybe. Save() { if (ui. central. Widget->is. Modified()) { QMessage. Box: : Standard. Button ret; ret = QMessage. Box: : warning(this, tr("Scribble"), tr("The image has been modified. n" "Do you want to save your changes? "), QMessage. Box: : Save | QMessage. Box: : Discard| QMessage. Box: : Cancel); if (ret == QMessage. Box: : Save) { return save. File("png"); } else if (ret == QMessage. Box: : Cancel) { return false; } } return true; }
Open an Image 3 bool Scribble. Area: : open. Image(const QString &file. Name) { QImage loaded. Image; if (!loaded. Image. load(file. Name)) return false; // union of loaded. Image. size() & Scribble. Area's size. QSize new. Size = loaded. Image. size(). expanded. To(size()); resize. Image(&loaded. Image, new. Size); m_image = loaded. Image; m_modified = false; update(); return true; }
Save Your Scribble 1 void XScribble: : create. Actions(){ connect( ui. action. Open, SIGNAL(triggered()), this, SLOT(open())); foreach (QByte. Array format, QImage. Writer: : supported. Image. Formats()) { QString text = tr("%1. . . "). arg(QString(format). to. Upper()); QAction *action = new QAction(text, this); action->set. Data(format); connect(action, SIGNAL(triggered()), this, SLOT(save())); m_save. As. Acts. append(action); } … } QList<QAction *> m_save. As. Acts;
Save Your Scribble 2 void XScribble: : create. Menus() { m_save. As. Menu = new QMenu(tr("&Save As"), this); foreach (QAction *action, m_save. As. Acts) m_save. As. Menu->add. Action(action); ui. menu. File->add. Menu(m_save. As. Menu); // menu. File is Qmenu* } void XScribble: : save() { QAction *action = qobject_cast<QAction *>(sender()); QByte. Array file. Format = action->data(). to. Byte. Array(); save. File(file. Format); }
Save Your Scribble 3 bool XScribble: : save. File(const QByte. Array &file. Format) { QString initial. Path = QDir: : current. Path() + "/untitled. " + file. Format; QString file. Name = QFile. Dialog: : get. Save. File. Name(this, tr("Save As"), initial. Path, tr("%1 Files (*. %2); ; All Files (*)") . arg(QString(file. Format. to. Upper())) . arg(QString(file. Format))); if (file. Name. is. Empty()) { return false; } else { return ui. central. Widget->save. Image(file. Name, file. Format); } }
Save Your Scribble 4 bool Scribble. Area: : save. Image(const QString &file. Name, const char *file. Format) { if (m_image. save(file. Name, file. Format)) { m_modified = false; return true; } else { return false; } }
Splash Screens Add splash. png into the resource by QT Designer int main(int argc, char *argv[]){ QApplication a(argc, argv); QPixmap pixmap(": /XScribble/Resources/splash. png"); QSplash. Screen *splash = new QSplash. Screen(pixmap); splash->show(); splash->show. Message("Loaded modules"); q. App->process. Events(); splash->show. Message("Established connections"); q. App->process. Events(); } XScribble w; w. show(); return a. exec();
Storing Settings – read settings void XScribble: : read. Settings() { QSettings settings("Ability Co. Ltd. ", "XScribble"); QRect rect = settings. value("geometry", QRect(200, 400, 400)). to. Rect(); move(rect. top. Left()); resize(rect. size()); m_recent. Files=settings. value("recent. Files"). to. String. List(); update. Recent. File. Actions(); } XScribble: : XScribble(QWidget *parent, Qt: : WFlags flags): QMain. Window(parent, flags){ ui. setup. Ui(this); create. Actions(); create. Menus(); read. Settings(); }
bool is. Not. Exists(const QString& elem) //functor { bool result = QFile: : exists(elem); return !result; } void XScribble: : update. Recent. File. Actions() { m_recent. Files. erase( std: : remove_if(m_recent. Files. begin(), m_recent. Files. end(), is. Not. Exists), m_recent. Files. end() ); for (int j = 0; j < Max. Recent. Files; ++j) { if (j < m_recent. Files. count()) { QString text = tr("&%1 %2") . arg(j+1). arg(QFile. Info( m_recent. Files[j] ). file. Name()); m_recent. File. Actions[j]->set. Text(text); m_recent. File. Actions[j]->set. Data(m_recent. Files[j]); m_recent. File. Actions[j]->set. Visible(true); } else { m_recent. File. Actions[j]->set. Visible(false); } } m_separator. Action->set. Visible(!m_recent. Files. is. Empty()); }
void XScribble: : open. Recent. File(){ if (maybe. Save()) { QAction *action = qobject_cast<QAction *>(sender()); if (action) { QString file. Name(action->data(). to. String()); ui. central. Widget->open. Image(file. Name); void XScribble: : open(){ … m_recent. Files. remove. All(file. Name); . . . } m_recent. Files. remove. All(file. Name); m_recent. Files. prepend(file. Name); update. Recent. File. Actions(); set. Window. Title(tr("%1[*] - %2"). arg(QFile. Info(file. Name). file. Name()). arg(tr("Scribble"))); } } } void XScribble: : create. Actions(){ … for (int i = 0; i < Max. Recent. Files; ++i) { m_recent. File. Actions[i] = new QAction(this); m_recent. File. Actions[i]->set. Visible(false); connect (m_recent. File. Actions[i], SIGNAL(triggered()), this, SLOT(open. Recent. File())); } … }
Storing Settings – write settings protected: void close. Event(QClose. Event *event); // overriding 覆盖 void XScribble: : close. Event(QClose. Event *event){ if (maybe. Save()) { write. Settings(); event->accept(); } else { event->ignore(); } } void XScribble: : write. Settings(){ QSettings settings("Ability Co. Ltd. ", "XScribble"); settings. set. Value("geometry", geometry()); settings. set. Value("recent. Files", m_recent. Files); }
Status Bar void XScribble: : create. Status. Bar() { m_status. Label = new QLabel("Ready!"); m_status. Label->set. Alignment(Qt: : Align. HCenter); m_status. Label->set. Minimum. Size(m_status. Label->size. Hint()); ui. status. Bar->add. Widget( m_status. Label); connect( ui. action. Line, SIGNAL(triggered()), this, SLOT(update. Status. Bar()) ); connect( ui. action. Circle, SIGNAL(triggered()), this, SLOT(update. Status. Bar()) ); update. Status. Bar(); } void XScribble: : update. Status. Bar() { QAction *action = qobject_cast<QAction *>(sender()); if (action) { QString tmp = "scribble tools changed to: " + action->data(). to. String(); m_status. Label->set. Text( tmp); } }
More Widgets on Toolbar • todo
References • C++ GUI Programming with Qt 4