Qt GUI Toolkit
Flickering is a common problem in graphics programming. Some GUI programs do updating by clearing the area of a widget and then draw the different graphics elements. This process normally takes enough time for the eye to notice the clearing and drawing process. The widget flickers, the program looks unprofessional and fatigues the eyes of the users.
A technique called double-buffering can be used to solve this problem. A pixmap (i.e., pixel map—an off-screen memory segment used as if it were a part of the screen raster buffer) is used, and all drawing is done off-screen on this pixmap. The pixmap is then transferred to the screen in one lightning-fast operation. This pixmap transfer is normally so fast that on most systems it appears instantaneous to the human eye.
Sometimes a pixmap the size of the widget to update is used, in other cases, only certain parts of the widget are double-buffered. Which method will be most effective must be considered in each case.
Pixmaps often contain large amounts of data and are often slow to create and handle (in CPU-time). A good technique is to store the buffer pixmap as a part of the widget. When the widget needs to update itself (in Qt, whenever it receives a paint event), it simply copies the required part of the buffer pixmap to the part of the widget that must be repainted.
Often, it is useful to include a dirty flag as a part of the widget. All state changes (i.e., changes to member variables) that affect the visual appearance of the widget can then simply set this flag to TRUE telling the widget to repaint itself. The paint event function then checks the dirty flag, and updates the buffer pixmap before it updates the screen. This ensures that all widget painting code is in one place, making the widget easier to maintain and debug.
I've found this technique to be very useful and powerful and have used it on a variety of GUI-systems, as well as Qt.
OK, now that we've looked at different parts of Qt, let's use it to build a custom-made software component that can display an image and rotate it by an angle. This widget should contain slots with instructions to let the user choose a file on disk, and it should have the ability to print the rotated image on a printer.
As a start we decide to give it the following signals and slots:
public slots:
void setAngle( int degrees );
void load();
void print();
signals:
void angleChanged( int );
void filePathChanged( const char * );
We can now set the rotation angle setAngle, let the user choose a new image file load, and print the image print. We choose to implement the functionality we need for the first version first. Later this component can be expanded to include slots like setPixmap(QPixmap) or setFilePath(QString).
The two signals tell the world about a change in the rotation angle (angleChanged) or the image file being displayed (filePathChanged).
Next, we include two member functions to fetch the angle and file path:
public:
int angle() const { return ang; }
const char *filePath() const { return name; }
And we include the following member variables:
private:
int ang;
QString name;
QPixmap pix;
QPrinter printer;
QFileDialog fileDlg;
QPixmap bufferPix;
bool dirty;
By setting these variables, we store an angle, file name, pixmap, printer and file selection dialog in the component. We want the widget to update itself smoothly and have decided to use the double-buffering technique, so we store a buffer pixmap. In addition, we have a dirty flag which is set when the widget needs to update the buffer pixmap. The combination of a buffer pixmap and a dirty flag is a very useful and powerful GUI technique that can be used in a large range of widgets.
Also, the widget has a paint event function and a resize event function, see code Listing 3 for the full class declaration.
Since we want to be able to paint to both the screen and a printer, we put the drawing code in a private member function that operates on a QPainter:
void PixmapRotator::paintRotatedPixmap(QPainter *p)
{
// need device width and height
QPaintDeviceMetrics m( p->device() );
// center point
p-$gt;translate( (m.width())/2,
(m.height()) / 2 );
p->rotate( ang );
p->drawPixmap( - (pix.width())/2,
- (pix.height())/2, pix );
}
First we fetch the metrics of the device the painter is operating on. We use the width and height of the device to put the center (0,0) of our coordinate system in the middle of the device. Next we rotate the coordinate system by the wanted angle and draw the pixmap with its center point at (0,0). In other words, the center point of the pixmap is put at the center point of the device.
The paint event function looks like this:
void PixmapRotator::paintEvent( QPaintEvent *e )
{
if ( dirty ) { // buffer needs update?
// same size as widget
bufferPix.resize( size() );
// clear pixmap
bufferPix.fill( backgroundColor() );
QPainter p;
// paint on buffer pixmap
p.begin( &bufferPix );
paintRotatedPixmap( &p );
p.end();
dirty = FALSE; // buffer now new and clean
} // update exposed region:
bitBlt( this, e->rect().topLeft(), &bufferPix,
e->rect() );
}
If the widget is “dirty”, we need to update the buffer pixmap. We set its size to the size of the widget, clear it and call our local painting function. Don't forget to reset the dirty flag when a buffer pixmap has been updated.
Finally, we use the QPaintEvent pointer to find out which part of the widget must be updated and call bitBlt. bitBlt is a global function that can transfer data from one paint device to another as fast as possible. bitBlt is common GUI shorthand for “bit block transfer”.
With double-buffering and a dirty flag, the resize event function becomes trivial:
void PixmapRotator::resizeEvent( QResizeEvent *e )
{
dirty = TRUE; // need to redraw
}
Again, it is never necessary to repaint a widget in a resize event, since Qt automatically sends a paint event after the resize event.
With a common drawing function doing printing is also easy:
void PixmapRotator::print()
{
// opens printer dialog
if ( printer.setup(this) ) {
QPainter p;
p.begin( &printer ); // paint on printer
paintRotatedPixmap( &p );
p.end(); // send job to printer
}
}
First we let the user setup the printer, then we open a painter on that printer, and finally, call the drawing function.
Loading a new image takes a bit more code:
void PixmapRotator::load()
{
QString newFile;
QPixmap tmpPix;
while ( TRUE ) {
// open file dialog
if ( fileDlg.exec() != QDialog::Accepted )
return; // the user clicked cancel
// get the file path
newFile = fileDlg.selectedFile();
// is it an image?
if ( tmpPix.load( newFile ) )
break; // yes, break the loop
QString s; // build a message string
s.sprintf("Could not load \"%s\"",
newFile.data() );
// sorry!
QMessageBox::message( "Error", s );
}
pix = tmpPix; // keep the pixmap
name = newFile; // new file name
emit filePathChanged( name ); // tell world
dirty = TRUE; // need to redraw
repaint( FALSE ); // paint the whole widget
}
We set up a loop that opens the file dialog box. If the user has selected a file that cannot be loaded, we tell her and let her try again. If a valid file has been selected, we copy the new pixmap and the file path. Finally, we emit a signal to tell the world, mark the widget as dirty and repaint all of it (the FALSE argument means that Qt should not clear the widget before sending the paint event).
We have now made a new software component which can be connected to others through the signal/slot mechanism. See www.troll.no/qt for the full code of the PixmapRotator widget.
Realizing the promise of Apache® Hadoop® requires the effective deployment of compute, memory, storage and networking to achieve optimal results. With its flexibility and multitude of options, it is easy to over or under provision the server infrastructure, resulting in poor performance and high TCO. Join us for an in depth, technical discussion with industry experts from leading Hadoop and server companies who will provide insights into the key considerations for designing and deploying an optimal Hadoop cluster.
Sponsored by AMD
Built-in forensics, incident response, and security with Red Hat Enterprise Linux 6
Every security policy provides guidance and requirements for ensuring adequate protection of information and data, as well as high-level technical and administrative security requirements for a system in a given environment. Traditionally, providing security for a system focuses on the confidentiality of the information on it. However, protecting the data integrity and system and data availability is just as important. For example, when processing United States intelligence information, there are three attributes that require protection: confidentiality, integrity, and availability.
Learn more about catching the bad guy in this free white paper.
Sponsored by DLT Solutions
| Designing Electronics with Linux | May 22, 2013 |
| Dynamic DNS—an Object Lesson in Problem Solving | May 21, 2013 |
| Using Salt Stack and Vagrant for Drupal Development | May 20, 2013 |
| Making Linux and Android Get Along (It's Not as Hard as It Sounds) | May 16, 2013 |
| Drupal Is a Framework: Why Everyone Needs to Understand This | May 15, 2013 |
| Home, My Backup Data Center | May 13, 2013 |
- New Products
- Linux Systems Administrator
- Senior Perl Developer
- Technical Support Rep
- UX Designer
- Web & UI Developer (JavaScript & j Query)
- Designing Electronics with Linux
- Dynamic DNS—an Object Lesson in Problem Solving
- Using Salt Stack and Vagrant for Drupal Development
- Making Linux and Android Get Along (It's Not as Hard as It Sounds)
- Reply to comment | Linux Journal
4 hours 21 min ago - Reply to comment | Linux Journal
4 hours 37 min ago - Favorite (and easily brute-forced) pw's
6 hours 28 min ago - Have you tried Boxen? It's a
12 hours 20 min ago - seo services in india
16 hours 52 min ago - For KDE install kio-mtp
16 hours 52 min ago - Evernote is much more...
18 hours 53 min ago - Reply to comment | Linux Journal
1 day 3 hours ago - Dynamic DNS
1 day 4 hours ago - Reply to comment | Linux Journal
1 day 5 hours ago
Enter to Win an Adafruit Pi Cobbler Breakout Kit for Raspberry Pi

It's Raspberry Pi month at Linux Journal. Each week in May, Adafruit will be giving away a Pi-related prize to a lucky, randomly drawn LJ reader. Winners will be announced weekly.
Fill out the fields below to enter to win this week's prize-- a Pi Cobbler Breakout Kit for Raspberry Pi.
Congratulations to our winners so far:
- 5-8-13, Pi Starter Pack: Jack Davis
- 5-15-13, Pi Model B 512MB RAM: Patrick Dunn
- 5-21-13, Prototyping Pi Plate Kit: Philip Kirby
- Next winner announced on 5-27-13!
Featured Jobs
| Linux Systems Administrator | Houston and Austin, Texas | Host Gator |
| Senior Perl Developer | Austin, Texas | Host Gator |
| Technical Support Rep | Houston and Austin, Texas | Host Gator |
| UX Designer | Austin, Texas | Host Gator |
| Web & UI Developer (JavaScript & j Query) | Austin, Texas | Host Gator |
Free Webinar: Hadoop
How to Build an Optimal Hadoop Cluster to Store and Maintain Unlimited Amounts of Data Using Microservers
Realizing the promise of Apache® Hadoop® requires the effective deployment of compute, memory, storage and networking to achieve optimal results. With its flexibility and multitude of options, it is easy to over or under provision the server infrastructure, resulting in poor performance and high TCO. Join us for an in depth, technical discussion with industry experts from leading Hadoop and server companies who will provide insights into the key considerations for designing and deploying an optimal Hadoop cluster.
Some of key questions to be discussed are:
- What is the “typical” Hadoop cluster and what should be installed on the different machine types?
- Why should you consider the typical workload patterns when making your hardware decisions?
- Are all microservers created equal for Hadoop deployments?
- How do I plan for expansion if I require more compute, memory, storage or networking?




Comments
GUI deveopment using QT
i wanted to know as to how a GUI can be developed using QT with C++ program give an example .
linux
sir,
i am troubling about qt.i am begineer of linux.In my project i am doing in linux.for gui designing we use qt design.i not very well about qt:gui design and where we write code in qt,and how to complie in c++ coding.i am using fedora.pls give me steps for designing and coding... i am waiting..