An Improved Selectable, Sizable Graphic Box with Text

The visualsc project needs several types of graphic boxes (this project builds on this project: “Example of re-sizing a QGraphicsItem using Mouse events.”) One is to represent the state itself, where I preferred a shadowed box. The box has to be re-sizable and move-able. Another type of box needed is a text box. The text box is similar in that it needs to be re-sizable and move-able. But the text box should not have any lines around it, except when its being sized by the user. And it should not have a shadow.  The text box adds a complication with the addition of text. The boundingRect() defined what area Qt will draw but this must include the border lines and corner-grabbers, and we do not want these visual cues to cross over the text itself, so we need a margin when the graphic box is used as a text box.

Below is an example of the a graphic box when used to represent a state. It has a solid border line, a drop shadow on two sides, four cross-hairs for the user to grab with the mouse for re-sizing. The red colored cross hair is one that is currently selected by the mouse and ready to be dragged for box re-sizing.

Figure 1.

The next example is the graphic box when used to represent a text box that is being resized, the dotted line and cross-hairs are visible so the user can grab a corner with the mouse to re-size the box.

 

Figure 2.

The next example pulls it all together. The flash video below shows a state chart box (which is the standard box with drawn borders) holding a text box (which only has dotted lines when being manipulated). Additionally, the user can edit the text with a double click on the text box to bring up a text-edit box. The text-edit box is also this same graphic box but with the additional components of a QTextEditItem and a background image and background color.

Get the Flash Player to see this video.

The Design

You can find all the source code in the visualsc chart project. The relavant files are:

scgraphicsview/selectableboxgraphic.cpp
scgraphicsview/selectabletextblock.cpp
scgraphicsview/maskedtextedit.cpp

The SelectableBoxGraphic class forms the basis for several types of graphic boxes. Figure 1 shows the SelectableBoxGraphic with a solid line and drop-shadow. Figure 2 shows the same class but with no-line normally and with a dotted-line when the user is resizing. In both cases cross-hairs are shown at the four corners. The cross-hairs are provided a grab-points for the user to grab the corner and drag the size change to the box.

Figure 3. Box Design

Figure 3 shows the design of the graphic box (refer to the SelectableBoxGraphic::paint method).  So that the cross-hairs are drawn completely, they must be fully contained in the rectangle that is returned in SelectableBoxGraphic::boundingRect(). Because we want the cross-hairs to appear to be just outside the box, we must draw the box in a smaller area. This smaller area is defined with the _drawingWidth, _drawingHeight, _drawingOrginX, and _drawingOrigenY member variables.

QRectF SelectableBoxGraphic::getUsableArea() returns the area that can be used to draw text and other items without crossing one of the border lines. SelectableTextBlock inherits SelectableBoxGraphic and uses getUsableArea() to determine where text can be drawn.

Adding text to the box to make a text-block adds a level of complexity. To make the text-block resizable it is desirable to make the text-block derived class from SelectableBoxGraphic. This derived class (SelectableTextBlock) can then have an instance of a QGraphicsTextItem to provide an editable text field. However, QGraphicsTextItem does not provide a convenient method for limiting the display area of the text. So this is accomplished by creating a MaskedTextEdit which is a subclass of QGraphicsTextItem. MaskedTextEdit simply provides a clipping region so that the text itself is only visible within the confines of the usable area of the SelectableBoxGraphic. Otherwise, without this clipping region, the text would appear within the entire area of the box, so that the text could appear under the border lines and drop shadow.

Refer to MaskedTextEdit::setBoundingRect() and SelectableTextBlock::setSize(). In the MaskedTextEdit, we implement a paint() virtula method so we can set the clip region of the painter, then call the QGraphicsTextItem::paint() method with the modified painter. Now the text will not appear outside of the usable area of the text box.

 

Leave a Reply

Trackback this post  |  Subscribe to the comments via RSS Feed