Presentation is loading. Please wait.

Presentation is loading. Please wait.

QT – Dialog C++ GUI Programming with Qt 4 Qt 4.5 Reference Documentation Blanchette and Summerfield, Ch. 3.

Similar presentations


Presentation on theme: "QT – Dialog C++ GUI Programming with Qt 4 Qt 4.5 Reference Documentation Blanchette and Summerfield, Ch. 3."— Presentation transcript:

1 QT – Dialog C++ GUI Programming with Qt 4 Qt 4.5 Reference Documentation Blanchette and Summerfield, Ch. 3

2 Overview Another example of essential Qt concepts – Addressbook tutorial Qt – “main window” Subclassing – many “actions” / methods Menus, tool bars –Selection of item creates action, using signals and slots Implementing functionality – in actions “Context menus – right button Modal vs. modeless dialogs

3 Another Example Another example of essential Qt concepts Tutorial – address book –Qt 4.5 Reference Documentation Essentially all of the elements of Qt programming needed Today, for review will look at first part of the tutorial example –Files organization –Class definition –Widgets (labels and text input fields) –Layout

4 Addressbook Subclass & Widgets Addressbook will be subclass of QWidget Widgets (elements) QLabel objects –nameLabel, addresslabel Input fields – objects –QLineEdit: nameLine –QTextEdit: addressText

5 Files c/c++, use files to organize implementation addressbook.h –definition file for AddressBook class addressbook.cpp –implementation file for AddressBook class main.cpp –main() function, with an instance of AddressBook.

6 addressbook.h Defines the AddressBook Class #include class QLabel; class QLineEdit; class QTextEdit; class AddressBook : public QWidget // Declare AddressBook subclass of QWidget { Q_OBJECT // Qt macro for signals and slots, etc. public: AddressBook (QWidget *parent = 0); private: QLineEdit *nameLine; // Declare private instance of QLineEdit QTextEdit *addressText; // “ QTextEdit };

7 addressbook.cpp – Part 1 Implements addressbook class // Will declare local objects and create layout in Part 1 // Part 2 will implement functionality (more next week) #include #include "addressbook.h" // Constructor of AddressBook accepts QWidget // parent AddressBook::AddressBook(QWidget *parent) : QWidget(parent) { // declare local objects QLabel *nameLabel = new QLabel(tr("Name:")); nameLine = new QLineEdit; QLabel *addressLabel = new QLabel(tr("Address:")); addressText = new QTextEdit;

8 addressbook.cpp Implements addressbook class // Create layout // Here, use GridLayout (BoxLayout last time) // divides space into grid with row and col nums GridLayout *mainLayout = new QGridLayout; mainLayout->addWidget(nameLabel, 0, 0); mainLayout->addWidget(nameLine, 0, 1); mainLayout->addWidget(addressLabel, 1, 0, Qt::AlignTop); mainLayout->addWidget(addressText, 1, 1); // Invode layout widget’s setLayout function to install objects setLayout(mainLayout); setWindowTitle(tr("Simple Address Book")); }

9 Main.cpp “executes” Qt application // Instantiates a Qapplication object, here, app // Qapplication manages application-wide resources, e.g., font, cursor, and runs event loop // int main(int argc, char *argv[]) { QApplication app(argc, argv); // Construct new AddressBook widget on heap with new keyword AddressBook *addressBook = new AddressBook; // Display the widget, when the application’s event loop is started addressBook->show(); // Start the event loop return app.exec(); }

10 addressbook.cpp – Part 2 Implements addressbook class – 1. add labels and buttons #include #include "addressbook.h" AddressBook::AddressBook(QWidget *parent) : QWidget(parent) { QLabel *nameLabel = new QLabel(tr("Name:")); nameLine = new QLineEdit; nameLine->setReadOnly(true); QLabel *addressLabel = new QLabel(tr("Address:")); addressText = new QTextEdit; addressText->setReadOnly(true); addButton = new QPushButton(tr("&Add")); addButton->show(); submitButton = new QPushButton(tr("&Submit")); submitButton->hide(); cancelButton = new QPushButton(tr("&Cancel")); cancelButton->hide();

