1. QT Style
A) Qt Introduction
QT is a cross-platform C ++ graphical user interface application.ProgramThe development library can use QT to develop high-quality graphical user interfaces. It is fully object-oriented, easy to expand, and allows true component programming. Qt has achieved great success. In particular, its signal-slot mechanism is a communication mechanism worth studying. It is also the basis of KDE (K desktop enviroment), a standard component of Linux release.
B) style Mechanism
Qt's style mechanism implements the look and feel of GUI on different platforms. For example, windows or Windows-XP are usually used on Windows platforms, on UNIX platforms, Motif and cde are usually used.
Shows the inheritance relationships of style-related classes in QT.
Qstyle is the base class of all style classes. It controls the interface style or perception of all components (widgets are controls in Windows programming, it defines a large number of enumeration types and a dozen functions. The enumeration type indicates different elements on the interface (such as buttons in the combo box and button borders). The function controls the drawing of the graphic user interface, however, most functions are basically just declaration without function implementation. Their implementation is in qcommonstyle, qwindowstyle, qmotifstyle and its subclass. Qstyle only implements three functions: drawitem (), itemrect (), and visualrect ().
Drawitem (): draws text and pixel graphs.
Itemrect (): the area of the returned text or image.
Visualrect (): returns the logical coordinates. This function enables QT to implement the right-to-left style (AVEN and vivin are traditionally used to display text from right to left, so the control layout is also from right to left ). As shown in:
You can see that the menu, toolbar is right aligned, and button with a single button is on the right.
C) Steps for creating a new style
To implement a new style in QT, you only need to select a style class (such as qcommonstyle or qstyle) as the parent class and then implement the functions you are interested in. The difficulty lies in the implementation of functions.
Select parent class: You can select qstyle, qcommonstyle, qwindowstyle, qmotifstyle, and any of their child classes as the parent class. You can choose either qwindowsstyle or qmotifstyle, or qcommonstyle or even qstyle, but the workload will be large, because many interface details need to be implemented by yourself.
Re-implement the necessary functions: If you want to modify the part of the interface style, re-implement the functions related to the part to be drawn. The following describes several functions in the qstyle to be reloaded, these functions control the layout and view of different elements on the graphic user interface.
.
1) void drawprimitive (primitiveelement PE, Qpainter * P, Const qrect & R, Const qcolorgroup & CG, Sflags flags = style_default, Const qstyleoption & OPT = qstyleoption: Default );
|
Function: draws basic graphic elements, such as buttons with arrows in qspinbox.
Parameter: primitiveelement PE: This enumeration variable represents the basic graphic interface elements to be drawn (the basic graphic user interface elements mentioned here refer to an atomic element that cannot be further divided in the GUI, for example, if the button in the combo box is painted with a black triangle
Qpainter * P: pointer to the qpainter class. This class processes all painting operations in QT, including text, graphics, and images.
Qrect & R: indicates a rectangular area in which QT draws the basic interface element (primitiveelement ).
Qcolorgroup & CG: qcolorgroup indicates the color group of a widget. The color group contains various colors used when the widget draws itself, such as the foreground color and background color. Displays various color attributes in a color group.
Sflags flags: controls how to draw graphical element labels.
Qstyleoption & OPT: different parameters are required to draw different Widgets. For example, to draw a panel, you may need to use the line width as an additional parameter to draw a focus rectangle (Focus rect) the background color may be used as an additional parameter. Therefore, QT provides a special qstyleoption class to encapsulate different parameters that may be required by different Widgets. Opt points to the object of such a class.
2) void drawcomplexcontrol (complexcontrol Control, Qpainter * P, Const qwidget * widget, Const qrect & R, Const qcolorgroup & CG, Sflags flags = style_default, Scflags controls = qstyle: SC _all, Scflags active = qstyle: SC _none, Const qstyleoption & OPT = qstyleoption: default)
|
Function: draws widgets such as spinwidget, ComboBox, Slider, and listview.
Parameters:
Complexcontrol control: it is an enumeration volume that indicates the complex control components (widgets) to be drawn, such as a combo box and a list box.
Qpainter * P: pointer to qpainter. This class processes all painting operations in QT, including text, graphics, and images.
Qwidget * Widget: pointer to qwdget or its subclass. You can convert the value of the control to a suitable type. For example, if you want to draw a qspinwidget, set the control value to cc_spinwidget, the widget points to an instance of a qspinwidget (subclass of qwidget ). You can use this variable to access the member functions and member variables of qspinwidget. For example, you can call the sizehint function of qspinwidget to obtain the default size (a rectangle space) of this component ).
Qrect & R: indicates a rectangular area in which QT draws controls or its child widgets.
Qcolorgroup & CG: qcolorgroup indicates the color group of a widget. The color group contains various colors used when the widget draws itself, such as the foreground color and background color.
Sflags flags: controls how to draw graphical element labels
Scflags controls indicates the child part of the control component for drawing the complex control component. The default value is SC _all. That is, the entire control is drawn instead of a child part of the control component. (Note that control and controls are two different parameters)
Qstyleoption & OPT: different additional parameters may be required when drawing different Widgets. This variable provides different information when drawing different widgets.
3) qrect querysubcontrolmetrics (complexcontrol Control, Const qwidget * widget, Subcontrol SC, Const qstyleoption & = qstyleoption: default)
|
Function: obtains coordinates and dimensions of child parts. This function controls the layout of a complex control. By reloading this function, you can draw the drop-down buttons of the combo box on the left rather than the default right.
Parameters:
Complexcontrol control: the enumerated quantity, indicating the complex control components (widgets) to be drawn, such as the combo box and list box.
Qwidget * Widget: a pointer to a qwidget or its subclass. You can convert it to a suitable type based on the preceding control value (CAST). For example, if you want to draw a qspinwidget, set the control value to cc_spinwidget, the widget points to an instance of qspinwidget (a subclass of qwidget. You can use this variable to access the member functions and member variables of qspinwidget. For example, you can call the sizehint function of qspinwidget to obtain the default size (a rectangle space) of this component ).
Subcontrol SC: enumeration quantity. A complex part may consist of multiple child parts. The SC variable is used to obtain the coordinates and dimensions of the Child part.
Qstyleoption & OPT: different extra information may be required to calculate the size of different parts. qstyleoption encapsulates this information.
2. Create a New Style
Next we will use an example to introduce the entire process of creating a new style. Before programming, let's take a look at what the final result is. (The qspinbox class in QT is implemented through qspinwidget)
Effect of the default style:
New Style effects:
We can see that in the new style, our spinbox has a vertical display effect. Next we will follow the steps described above to create a new style.
1) Select the base class: We select the qwindowsstyle class as the base class of our new style class. Of course, you can also choose qmotifstyle. In this example, you can also choose qcommonstyle. We generally do not recommend that you use qcommonstyle as the base class, because qcommonstyle only implements some interface components. If you want to implement a complete style class, we need to re-write a lotCode.
2) reload-related functions: In this routine, we only modify the spinbox style. The implementation of this component (widget) is only related to the three functions of the qstyle class drawprimitive, drawcomplexcontrol, and qureysubcontrolmerics, therefore, we only need to reload the Code related to these three functions. next, comment on the key part of the code. Detailed code can be downloaded later.
Function for drawing buttons in the spinbox:
Void customstyle: drawprimitive (primitiveelement PE, Qpainter * P, Const qrect & R, Const qcolorgroup & CG, Sflags flags, Const qstyleoption & OPT) const { /* Pe_spinwidgetup, pe_spinwidgetdown indicates the bottom and top buttons in the spinbox, The following code sets the triangles in the two buttons to the left and right respectively */ If (PE = pe_spinwidgetup) | (PE = pe_spinwidgetdown )){ Int fw = pixelmetric (pm_defaframeframewidth, 0); // FW indicates the Border width. The default value is 2. Qrect BR; // The button boundary rectangle on the spinbox is not the boundary rectangle of the spinbox. BR. setrect (R. X () + FW, R. Y () + FW, R. Width ()-fw * 2, R. Height ()-fw * 2 ); P-> fillrect (BR, CG. Brush (qcolorgroup: button )); Int x = R. X (), Y = R. Y (), W = R. Width (), H = R. Height (); Int Sw = W-4; Int SH = Sw/2 + 2; // must have empty row at foot of Arrow Int SX = x + W/2-Sw/2-1; Int Sy = Y + H/2-SH/2-1;
Qpointarray; /* Set the coordinates of the three points of the triangle. modifying these three points can make the triangle in the qspinbox display any shape, The following settings make the arrow represented by the triangle to the left and right respectively. */ If (PE = pe_spinwidgetdown) A. setpoints (3, 0, SH/2, sw-1, 1, sw-1, sh-1 ); Else A. setpoints (3, 0, 1, 0, sh-1, sw-1, SH/2 ); ........... P-> drawpolygon (a); // draw a triangle } Else if (PE = pe_buttonbevel) | (PE = pe_buttoncommand) | (PE = pe_buttontool) | (PE = pe_buttondropdown) | (PE = pe_headersection )) {// Various effects of the draw Button make it look convex or concave. Qdrawshadepanel (P, R, CG, flags & (style_sunken | style_down | style_on ), 1, & CG. Brush (qcolorgroup: button )); } Else { /* For the painting of other basic graphic elements (primitiveelement), we will not deal with it, but simply call the function of the parent class. */ Qwindowsstyle: drawprimitive (PE, P, R, CG, flags, OPT ); } }
|
Function for drawing the entire spinbox:
Void customstyle: drawcomplexcontrol (complexcontrol Control, Qpainter * P, Const qwidget * widget, Const qrect & R, Const qcolorgroup & CG, Sflags flags, Scflags controls, Scflags active, Const qstyleoption & OPT) const { // The following Code makes the spinwidget display a vertical display style instead of a normal horizontal display. If (control = cc_spinwidget ){ Const qspinwidget * Sw = (const qspinwidget *) widget; // Draw the up button. The default value of controls is SC _all, that is, draw the entire spinwidget. If (controls & SC _spinwidgetup ){
If (SW-> buttonsymbols () = qspinwidget: plusminus) Pe = pe_spinwidgetplus; // use the plus or minus sign.
|
Else Pe = pe_spinwidgetup; // use a triangle
|
Qrect Re = Sw-> uprect (); Qcolorgroup UCG = Sw-> isupenabled ()? CG: Sw-> palette (). Disabled (); Drawprimitive (pe_buttonbevel, P, re, UCG, flags); // draw the border of the button Drawprimitive (PE, P, re, UCG, flags); // draw button } // Draw the left button. If (controls & SC _spinwidgetdown ){ /* Similar to the draw down button */ } } Else {// calls the parent class function for processing other complex control components except the spinbox Qwindowsstyle: drawcomplexcontrol (control, P, widget, R, CG, flags, controls, active, OPT ); } }
|
Obtains the layout information of each child part in a widget. This function controls the appearance of a widget.
Qrect customstyle: querysubcontrolmetrics (complexcontrol Control, Const qwidget * widget, Subcontrol SC, Const qstyleoption & OPT) const { If (control = cc_spinwidget ){ Int fw = pixelmetric (pm_spinboxframewidth, widget ); /* Qsize defines the size of a two-dimensional object, that is, width and height. The coordinate type is qcoord and is defined as Int )*/ Qsize BS; // BS indicates the size of each button. Because there are two buttons, divide them by 2. BS. setwidth (widget-> width ()/2-fw ); If (BS. Width () <8) BS. setwidth (8 ); /* Set the button height to qmin {1.6 times the button width and 1/4 of the part height} BS. setheight (qmin (BS. Width () * 8/5, widget-> height ()/4 )); BS = BS. expandedto (qapplication: globalstrut ());
Int x = fw; Int y, Ly, Ry; Y = widget-> height ()-X-bs. Height (); Ly = fw; Ry = Y-fw; // The coordinates of each sub-part of qspinwidget are defined below. Switch (SC ){ Case SC _spinwidgetup: // Returns the coordinates of the right button. Return qrect (x + BS. Width (), y, BS. Width (), BS. Height ()); Case SC _spinwidgetdown: // Returns the coordinates of the left button. Return qrect (X, Y, BS. Width (), BS. Height ()); Case SC _spinwidgetbuttonfield: // Returns the total area size of the two buttons. Return qrect (X, Y, widget-> width ()-2 * Fw, BS. Height ()); Case SC _spinwidgeteditfield: /* Return the coordinate information of the Editable box */ Return qrect (FW, Ly, widget-> width ()-2 * Fw, ry ); Case SC _spinwidgetframe: // Returns the coordinates of the entire spinbox. Return widget-> rect (); Default: Break; } } Else {// call the parent class function to process the layout information of other components. Return qwindowsstyle: querysubcontrolmetrics (control, widget, SC, OPT ); } Return qrect (); }
|
3. Use a new style
There are two ways to use the new style, one is as a plug-in, and the other is directly used in the application. As a plug-in, you can use the new style without modifying the code or re-compiling. This article focuses on how to create a style, so we use the first method. This method is simple. You only need to include the header file of the corresponding Style Class in the application, and then set the first executable code of the main () function to qapplication: setstyle (New mystyle ()) you can.
Let's take a small example to see the effect.
# I nclude <qapplication. h> # I nclude <qspinbox. h> # I nclude "customstyle. H" Int main (INT argc, char ** argv) { Qapplication: setstyle (New customstyle (); // use the new style class to draw the interface. Qapplication A (argc, argv ); Qspinbox spin (0, 15 ); Spin. Resize (20,100 ); A. setmainwidget (& spin ); Spin. Show (); Return a.exe C (); }
|
Then compile and run the program to see the effect.
Compile and use qmake in PS. QT. The procedure is as follows:
- Create source program
- Run qmake-project in the same directory
- Qmake
- Make
- Run the executable program.
4. Further work
1) default size: A careful friend may see the above Code: spin. resize (20,100), which sets the length of the spinbox to 20 pixels and the width to 100 pixels. Without this sentence, the result will be a mess, and the two buttons will be almost invisible.
Because the default display of QT is horizontal and vertical display is not taken into account at all.
If you want to make the spinbox look narrow by default and the width is high, you need to modify the sizehint function in the qspinbox class. This function is used to set the default size of the widget. In QT, almost every GUI component class has the sizehint function to set its own default length and width.
Vertical text display: In this example, although the control spinbox achieves vertical display, the text is still horizontally displayed. Therefore, to achieve real vertical display, you need to understand the text display mechanism of QT. These jobs make sense, because the linguistic traditions of some ethnic groups (such as mengwen) are displayed vertically, and there is no system that truly meets this requirement. I am now looking at the qt-x11-free-3.2.2 source code, the current text display mechanism only a preliminary understanding, has not really figured out, very hope and interested friends exchange, learning.