310 likes | 1.03k Views
CS 352: Computer Graphics The QT portable GUI Toolkit Perspective How hard is it to build a computer? How hard is it to build a word processor? Why? Holy grail of software engineering: re-use Where has re-use been successful? Why?
E N D
CS 352: Computer Graphics The QT portable GUI Toolkit
Perspective • How hard is it to build a computer? • How hard is it to build a word processor? • Why? • Holy grail of software engineering: re-use • Where has re-use been successful? Why? • A major success in re-use: GUI toolkits, component-style software architecture • A way to serve the world: design, document, distribute
GUI toolkits • Windows – MFC, .net • Mac – MacOS, Carbon, Cocoa • Unix and Linux – many. E.g. GTK (www.gtk.org) • Not cross platform; verbose? • Java – cross platform • QT: portable • "framework" – also handles sending events to widgets • Not based on layering (too slow, LCD) • Not based on API emulation (slow; different platforms require different API) • Based on GUI emulation • Fast, responsive, cross platform, compact code, …
QT notes • GUI emulation • Different API, same look-and-feel • Fast • Harder to implement • GUI emulation may not be perfect • Commercial, but GNU-licensed open source version • Used for KDE • Shunned by Red Hat • Online documentation, tutorial • Use: concepts, familiarity with widgets, and using the documentation…
QT examples • Various widgets • Panes – splitter • Tables – table • XML parsing – tagreader • Networking, sound, printing • 2D graphics – drawlinescanvasxform • OpenGL support – gear • OpenGL widgets, pixmaps – glpixmaps
Hello World #include <QApplication> #include <QPushButton> int main(int argc, char *argv[]) { QApplication app(argc, argv); QPushButton hello("Hello world!"); hello.show(); return app.exec(); }
Event handling • In glut we registered callback functions • Callback registration is not type-safe • Usually very primitive events, e.g. mousedown • Would rather have a button's click handler called by toolkit • Could use virtual methods • Clean C++ solution • But it can be a nuisance – you have to derive a new class to handle an event • Could use macros to tie C++ methods to events (MFC) • Message maps are hard to read, hard to write, and not type-safe (though in Visual C++, IDE handles them)
Event handling in QT • QT's new approach: signals and slots • A widget sends out various signals • Object methods can be declared as slots • Compatible signals and slots can be connected or plugged together like a telephone switchboard (parameter types must match) • Strict separation • This strict separation between UI components and program elements lends itself to component-based programming • Goal: separate UI from program logic
Button #include <QApplication> […] int main(int argc, char *argv[]) { QApplication app(argc, argv); QWidget window; window.resize(200, 120); QPushButton quit("Quit", &window); quit.setFont(QFont("Times", 18, QFont::Bold)); quit.setGeometry(10, 40, 180, 40); QObject::connect(&quit, SIGNAL(clicked()), &app, SLOT(quit())); window.show(); return app.exec(); }
Defining signals and slots • New C++ syntax for defining signals and slots, added to public, private, etc. class myClass : public Qobject { Q_OBJECT //required macro, no semicolon … signals: void somethingHappened(); … public slots: void slotDoSomething(); … private slots: void slotDoSomethingInternal(); … };
Signals and Slots • Signals: emit events • declare as signals, otherwise normal member functions • You don't implement them. Rather, you send them with the (new) keyword emit • E.g. emit(sliderChanged(5)) • Slots: receive and handle events • Normal member fcns declared as slots • Connect: must connect signals to slots • QObject::connect( mymenu, SIGNAL(activated(int)), myobject, SLOT(slotDoMenuFunction(int)) ); • moc: meta object compiler (preprocessor) converts these new keywords to real C++
QWidget • Base class for all UI widgets • Properties • width, height, backgroundColor, font, mouseTracking, backgroundPixmap, etc. • Slots • repaint, show, hide, move, setGeometry, setMainWidget, etc. • Signals: • mouseMoveEvent, keyPressEvent, resizeEvent, paintEvent, enterEvent, leaveEvent, etc.
QPixmap, QImage • QPixmap: offscreen pixmap optimized for drawing • Member functions: fill, resize, load, save, … • Paint on it with a QPainter • QImage: similar, but optimized for access to pixel data
QPainter • Paints on a paint device (window, QPixmap…) • Member functions such as • setPen, setBrush, setBackgroundColor, setViewport • Scale, shear, rotate, translate • moveTo, lineTo, drawPoint, drawLine, drawRect, drawEllipse, drawArc, drawPolyline, drawPolygon, drawPixmap, drawImage, drawText, fillRect
QPainter use • 99% of QPainter use is in reimplementing QWidget::paintEvent() void SimpleExampleWidget::paintEvent() { QPainter paint( this ); paint.setPen( Qt::blue ); paint.drawText(rect(), AlignCenter, "Zyzzyvas are the Last Word in Rodents!"); } • A nice, full, fast 2D drawing class, though it uses the CPU, not the graphics card
Scribble (Trolltech example) • class ScribbleArea: public QWidget • Offscreen image buffer: QImage image; • ScribbleArea::mousePressEvent( QMouseEvent* event): lastPoint = event->pos(); • ScribbleWindow::mouseMoveEvent:QPainter painter(&image); Painter.drawLine(lastPoint, endPoint); lastPoint=endPoint; • ScribbleWindow::paintEvent(QEvent *event) QPainter painter(&image); QPainter painter(this); painter.drawImage(QPoint(0,0), image);
Menus • Using Menus • Define “actions”, which are menu items with shortcuts, connected to slots • Define menus • Add actions to menus • Define menuBar • Add menus to menuBar
File I/O • To load an image: get filename, load using built-in methods void ScribbleArea::slotLoad() { QString filename = QFileDialog::getOpenFileName( this, tr(“Open File”), QDir::currentPath()); if (!filename.isEmpty()) scribbleArea->openImage(fileName); }
Selecting colors • Built-in dialogues for common tasks are God's gift to graphics programming! QColor QColorDialog::getColor( QColor initial); void Scribble::slotColor() { QColor c = QColorDialog::getColor( canvas->penColor()); if (c.isValid()) canvas->setPenColor( c ); }
OpenGL • Use QT instead of glut for windows, GUI • QGLWidget instead of QWidget • paint with GL functions, not QPainter • Re-implement initializeGL(), paintGL(), resizeGL() [ instead of paintEvent() and resizeEvent() ] • repaintGL() is called each time a window is resized, including before the viewport is first draw--use for setting up size-specific parameters such as viewing transform • Hellogl, grabber examples
Animation • How would you get things to move smoothly? • QTimer() can call a slot at intervals QTimer *timer = new QTimer(this); connect(timer, SIGNAL(timeout()), this, SLOT(drawNextFrame())); timer->start(20);
QGLWidget • Important members: • initializeGL(), resizeGL(), paintGL() • qglColor(), qglClearColor() • setAutoBufferSwap(bool), swapBuffers() • QImage grabFrameBuffer() • QImage convertToGLFormat( QImage &image ) • How to get images in/out of a QGLWidget?
OpenGL and Pixmaps • QPixmap, QImage have support for load, save • Save: use grabFrameBuffer to make a QImage and use QImage::save() • Load: copy offscreen pixmap back into OpenGL • GLPaint example
Image processing tidbits • How would you brighten an image? • How would you increase the contrast? • How would you blur or soften an image? • How would you sharpen an image?
Gamma correction • How bright is 0? 256? 128? • People's perception is not linear: twice the number of photons one step brighter • Intensities needed: e.g. 1, ½, ¼, 1/8, … • Different monitors have different, non-linear brightness function for voltage (gamma) • NTSC, I = k N γ • I = brightness, N = # electrons (driving voltage) • NTSC: gamma = 2.2 • Better monitors: gamma is lower, e.g. 1.4 • Need "gamma correction" (intensity look-up table)
Convolution • Generate a new image from old • Each pixel x,y in new is based on region of the old, e.g. 3x3, centered on x,y • Each pixel in region is multiplied by a coefficient in the (3x3) convolutionkernel • Example kernels: • Blurring: averaging. E.g. all values in kernel 1/9. • Sharpening: differentiation. E.g. all values –1/8 except center value, which is 2 • Edge detection: e.g. Robert’s Cross, [-1 0 1 \ -2 0 2 \ -1 0 1]
Web resources for image processing • Gamma correction • Blurring • Sharpening • Edge detection
QMake • You can define a .pro project file and run qmake to generate a makefile • QTScribble2.pro: TEMPLATE = app CONFIG = qt opengl warn_on release HEADERS = SOURCES = qtscribble2.cpp
Using QT • Download, install open source version from http://www.qtsoftware.com/downloads/opensource/appdev • Can use qmake –project, qmake, make • Eclipse plug-in available • Mac installation enables Xcode development
Using the QT documentation • You will need to refer constantly to the QT documentation to find available classes, members, parameters • It's available at http://doc.trolltech.com