11 addressbook.cpp – Part 2 Implements addressbook class – 2. Connect signals and slots // As we’ve seen widgets can emit signals, // which then invoke methods connect(addButton, SIGNAL(clicked()), this, SLOT(addContact())); connect(submitButton, SIGNAL(clicked()), this, SLOT(submitContact())); connect(cancelButton, SIGNAL(clicked()), this, SLOT(cancel()));

12 addressbook.cpp – Part 2 Implements addressbook class – 3. Add buttons & create layout QGridLayout *mainLayout = new QGridLayout; mainLayout->addWidget(nameLabel, 0, 0); mainLayout->addWidget(nameLine, 0, 1); mainLayout->addWidget(addressLabel, 1, 0, Qt::AlignTop); mainLayout->addWidget(addressText, 1, 1); mainLayout->addLayout(buttonLayout1, 1, 2); setLayout(mainLayout); setWindowTitle(tr("Simple Address Book")); }

13 Rest of AddressBook Tutorial Rest of tutorial adds more buttons (easy enough) Also, adds substantial functionality to methods invoked when a button is clicked (and emits the clicked signal) –E.g., inserting names in list, searching for duplicates Adding such functionality will be covered next week This week – main windows

14 Main Windows For Qt (and other systems) “main window” refers to a kind of “executive” control and coordination of elements –Dialogs, menus, tool bars, status bars After this, final essential that remains is to look carefully at implementation of application functionality – Ch. 4, next week Blanchette and Summerfield build on spreadsheet dialogs

15 Creating Application’s Main Window Subclassing QMainWindow // mainwindow.h - Create main window as subclass of QMainWindow #include class QAction; class QLabel; class FindDialog; class Spreadsheet; class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = 0, const char *name = 0); protected: void closeEvent(QCloseEvent *event);// reimplement to modify void contextMenuEvent(QContextMenuEvent *event);// “ right-click menu

16 mainwindow.h, 2 Subclassing QMainWindow – Slots for menu options // Most menu options are implemented as private slots (methods, functions) in MainWindow private slots: void newFile(); void open(); bool save(); bool saveAs(); void find(); void goToCell(); void sort(); void about();

17 mainwindow.h, 3 Subclassing QMainWindow – More slots void updateCellIndicators(); void spreadsheetModified(); void openRecentFile(int param); private: void createActions(); void createMenus(); void createToolBars(); void createStatusBar(); void readSettings(); void writeSettings(); bool maybeSave(); void loadFile(const QString &fileName); void saveFile(const QString &fileName); void setCurrentFile(const QString &fileName); void updateRecentFileItems(); QString strippedName(const QString &fullFileName);

18 mainwindow.h, 4 Subclassing QMainWindow – More slots – to support UI Spreadsheet *spreadsheet; FindDialog *findDialog; QLabel *locationLabel; QLabel *formulaLabel; QLabel *modLabel; QStringList recentFiles; QString curFile; QString fileFilters; bool modified; enum { MaxRecentFiles = 5 }; int recentFileIds[MaxRecentFiles]; QPopupMenu *fileMenu; QPopupMenu *editMenu; QPopupMenu *selectSubMenu; QPopupMenu *toolsMenu; QPopupMenu *optionsMenu; QPopupMenu *helpMenu; QToolBar *fileToolBar; QToolBar *editToolBar; QAction *newAct; QAction *openAct; QAction *saveAct; ··· QAction *aboutAct; QAction *aboutQtAct; };

19 And that’s all there is to mainwindow.h! … and mainwindow.cpp holds the implementation

