The so-called buffer is to first draw a picture in the memory, and finally draw this picture to the screen at a time
1. Add a variable to the main form:
PRIVATE:
Qpixmap * BMP;
2. assign a value to the constructor:
BMP = new qpixmap (this-> size (); // The size here is the size of the form (the same size of the LED should be set)
3. Drawing on BMP using specific business logic:
Void mainwindow: changescreen ()
{
BMP-> Fill (QT: Black );
Qpainter P (BMP );
P. setpen (QT: Green );
P. setbrush (QT: Green );
P. drawtext (BMP-> rect (), "test"); // black on BMP, green
Update (); // call the paintevent () function indirectly
}
Scroll (-) means to move the horizontal scroll bar to the left one pixel, which will cause the repainting of the entire scroll bar content window, because the value of each pixel has changed, if you want to specify to repaint only a region, you can specify the parameters of the update () function. In this way, the re-painting function automatically redraws the specified region without affecting other regions.
4. The redraw function should have the following content:
Void mainwindow: paintevent (qpaintevent * E)
{
Qpainter P (this );
P. drawimage (this-> rect (), BMP); // The bitmap should be filled in the entire form.
}
Step 3: associate your business logic with the content that you want to draw on BMP.
<! --
# TOC,
. TOC,
. Mw-warning {
Border: 1px solid # AAA;
Background-color: # f9f9f9;
Padding: 5px;
Font-size: 95%;
}
# TOC H2,
. TOC H2 {
Display: inline;
Border: none;
Padding: 0;
Font-size: 100%;
Font-weight: bold;
}
# TOC # toctitle,
. TOC # toctitle,
# Toc. toctitle,
. Toc. toctitle {
Text-align: center;
}
# TOC ul,
. TOC ul {
List-style-type: none;
List-style-image: none;
Margin-left: 0;
Padding-left: 0;
Text-align: left;
}
# TOC ul,
. TOC ul {
Margin: 0 0 0 2em;
}
# Toc. toctoggle,
. Toc. toctoggle {
Font-size: 94%;
} @ Media Print, projection, embossed {
Body {
Padding-top: 1In;
Padding-bottom: 1In;
Padding-left: 1In;
Padding-Right: 1In;
}
}
Body {
Font-family: 'libation serif ';
Font-variant: normal;
Text-indent: 0in;
Widows: 2;
Font-style: normal;
Font-weight: normal;
Text-Decoration: none;
Color: #000000;
Text-align: left;
Font-size: 12pt;
}
Table {
}
TD {
Border-collapse: collapse;
Text-align: left;
Vertical-align: top;
}
P, H1, H2, H3, Li {
Color: #000000;
Font-family: 'libation serif ';
Font-size: 12pt;
Text-align: left;
Vertical-align: normal;
}
-->
Double Buffer drawing
In qt4, by default, all widgets use double buffering for plotting. Double Buffering can reduce the flickering effect of the painting. In some cases, you need to disable double buffering and manage the drawing by yourself. The following statement sets the QT: wa_paintonscreen attribute of the widget to disable the double buffering of the widget.
Mywidget-> setattribute (QT: wa_paintonscreen );
Since qt4 no longer provides an exclusive or pen, the combination mode qpainter: compostionmode_xor () is not an exclusive or pen. qt4 only provides qrubberband for Drawing Feedback on Rectangles and straight lines. Therefore, we need to implement the dynamic
Other methods must be used for feedback.ProgramTo solve this problem. During the drawing process, a buffer zone draws a temporary memory, a buffer zone stores the drawn content, and finally merges it.
During the interactive drawing process, the program copies the image buffer zone to the temporary buffer zone and draws the image in the temporary buffer zone. After the drawing is complete, the results are copied to the image buffer zone. If no interactive copying is performed, the image buffer is directly drawn to the screen.
Two-buffer non-blinking plot in QT component
First, set the background mode of the component to nobackground to reduce the flicker.
Setbackgroundmode (nobackground );
Second, the paintevent () function of the overload component is rewritten as follows:
Void mywidget: paintevent (qpaintevent * E)
{
Qrect ur = e-> rect (); // obtain the component size.
Qpixmap pix (Ur. Size (); // create a bitmap variable with this parameter
PIX. Fill (this, Ur. topleft (); // fill the bitmap
Qpainter P (& pic); // create a qpainter object with bitmap as the parameter
P. Translate (-ur. X (),-ur. Y (); // draw on qpainter
// ...... // Drawing
P. End (); // painting completed
Bitblt (this, Ur. topleft (). & pix); // paste the bitmap to the component.
// Note from qt4, bitblt function is not used, instead of drawpixmap.
}
// This is the key to random point painting. If this attribute is not set, the last screen is completely wiped by default for each QT,
// The repaint (bool) interface is no longer available in the new QT version.
W. setattribute (QT: wa_opaquepaintevent );
In the snowflake effect of the old TV, you need to erase and redraw each time to avoid point overlay. So comment out the statement.
// W. setattribute (QT: wa_opaquepaintevent );
(
The following is the implementation of private functions:
Void plotter: updaterubberbandregion ()
{
Qrect rect = rubberbandrect. Normalized ();
Update (rect. Left (), rect. Top (), rect. Width (), 1 );
Update (rect. Left (), rect. Top (), 1, rect. Height ());
Update (rect. Left (), rect. Bottom (), rect. Width (), 1 );
Update (rect. Right (), rect. Top (), 1, rect. Height ());
}
The updaterubberband () function is called in mousepressevent (), mousemoveevent (), and mousereleaseevent () to delete or re-draw the rubber line. The function calls Update () four times, and uses four draw events to draw four small rectangles consisting of a rubber line (two vertical and horizontal lines. Qt also provides a class of qrubberband to draw the rubber line, but the draw function provided by the control itself will be better
Void plotter: refreshpixmap ()
{
Pixmap = qpixmap (SIZE ());
Pixmap. Fill (this, 0, 0 );
Qpainter painter (& pixmap );
Painter. initfrom (this );
Drawgrid (& painter );
Drawcurves (& painter );
Update ();
}
The refreshpixmap () function draws the plot on the image and updates the display. First, adjust the image size to the same size as the current control, and then fill the entire image with the background color of the control. This color is the "dark" part of the current color palette, because setbackgroundrole () is called in the plotter constructor (). Qpixmap: Fill () you need to know the offset of the paint brush in the control to align the image with the paint brush mode. The image corresponds to the entire control, so the offset is (0, 0 ).
Next, we create a qpainter object to draw an image. qpainter: initfrom () sets the paint brush, background, and font required to draw the image, this parameter indicates that these settings are consistent with those of the plotter control. Then we call drawgrid () and drawcurves () to draw the grid and curve. Finally, the update () function schedules the draw events of the entire control and copies the image to the control in the painteevent () function.
Void plotter: drawgrid (qpainter * painter)
{
Qrect rect (margin, margin,
Width ()-2 * margin, height ()-2 * margin );
If (! Rect. isvalid ())
Return;
Plotsettings settings = zoomstack [curzoom];
Qpen quitedark = palette (). Dark (). color (). Light ();
Qpen light = palette (). Light (). color ();
For (INT I = 0; I <= settings. numxticks; ++ I ){
Int x = rect. Left () + (I * (rect. Width ()-1)
/Settings. numxticks );
Double Label = settings. Minx + (I * settings. Spanx ()
/Settings. numxticks );
Painter-> setpen (quitedark );
Painter-> drawline (x, rect. Top (), X, rect. Bottom ());
Painter-> setpen (light );
Painter-> drawline (x, rect. Bottom (), X, rect. Bottom () + 5 );
Painter-> drawtext (X-50, rect. Bottom () + 5,100, 15,
Qt: alignhcenter | QT: aligntop,
Qstring: Number (Label ));
}
For (Int J = 0; j <= settings. numyticks; ++ J ){
Int y = rect. Bottom ()-(J * (rect. Height ()-1)
/Settings. numyticks );
Double Label = settings. miny + (J * settings. spany ()
/Settings. numyticks );
Painter-> setpen (quitedark );
Painter-> drawline (rect. Left (), y, rect. Right (), y );
Painter-> setpen (light );
Painter-> drawline (rect. Left ()-5, Y, rect. Left (), y );
Painter-> drawtext (rect. Left ()-margin, Y-10, margin-5, 20,
Qt: alignright | QT: alignvcenter,
Qstring: Number (Label ));
}
Painter-> drawrect (rect. Adjusted (0, 0,-1,-1 ));
}
The drawgrid () function draws a grid under the coordinate axis and curve. This area is determined by a rectangle. If the control is too small, return immediately if it is not drawn. The first cycle draws the vertical line of the grid and the scale along the X axis. The second cycle draws the horizontal line of the grid and the scale along the Y axis. Finally, draw a rectangle along the boundary. Drawtext () draws a number that corresponds to the scale mark on the two coordinate axes.
The syntax of the painter-> drawtext () function is as follows:
Painter-> drawtext (X, Y, width, height, alignment, text );
The rectangle (X, Y, width, height) and alignment determine the position of the text in the rectangle.
Void plotter: drawcurves (qpainter * painter)
{
Static const qcolor colorforids [6] = {
Qt: Red, QT: Green, QT: blue, QT: cyan, QT: magenta, QT: Yellow
};
Plotsettings settings = zoomstack [curzoom];
Qrect rect (margin, margin,
Width ()-2 * margin, height ()-2 * margin );
If (! Rect. isvalid ())
Return;
Painter-> setcliprect (rect. Adjusted (+ 1, + 1,-1,-1 ));
Qmapiterator <int, qvector <qpointf> I (curvemap );
While (I. hasnext ()){
I. Next ();
Int id = I. Key ();
Const qvector <qpointf> & Data = I. Value ();
Qpolygonf polyline (data. Count ());
For (Int J = 0; j <data. Count (); ++ J ){
Double dx = data [J]. X ()-settings. Minx;
Double DY = data [J]. Y ()-settings. miny;
Double X = rect. Left () + (dx * (rect. Width ()-1)
/Settings. Spanx ());
Double Y = rect. Bottom ()-(dy * (rect. Height ()-1)
/Settings. spany ());
Polyline [J] = qpointf (x, y );
}
Painter-> setpen (colorforids [uint (ID) % 6]);
Painter-> drawpolyline (polyline );
}
}
The drawcurves () function draws a curve on the upper layer of the grid. The qpainter: setcliprect () function is called to set the cut area of qpainter to the rectangle area containing the curve (excluding the surrounding gap and the outer frame of the image ). Qpainter ignores pixels outside this area.
Then we use a Java-style iterator to traverse all curves, traverse each curve, and traverse all its qpointf points. Function key () obtains the curve ID, and value () function obtains the qvector <qpointf> data of the curve. The inner loop converts the plotter coordinate of each qpointf record into the control coordinate, and stores the result in the polyline variable.
After the coordinates are converted, we set the color of the paint brush (using the predefined color before the function) and call drawpolyline () to draw the curve and go through all the points on the curve.