- C.4.1.1. Modify the method KTicTacToe::processClicks() so that the user is required to take turns between X and O.
- C.4.1.2. Reimplement KXOSquare::sizeHint() and use this method appropriately in the constructor of KTicTacToe. Compare what happens now when you resize the window to what happened before.
- C.4.1.3. What's the difference between QPen and QBrush? Examine the KDisc code and consult the Qt documentation.
- C.4.1.4. Get to know QPainter. Construct different QPens and QBrushes in KDisc. Draw figures other than a disc.
- C.4.1.5. Try using mousePressEvent() instead of mouseReleaseEvent() in KDisc. Can you tell the difference? Which feels right?
C.4.1.1. Modify the method KTicTacToe::processClicks() so that the user is required to take turns between X and O. Listing C.7 highlights the modified ktictactoe.cpp file.
Example C.7. Modified ktictactoe.cpp File 1
2 #include <qlayout.h>
3 #include <qlabel.h>
4
5 #include "ktictactoe.moc"
6
7 KTicTacToe::KTicTacToe (QWidget *parent, const char *name) :
8 QWidget (parent, name)
9 {
10 int row, col;
11
12 QGridLayout *layout = new QGridLayout (this, 4, 3);
13
14 const int rowlabel0 = 0, rowlabel1 = 0, collabel0 = 0, collabel1 = 2,
15 rowsquares0 = 1, rowsquares1 = 4, colsquares0 = 0, colsquares1 = 3;
16 for (row=rowsquares0; row<rowsquares1; row++)
17 for (col=colsquares0; col<colsquares1; col++)
18 {
19 KXOSquare *kxosquare = new KXOSquare (this);
20 layout->addWidget (kxosquare, row, col);
21 connect ( kxosquare,
22 SIGNAL (changeRequest (KXOSquare *, KXOSquare::State)),
23 SLOT (processClicks (KXOSquare *, KXOSquare::State)) );
24 }
25
26 QLabel *label = new QLabel ("Tic-Tac-Toe, this);
27 label->setAlignment (Qt::AlignCenter);
28 layout->addMultiCellWidget (label,
29 rowlabel0, rowlabel1,
30 collabel0, collabel1);
31 }
32
33 void
34 KTicTacToe::processClicks (KXOSquare *square, KXOSquare::State state)
35 {
36 //Chapter 4, Exercise 1
37 if (state!=previousstate)
38 {
39 square->newState (state);
40 previousstate=state;
41 }
42 }
43 |
C.4.1.2. Reimplement KXOSquare::sizeHint() and use this method appropriately in the constructor of KTicTacToe. Compare what happens now when you resize the window to what happened before. Listings C.8–C.10 demonstrate this.
Example C.8. Modified ktictactoe.h Method 1
2 #ifndef __KTICTACTOE_H__
3 #define __KTICTACTOE_H__
4
5 #include <qarray.h>
6 #include <qwidget.h>
7
8 #include "kxosquare.h"
9
10 /**
11 * KTicTacToe
12 * Draw and manage a Tic-Tac-Toe board using KXOSquare.
13 **/
14 class KTicTacToe : public QWidget
15 {
16 Q_OBJECT
17
18 public:
19 /**
20 * Create an empty game board.
21 **/
22 KTicTacToe (QWidget *parent, const char *name=0);
23
24
25 protected slots:
26 /**
27 * Process user input.
28 **/
29 void processClicks (KXOSquare *, KXOSquare::State);
30 };
31
32 #endif
33 Modified ktictactoe.cpp
34 #include <qlayout.h>
35 #include <qlabel.h>
36 #include "ktictactoe.moc"
37
38 KTicTacToe::KTicTacToe (QWidget *parent, const char *name) :
39 QWidget (parent, name)
40 {
41 int row, col;
42
43 QGridLayout *layout = new QGridLayout (this, 4, 3);
44
45 const int rowlabel0 = 0, rowlabel1 = 0, collabel0 = 0, collabel1 = 2,
46 rowsquares0 = 1, rowsquares1 = 4, colsquares0 = 0, colsquares1 = 3;
47
48 for (row=rowsquares0; row<rowsquares1; row++)
49 for (col=colsquares0; col<colsquares1; col++)
50 {
51 KXOSquare *kxosquare = new KXOSquare (this);
52 //Chapter 4, Exercise 2
53 kxosquare->setMinimumSize (kxosquare->sizeHint());
54
55 layout->addWidget (kxosquare, row, col);
56 connect ( kxosquare,
57 SIGNAL (changeRequest (KXOSquare *, KXOSquare::State)),
58 SLOT (processClicks (KXOSquare *, KXOSquare::State)) );
59 }
60
61 QLabel *label = new QLabel ("Tic-Tac-Toe", this);
62 label->setAlignment (Qt::AlignCenter);
63 layout->addMultiCellWidget (label,
64 rowlabel0, rowlabel1,
65 collabel0, collabel1);
66 }
67
68
69 void
70 KTicTacToe::processClicks (KXOSquare *square, KXOSquare::State state)
71 {
72 //In this simple example, just pass along the click to the appropriate
73 // square.
74 square->newState (state);
75 }
76 |
Example C.9. Modified kxosquare.h Method 1
2 #ifndef __KXOSQUARE_H__
3 #define __KXOSQUARE_H__
4
5
6 #include <qwidget.h>
7 #include <qsize.h>
8
9 /**
10 * KXOSquare
11 * Draws a square in one of three states: empty, with an X inside,
12 * or with an O inside.
13 **/
14 class KXOSquare : public QWidget
15 {
16 Q_OBJECT
17
18 public:
19 enum State {None=0, X=1, O=2};
20
21 /**
22 * Create the widget.
23 **/
24 KXOSquare (QWidget *parent, const char *name=0);
25
26 /**
27 * Chapter 4, Exercise 2
28 * Return a recommended size for this widget.
29 **/
30 QSize sizeHint() const;
31
32 public slots:
33 /**
34 * Change the state of the widget to <i>state</i>.
35 **/
36 void newState (State state);
37
38 signals:
39 /**
40 * The user has requested that the state be changed to <i>state</i>
41 * by clicking on the square.
42 **/
43 void changeRequest (KXOSquare *, KXOSquare::State state);
44
45 protected:
46 /**
47 * Draw the widget.
48 **/
49 void paintEvent (QPaintEvent *);
50
51 /**
52 * Process mouse clicks.
53 **/
54 void mousePressEvent (QMouseEvent *);
55
56 private:
57 State thestate;
58 };
59
60 #endif
61 |
Example C.10. Modified kxosquare.cpp Method 1
2 #ifndef __KXOSQUARE_H__
3 #define __KXOSQUARE_H__
4
5
6 #include <qwidget.h>
7 #include <qsize.h>
8
9 /**
10 * KXOSquare
11 * Draws a square in one of three state: empty, with an X inside,
12 * or with an O inside.
13 **/
14 class KXOSquare : public QWidget
15 {
16 Q_OBJECT
17
18 public:
19 enum State {None=0, X=1, O=2};
20
21 /**
22 * Create the widget.
23 **/
24 KXOSquare (QWidget *parent, const char *name=0);
25
26 /**
27 * Chapter 4, Exercise 2
28 * Return a recommended size for this widget.
29 **/
30 QSize sizeHint() const;
31
32 public slots:
33 /**
34 * Change the state of the widget to <i>state</i>.
35 **/
36 void newState (State state);
37
38 signals:
39 /**
40 * The user has requested that the state be changed to <i>state</i>
41 * by clicking on the square.
42 **/
43 void changeRequest (KXOSquare *, KXOSquare::State state);
44
45 protected:
46 /**
47 * Draw the widget.
48 **/
49 void paintEvent (QPaintEvent *);
50
51 /**
52 * Process mouse clicks.
53 **/
54 void mousePressEvent (QMouseEvent *);
55
56 private:
57 State thestate;
58 };
59
60 #endif
61 |
C.4.1.3. What's the difference between QPen and QBrush? Examine the KDisc code and consult the Qt documentation. C.4.1.4. Get to know QPainter. Construct different QPens and QBrushes in KDisc. Draw figures other than a disc. Listing C.11 lists the modified methods from kdisc.cpp.
Example C.11. Modified Methods from kdisc.cpp 1
2 void
3 KDisc::paintEvent (QPaintEvent *)
4 {
5 QPainter painter (this);
6
7 //Chapter 4, Exercise 4
8
9 painter.setPen ( QPen (QColor (200, 100, 0), 1) );
10 painter.setBrush ( QBrush (Qt::green, Qt::SolidPattern) );
11
12 painter.drawPie (discposition.x(), discposition.y(),
13 45, 45, 0, 4760);
14 }
15 void
16 KDisc::mouseMoveEvent (QMouseEvent *qmouseevent)
17 {
18
19 if (qmouseevent->state()==Qt::LeftButton)
20 {
21 //Chapter 4, Exercise 4
22 QPoint qpoint = qmouseevent->pos();
23 qpoint.setX(qpoint.x() - 45/2);
24 qpoint.setY(qpoint.y() - 45/2);
25 discposition = qpoint;
26 update();
27 }
28
29 }
30 |
C.4.1.5. Try using mousePressEvent() instead of mouseReleaseEvent() in KDisc. Can you tell the difference? Which feels right? | |