20 mainwindow.cpp “implementation” MainWindow::MainWindow(QWidget *parent, const char *name) : QMainWindow(parent, name) { // Below creates spreadsheet widget and it’s constituent widgets spreadsheet = new Spreadsheet(this); // class to be defined later setCentralWidget(spreadsheet); createActions(); createMenus(); createToolBars(); createStatusBar(); readSettings(); setCaption(tr("Spreadsheet")); setIcon(QPixmap::fromMimeSource("icon.png")); findDialog = 0; fileFilters = tr("Spreadsheet files (*.sp)"); modified = false; }

21 mainwindow.cpp creating menu and toolbar elements, and actions A Qt “action” is item that can be added to menu or toolbar To create menus and toolbars in Qt: –Create actions –Add actions to menus –Add actions to toolbars Below is Qt-ese for the menu element “New”: void MainWindow::createActions() { newAct = new QAction(tr("&New"), tr("Ctrl+N"), this); newAct->setIconSet(QPixmap::fromMimeSource("new.png")); newAct->setStatusTip(tr("Create a new spreadsheet file")); connect(newAct, SIGNAL(activated()), this, SLOT(newFile()));

22 mainwindow.cpp creating menu and toolbar elements, and actions, 2 // Show Grid is toggle (Boolean) and rendered with check mark showGridAct = new QAction(tr("&Show Grid"), 0, this); showGridAct->setToggleAction(true); showGridAct->setOn(spreadsheet->showGrid()); showGridAct->setStatusTip(tr("Show or hide spreadsheet "grid")); connect(showGridAct, SIGNAL(toggled(bool)), spreadsheet, SLOT(setShowGrid(bool))); // So, for “About”, should be familiar now aboutQtAct = new QAction(tr("About &Qt"), 0, this); aboutQtAct->setStatusTip(tr("Show the Qt library’s About box")); connect(aboutQtAct, SIGNAL(activated()), qApp, SLOT(aboutQt())); } // Have now created all actions

23 mainwindow.cpp Building the menu system, “File” Actions are invoked through menu system –All menus are instances of QPopupMenu void MainWindow::createMenus() { fileMenu = new QPopupMenu(this);// Create file menu newAct->addTo(fileMenu);// Add “actions” to it openAct->addTo(fileMenu); saveAct->addTo(fileMenu); saveAsAct->addTo(fileMenu); fileMenu->insertSeparator(); exitAct->addTo(fileMenu); for (int i = 0; i < MaxRecentFiles; ++i) recentFileIds[i] = -1;

24 mainwindow.cpp Building the menu system, “Edit” Edit menu includes a submenu, otherwise, “same song, 2 nd …” –Submenu simply has parent and inserted where it is to appear editMenu = new QPopupMenu(this); cutAct->addTo(editMenu); copyAct->addTo(editMenu); pasteAct->addTo(editMenu); deleteAct->addTo(editMenu); selectSubMenu = new QPopupMenu(this); selectRowAct->addTo(selectSubMenu); selectColumnAct->addTo(selectSubMenu); selectAllAct->addTo(selectSubMenu); editMenu->insertItem(tr("&Select"), selectSubMenu);// submenu editMenu->insertSeparator(); findAct->addTo(editMenu); goToCellAct->addTo(editMenu);

25 mainwindow.cpp toolbars Creating toolbars is very similar to creating menus: void MainWindow::createToolBars() { fileToolBar = new QToolBar(tr("File"), this); newAct->addTo(fileToolBar); openAct->addTo(fileToolBar); saveAct->addTo(fileToolBar); editToolBar = new QToolBar(tr("Edit"), this); cutAct->addTo(editToolBar); copyAct->addTo(editToolBar); pasteAct->addTo(editToolBar); editToolBar->addSeparator(); findAct->addTo(editToolBar); goToCellAct->addTo(editToolBar); }

26 mainwindow.cpp context menu, creating User right mouse button Reimplement QWidget :: contextMenuEvent void MainWindow::contextMenuEvent(QContextMenuEvent *event) { QPopupMenu contextMenu(this); cutAct->addTo(&contextMenu); copyAct->addTo(&contextMenu); pasteAct->addTo(&contextMenu); // “exec” causes to be shown at loc contextMenu.exec(event->globalPos()); }

27 mainwindow.cpp context menu, event handling “Events are generated by Qt’s kernel to report mouse clicks, key presses, resize requests, and similar occurrences.” –As noted, will reimplement QWidget :: contextMenuEvent to handle event QPopupMenu *contextMenu = new QPopupMenu(this); cutAct->addTo(contextMenu); copyAct->addTo(contextMenu); pasteAct->addTo(contextMenu); contextMenu->exec(event->globalPos()); delete contextMenu;

28 Implementing Functionality What happens when menu item selected? Recall, basic control structure - when user selects a menu item, slot/member-function is called “New” newAct = new QAction(tr("&New"), tr("Ctrl+N"), this); newAct->setIconSet(QPixmap::fromMimeSource("new.png")); newAct->setStatusTip(tr("Create a new spreadsheet file")); connect(newAct, SIGNAL(activated()), this, SLOT(newFile())); “About” aboutQtAct = new QAction(tr("About &Qt"), 0, this); aboutQtAct->setStatusTip(tr("Show the Qt library’s About box")); connect(aboutQtAct, SIGNAL(activated()), qApp, SLOT(aboutQt()));

29 Implementing Functionality What happens when menu item selected? Functionality can be simple or complex –In fact, here, newFile implementation is as was Petzold’s – complex and rich –Will leave it to student to master such topics, as interest dictates –Today, getting feel for program elements, structure, and interactions is goal Functionality “built in”, e.g., “About” –connect(aboutQtAct, SIGNAL(activated()), qApp, SLOT(aboutQt())); –QMessageBox::about() - a “convenience function” void MainWindow::about() { QMessageBox::about(this, tr("About Spreadsheet"), tr(" Spreadsheet 1.0 " " Copyright © 2003 Software Inc." " Spreadsheet is a small application that " "demonstrates QAction, QMainWindow, " " QMenuBar, QStatusBar, " " QToolBar, and many other Qt classes.")); }

30 Using Dialogs How to create, initialize, execute, and respond to choices Dialog (window) “modes” –Modeless: executes independently of other windows –Modal: executes (pops up) when invoked and nothing else executes until closed Qt dialogs and typical user action handling –Modeless Have their signals connected to slots that respond to user action Invoked using show() –Modal Handle user action within dialog, no signals and slots Invoked using exec()

31 Recall, findDialog

32 Define finddialog slots, or functions // Called when user clicks Find button, emits signal findPrevious() or findNext void FindDialog ::findClicked() { QString text = lineEdit->text(); Qt::CaseSensitivity cs = caseCheckBox->isChecked() ? Qt::CaseSensitive : Qt::CaseInsensitive; if (backwardCheckBox->isChecked()) { emit findPrevious(text, cs); } else { emit findNext(text, cs);// emit keyword (macro) specific to Qt } // Called whenever user changes text in line editor, enables button if there is text in line editor void FindDialog::enableFindButton(const QString &text) { findButton->setEnabled (!text.isEmpty ()); }

33 A Modeless Dialog (box, window) findDialog - window (dialog) that enables user to search for text –Invoked when user clicks Edit|Find to “pop up” (execute) Find dialog (box) –Recall functionality implemented in last chapter –Basically, “just run it” void MainWindow::find() { if (!findDialog) { // if 1 st execution findDialog = new FindDialog(this); connect(findDialog, SIGNAL(findNext(const QString &, bool)), spreadsheet, SLOT(findNext(const QString &, bool))); connect(findDialog, SIGNAL(findPrev(const QString &, bool)), spreadsheet, SLOT(findPrev(const QString &, bool))); } findDialog->show();// make not hidden (if so) findDialog->raise();// may need to bring from “underneath” other wins findDialog->setActiveWindow();// make active (color title bar, give focus, etc.) }

34 A Modal Dialog When invoke modal dialogs using exec(), typically don’t need to set up any signal-slot connection Qdialog::exec() returns true, if dialog accepted, false otherwise –GoToCellDialog - Created with Designer in Ch. 2 –OK was connected to accept(), Cancel to reject() –Will need to essentially implement all functionality void MainWindow::goToCell() { GoToCellDialog dialog(this); if (dialog.exec()) { QString str = dialog.lineEdit->text();// get text from input widget spreadsheet->setCurrentCell(str.mid(1).toInt() - 1,// set… defined in program str[0].upper().unicode() - ’A’); }

35 Other Dialogs for Spreadsheet Many examples provided in chapter Some straightforward Some arcane When in doubt … keep it simple

36 Qt – Functionality, Custom Widgets Blanchette and Summerfield, Ch. 4,5

37 Overview Another example of essential Qt concepts – “Application Example” –Help > Qt Reference Documentation > Qt Examples > Application Example (in 2 nd pp) Class definition in.h: –For application’s menus, toolbars, slots, function Create (implement) in.cpp: –Menus, toolbars, status bar –Qt “actions” for menu items Function to be called upon selection, by connecting item action and function –connect(newAct, SIGNAL(triggered()), this, SLOT(newFile())); And item stuff – shortcut, status tip –“Functionality”, or just functions, for menu items Define resources –E.g., images

38 Application Example Application with menus, toolbars, and status bar Simple text editor program built around QTextEdit –“Powerful” Qt widget –Many others … –Documentation next

39 QTextEdit Reference, 1 A widget that is a text editor! Note properties –And where come from

40 QTextEdit Reference, 2 Slots and signals

41 QTextEdit Reference, 3 Functions

42 MainWindow Class Definition mainwindow.h – as before, slots, functions, menus, etc. class MainWindow : public QMainWindow { Q_OBJECT class QAction; class QMenu; class QPlainTextEdit; public: MainWindow(); protected: void closeEvent(QCloseEvent *event); private slots: void newFile(); void open(); bool save(); bool saveAs(); void about(); void documentWasModified(); private: void createActions(); void createMenus(); void createToolBars(); void createStatusBar(); void readSettings(); void writeSettings(); bool maybeSave(); void loadFile(const QString &fileName); bool saveFile(const QString &fileName); void setCurrentFile(const QString &fileName); QString strippedName(const QString &fullFileName); QPlainTextEdit *textEdit; QString curFile; QMenu *fileMenu; QMenu *editMenu; QMenu *helpMenu; QToolBar *fileToolBar; QToolBar *editToolBar; QAction *newAct ; …

43 “The Central Widget” Depending on design - central area of main window –In non-Qt-ese Can be: –Standard widget E.g., QtextEdit, Qtable –Custom widget –Widgets with layout manager –Splitter (is like Q[V/H]Box) –MDI workspace (multiple wins)

44 MainWindow Class Implementation mainwindow.cpp #include #include "mainwindow.h" // Invoking MainWindow creates all MainWindow::MainWindow() { textEdit = new QPlainTextEdit; // One call for lots of functionality setCentralWidget(textEdit); createActions(); createMenus(); createToolBars(); createStatusBar(); readSettings(); // Standard to save and restore on start connect(textEdit->document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified())); setCurrentFile(""); // Setup for later use setUnifiedTitleAndToolBarOnMac(true); }

45 Application’s Menus Similar to what seen BTW - status bar at bottom of main window shows description of menu item or toolbar button under cursor

46 Creating Menu Items with Actions mainwindow.cpp void MainWindow::createMenus() // Create the top level menus { fileMenu = menuBar()->addMenu(tr("&File")); fileMenu->addAction(newAct); fileMenu->addAction(openAct); fileMenu->addAction(saveAct); fileMenu->addAction(saveAsAct); fileMenu->addSeparator(); fileMenu->addAction(exitAct); editMenu = menuBar()->addMenu(tr("&Edit")); editMenu->addAction(cutAct); editMenu->addAction(copyAct); editMenu->addAction(pasteAct); menuBar()->addSeparator(); helpMenu = menuBar()->addMenu(tr("&Help")); helpMenu->addAction(aboutAct); helpMenu->addAction(aboutQtAct); }

47 Creating Toolbar and Status Bar void MainWindow::createToolBars() // Toolbar created as menu is { fileToolBar = addToolBar(tr("File")); fileToolBar->addAction(newAct); fileToolBar->addAction(openAct); fileToolBar->addAction(saveAct); editToolBar = addToolBar(tr("Edit")); editToolBar->addAction(cutAct); editToolBar->addAction(copyAct); editToolBar->addAction(pasteAct); } void MainWindow::createStatusBar() { statusBar()->showMessage(tr("Ready")); }

48 Create Actions, 1 “Actions” specify what happens when menu item selected // “Actions” specify what happens when menu item selected void MainWindow::createActions() { // From createMenus(): “fileMenu->addAction(newAct);” newAct = new QAction(QIcon(":/images/new.png"), tr("&New"), this); // Note relative location of icon newAct->setShortcuts(QKeySequence::New); newAct->setStatusTip(tr("Create a new file")); connect(newAct, SIGNAL(triggered()), this, SLOT(newFile())); openAct = new QAction(QIcon(":/images/open.png"), tr("&Open..."), this); openAct->setShortcuts(QKeySequence::Open); openAct->setStatusTip(tr("Open an existing file")); connect(openAct, SIGNAL(triggered()), this, SLOT(open())); saveAct = new QAction(QIcon(":/images/save.png"), tr("&Save"), this); saveAct->setShortcuts(QKeySequence::Save); saveAct->setStatusTip(tr("Save the document to disk")); connect(saveAct, SIGNAL(triggered()), this, SLOT(save()));

49 Create Actions, 2 //Continue specifying actions for rest of menu items saveAsAct = new QAction(tr("Save &As..."), this); saveAsAct->setShortcuts(QKeySequence::SaveAs); saveAsAct->setStatusTip(tr("Save the document under a new name")); connect(saveAsAct, SIGNAL(triggered()), this, SLOT(saveAs())); exitAct = new QAction(tr("E&xit"), this); … cutAct = new QAction(QIcon(":/images/cut.png"), tr("Cu&t"), this); … copyAct = new QAction(QIcon(":/images/copy.png"), tr("&Copy"), this); … pasteAct = new QAction(QIcon(":/images/paste.png"), tr("&Paste"), this); … aboutAct = new QAction(tr("&About"), this); … aboutQtAct = new QAction(tr("About &Qt"), this); …

50 “Functionality Implemented”, 1 newFile, open - functions // “Functionality” means everything that is done … // From createActions: // connect(newAct, SIGNAL(triggered()), this, SLOT(newFile())); void MainWindow::newFile() { if (maybeSave()) { textEdit->clear(); // Next page setCurrentFile(""); } } void MainWindow::open() { if (maybeSave()) { // Use Qt function QString fileName = QFileDialog::getOpenFileName(this); // Use it if you have it if (!fileName.isEmpty()) loadFile(fileName); } }

51 Reference

52 “Functionality Implemented”, 2 setCurrentFile – one function among many // “Maintain” file name // E.g., set “” with call from open void MainWindow::setCurrentFile(const QString &fileName) { curFile = fileName; textEdit->document()->setModified(false); setWindowModified(false); QString shownName; if (curFile.isEmpty()) shownName = "untitled.txt"; else shownName = strippedName(curFile); setWindowTitle(tr("%1[*] - %2").arg(shownName).arg(tr("Application"))); }

53 “Functionality Implemented”, 3 save, saveAs – more functions bool MainWindow::save() { // curFile value set in func setCurrentFile if (curFile.isEmpty()) { return saveAs(); } else { return saveFile(curFile); } bool MainWindow::saveAs() { // Use a Qt widget QString fileName = QFileDialog::getSaveFileName(this); if (fileName.isEmpty()) return false; return saveFile(fileName); }

54 “Functionality implemented”, 4 saveFile – another function bool MainWindow::saveFile(const QString &fileName) { QFile file(fileName); if (!file.open(QFile::WriteOnly | QFile::Text)) { QMessageBox::warning(this, tr("Application"), tr("Cannot write file %1:\n%2.").arg(fileName).arg(file.errorString())); return false; } QTextStream out(&file); QApplication::setOverrideCursor(Qt::WaitCursor); out toPlainText(); QApplication::restoreOverrideCursor(); setCurrentFile(fileName); statusBar()->showMessage(tr("File saved"), 2000); // status bar message return true; }

55 “Functionality Implemented”, 5 loadFile – another function void MainWindow::loadFile(const QString &fileName) { QFile file(fileName); if (!file.open(QFile::ReadOnly | QFile::Text)) { QMessageBox::warning(this, tr("Application"), tr("Cannot read file %1:\n%2.").arg(fileName).arg(file.errorString())); return; } QTextStream in(&file); QApplication::setOverrideCursor(Qt::WaitCursor); textEdit->setPlainText(in.readAll()); QApplication::restoreOverrideCursor(); setCurrentFile(fileName); statusBar()->showMessage(tr("File loaded"), 2000); }

56 “Functionality Implemented”, 6 about void MainWindow::about() { QMessageBox::about(this, tr("About Application"), tr("The Application example demonstrates how to " "write modern GUI applications using Qt, with a menu bar, " "toolbars, and a status bar.")); }

57 Summary Idea was to provide a “template”, or examples of functionality needed There is more to life than file processing …

58 “Custom Widgets” Of course, OO approach allows inheritance and subclassing –And it is good Subclassing Qt widgets allows “simple” modifications to be simple –Will see the books example, which may be simple to the Qt professional Hex spin box But first, simply using code to alter functionality works, too –And to combine separate widget functionality, as well E.g., age spin and line edit boxes’ Next slide –Also, changing public properties and calling public functions –This probably how you want to do it in your program Custom widgets are fine example of how things are done once familiar with system – maybe not yet

59 Recall Synchronization & Layout of 2 Widgets Using signals and slots of the QSpinbox and QSlider, set value of one depending on value set in the other –E.g., change spinbox value to 70, slider will move to appropriate position –Change slider to some position, spinbox value will be changed based on position spinBox->setRange(0, 130);// Set/define range of each slider->setRange(0, 130); // A particular widget signal causes a function (slot) to be called // here, when the value in the spinbox is changed, the function to set the value in the // slider is called, and passed the new value of the spinbox to be the new value of the slider QObject::connect(spinBox, SIGNAL(valueChanged(int)), slider, SLOT(setValue(int))); // … and vice versa QObject::connect(slider, SIGNAL(valueChanged(int)), spinBox, SLOT(setValue(int)));

60 Example – Hexadecimal Spin Box Spin box that accepts and displays hexadecimal values (sub) Class definition –HexSpinBox inherits most of its functionality from QSpinBox (and that is good) –Reimplements 2 virtual functions from QSpinBox // HexSpinBox.h – (sub)class definition #include class HexSpinBox : public QSpinBox { public: HexSpinBox(QWidget *parent, const char *name = 0); protected: QString mapValueToText(int value); int mapTextToValue(bool *ok); };

61 Hex Spin Box Functionality User can modify box’s value by clicking arrows or typing in value –For what entered, restrict input to valid hex numbers –Use QRegExpValidator #include #include "hexspinbox.h“ // Subclass of QSpinBox – hex vs. the decimal of QSpinBox HexSpinBox::HexSpinBox(QWidget *parent, const char *name) : QSpinBox(parent, name) { QRegExp regExp("[0-9A-Fa-f]+");// Reference next setValidator(new QRegExpValidator(regExp, this)); setRange(0, 255); }

62 Qt Reference Regular expression manipulation

63 Change QSpinBox Functionality mapValueToText: converts integer value to string –QSpinBox calls it to update editor part of spin box when user presses arrows –Use Qstring::number() with arg 16 to convert value to lower-case hex –Use Qstring::upper() on result to make uppercase –Will change this and mapText to value for subclassing – simple! QString HexSpinBox::mapValueToText(int value) { return QString::number(value, 16).upper(); } mapTextToValue: converts string to integer –QSpinBox calls it when user presses enter (line editor) int HexSpinBox::mapTextToValue(bool *ok) { return text().toInt(ok, 16); }

64 Subclassing QWidget Very general - can combine, adapt, modify, etc. existing widgets –As we just saw Or, … can create whatever functionality desired by subclassing Qwidget Here, will reimplement event handlers to paint widget and respond to mouse clicks –Which seems like a lot, but not too bad (for the Qt professional) –This why we looked at the windows API! –QLabel, QPushbutton, QTable implemented this way Example – icon editor – IconEditor implementation

65 IconEditor.h, 1 Define (sub) class #include class IconEditor : public QWidget { Q_OBJECT Q_PROPERTY(QColor penColor READ penColor WRITE setPenColor)// custom properties Q_PROPERTY(QImage iconImage READ iconImage WRITE setIconImage) Q_PROPERTY(int zoomFactor READ zoomFactor WRITE setZoomFactor) public: IconEditor(QWidget *parent = 0, const char *name = 0); void setPenColor(const QColor &newColor); QColor penColor() const { return curColor; } void setZoomFactor(int newZoom); int zoomFactor() const { return zoom; } void setIconImage(const QImage &newImage); const QImage &iconImage() const { return image; } QSize sizeHint() const;

66 IconEditor.h, 2 Define (sub) class // Reimplements 3 (important!) functions from QWidget and has private variables for 3 values protected: void mousePressEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); void paintEvent(QPaintEvent *event); private: void drawImagePixel(QPainter *painter, int i, int j);// Accesses image, below void setImagePixel(const QPoint &pos, bool opaque);//“ QColor curColor; QImage image;// Principal data structure int zoom; };

67 IconEditor.cpp All the functions … #include #include "iconeditor.h“ IconEditor::IconEditor(QWidget *parent, const char *name) : QWidget(parent, name, WStaticContents) { setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); curColor = black;// Default (start up) values: zoom = 8;// E.g., render pixel in 8x8 square image.create(16, 16, 32); image.fill(qRgba(0, 0, 0, 0)); image.setAlphaBuffer(true); } QSize IconEditor::sizeHint() const { QSize size = zoom * image.size(); if (zoom >= 3)// Will show grid at higher zooms size += QSize(1, 1); return size; }

68 IconEditor.cpp void IconEditor::setPenColor(const QColor &newColor) { curColor = newColor; } void IconEditor::setIconImage(const QImage &newImage) { if (newImage != image) { image = newImage.convertDepth(32);// Set right form image.detach();// Copy for faster update();// Force a repaint – as invalidaterect! updateGeometry();// So can use sizehint }

69 IconEditor.cpp // paintEvent is an event handler! – this handles the paint event, rather than something else in Qt void IconEditor::paintEvent(QPaintEvent *) { QPainter painter(this); if (zoom >= 3) {// if need grid, draw lines painter.setPen(colorGroup().foreground()); for (int i = 0; i <= image.width(); ++i) // Qt drawLine function painter.drawLine(zoom * i, 0, zoom * i, zoom * image.height()); for (int j = 0; j <= image.height(); ++j) painter.drawLine(0, zoom * j, zoom * image.width(), zoom * j); } for (int i = 0; i < image.width(); ++i) { for (int j = 0; j < image.height(); ++j) drawImagePixel(&painter, i, j); }

70 IconEditor.cpp void IconEditor::drawImagePixel(QPainter *painter, int i, int j) // i, j coords inQImage, NOT in {// widget – it will have zoom lines QColor color; QRgb rgb = image.pixel(i, j); if (qAlpha(rgb) == 0) color = colorGroup().base(); else color.setRgb(rgb); if (zoom >= 3) { painter->fillRect(zoom * i + 1, zoom * j + 1, zoom - 1, zoom - 1, color); } else { painter->fillRect(zoom * i, zoom * j, zoom, zoom, color); }

71 IconEditor.cpp // Reimplement mouse handling events void IconEditor::mousePressEvent(QMouseEvent *event) { if (event->button() == LeftButton) setImagePixel(event->pos(), true); else if (event->button() == RightButton) setImagePixel(event->pos(), false); } void IconEditor::mouseMoveEvent(QMouseEvent *event) { if (event->state() & LeftButton) setImagePixel(event->pos(), true); else if (event->state() & RightButton) setImagePixel(event->pos(), false); }

72 IconEditor.cpp void IconEditor::setImagePixel(const QPoint &pos, bool opaque) { int i = pos.x() / zoom; int j = pos.y() / zoom; if (image.rect().contains(i, j)) { if (opaque) image.setPixel(i, j, penColor().rgb()); else image.setPixel(i, j, qRgba(0, 0, 0, 0)); QPainter painter(this); drawImagePixel(&painter, i, j); }

73 End.


Download ppt "QT – Dialog C++ GUI Programming with Qt 4 Qt 4.5 Reference Documentation Blanchette and Summerfield, Ch. 3."

Similar presentations


Ads by Google