Neverendingo (Talk | contribs) m (Text replace - "<code ruby>" to "<syntaxhighlight lang="ruby">") |
|||
| Line 26: | Line 26: | ||
The '''<tt>CannonField</tt>''' now has a force value in addition to the angle. | The '''<tt>CannonField</tt>''' now has a force value in addition to the angle. | ||
| − | < | + | <syntaxhighlight lang="ruby"> |
signals 'angleChanged(int)', 'forceChanged(int)' | signals 'angleChanged(int)', 'forceChanged(int)' | ||
slots 'setAngle(int)', 'setForce(int)' | slots 'setAngle(int)', 'setForce(int)' | ||
| Line 33: | Line 33: | ||
The interface to the force follows the same practice as for the angle. | The interface to the force follows the same practice as for the angle. | ||
| − | < | + | <syntaxhighlight lang="ruby"> |
def initialize(parent = nil) | def initialize(parent = nil) | ||
super() | super() | ||
| Line 47: | Line 47: | ||
The force '''<tt>@currentForce</tt>''' is initialized to zero. | The force '''<tt>@currentForce</tt>''' is initialized to zero. | ||
| − | < | + | <syntaxhighlight lang="ruby"> |
def setAngle(angle) | def setAngle(angle) | ||
if angle < 5 | if angle < 5 | ||
| Line 67: | Line 67: | ||
We have made a slight change in the '''<tt>setAngle()</tt>''' function. It repaints only the portion of the widget that contains the cannon. | We have made a slight change in the '''<tt>setAngle()</tt>''' function. It repaints only the portion of the widget that contains the cannon. | ||
| − | < | + | <syntaxhighlight lang="ruby"> |
def setForce(force) | def setForce(force) | ||
if force < 0 | if force < 0 | ||
| Line 83: | Line 83: | ||
The implementation of '''<tt>setForce()</tt>''' is quite similar to that of '''<tt>setAngle()</tt>'''. The only difference is that because we don't show the force value, we don't need to repaint the widget. | The implementation of '''<tt>setForce()</tt>''' is quite similar to that of '''<tt>setAngle()</tt>'''. The only difference is that because we don't show the force value, we don't need to repaint the widget. | ||
| − | < | + | <syntaxhighlight lang="ruby"> |
def paintEvent(event) | def paintEvent(event) | ||
painter = Qt::Painter.new(self) | painter = Qt::Painter.new(self) | ||
| Line 100: | Line 100: | ||
We paint as in Chapter 9. | We paint as in Chapter 9. | ||
| − | < | + | <syntaxhighlight lang="ruby"> |
def cannonRect() | def cannonRect() | ||
result = Qt::Rect.new(0, 0, 50, 50) | result = Qt::Rect.new(0, 0, 50, 50) | ||
| Line 116: | Line 116: | ||
The constructor is mostly the same, but some new bits have been added. | The constructor is mostly the same, but some new bits have been added. | ||
| − | < | + | <syntaxhighlight lang="ruby"> |
force = LCDRange.new() | force = LCDRange.new() | ||
force.setRange(10, 50) | force.setRange(10, 50) | ||
| Line 123: | Line 123: | ||
We add a second '''<tt>LCDRange</tt>''', which will be used to set the force. | We add a second '''<tt>LCDRange</tt>''', which will be used to set the force. | ||
| − | < | + | <syntaxhighlight lang="ruby"> |
connect(force, SIGNAL('valueChanged(int)'), | connect(force, SIGNAL('valueChanged(int)'), | ||
cannonField, SLOT('setForce(int)')) | cannonField, SLOT('setForce(int)')) | ||
| Line 132: | Line 132: | ||
We connect the '''<tt>force</tt>''' widget and the '''<tt>cannonField</tt>''' widget, just like we did for the '''<tt>angle</tt>''' widget. | We connect the '''<tt>force</tt>''' widget and the '''<tt>cannonField</tt>''' widget, just like we did for the '''<tt>angle</tt>''' widget. | ||
| − | < | + | <syntaxhighlight lang="ruby"> |
leftLayout = Qt::VBoxLayout.new() | leftLayout = Qt::VBoxLayout.new() | ||
leftLayout.addWidget(angle) | leftLayout.addWidget(angle) | ||
| Line 146: | Line 146: | ||
In Chapter 9, we put '''<tt>angle</tt>''' in the lower-left cell of the layout. Now we want to have two widgets in that cell, so we make a vertical box, put the vertical box in the grid cell, and put each of '''<tt>angle</tt>''' and '''<tt>range</tt>''' in the vertical box. | In Chapter 9, we put '''<tt>angle</tt>''' in the lower-left cell of the layout. Now we want to have two widgets in that cell, so we make a vertical box, put the vertical box in the grid cell, and put each of '''<tt>angle</tt>''' and '''<tt>range</tt>''' in the vertical box. | ||
| − | < | + | <syntaxhighlight lang="ruby"> |
force.setValue(25) | force.setValue(25) | ||
</code> | </code> | ||
Contents |
Languages: عربي | Asturianu | Català | Česky | Kaszëbsczi | Dansk | Deutsch | English | Esperanto | Español | Eesti | فارسی | Suomi | Français | Galego | Italiano | 日本語 | 한국어 | Norwegian | Polski | Português Brasileiro | Română | Русский | Svenska | Slovenčina | Slovenščina | српски | Türkçe | Tiếng Việt | Українська | 简体中文 | 繁體中文
| Tutorial Series | Qt4 Ruby Tutorial |
| Previous | Tutorial 9 - With Cannon You Can |
| What's Next | Tutorial 11 - Giving It a Shot |
| Further Reading | n/a |
Files:
In this example, we add a force control.
The CannonField now has a force value in addition to the angle.
signals 'angleChanged(int)', 'forceChanged(int)' slots 'setAngle(int)', 'setForce(int)' </code> The interface to the force follows the same practice as for the angle. <syntaxhighlight lang="ruby"> def initialize(parent = nil) super() @currentAngle = 45 @currentForce = 0 setPalette(Qt::Palette.new(Qt::Color.new(250, 250, 200))) setAutoFillBackground(true) end </code> The force '''<tt>@currentForce</tt>''' is initialized to zero. <syntaxhighlight lang="ruby"> def setAngle(angle) if angle < 5 angle = 5 elsif angle > 70 angle = 70 end if @currentAngle == angle return end @currentAngle = angle update(cannonRect()) emit angleChanged(@currentAngle) end </code> We have made a slight change in the '''<tt>setAngle()</tt>''' function. It repaints only the portion of the widget that contains the cannon. <syntaxhighlight lang="ruby"> def setForce(force) if force < 0 force = 0 end if @currentForce == force return end @currentForce = force emit forceChanged(@currentForce) end </code> The implementation of '''<tt>setForce()</tt>''' is quite similar to that of '''<tt>setAngle()</tt>'''. The only difference is that because we don't show the force value, we don't need to repaint the widget. <syntaxhighlight lang="ruby"> def paintEvent(event) painter = Qt::Painter.new(self) painter.setPen(Qt::NoPen) painter.setBrush(Qt::Brush.new(Qt::blue)) painter.translate(0, height()) painter.drawPie(Qt::Rect.new(-35, -35, 70, 70), 0, 90 * 16) painter.rotate(-@currentAngle) painter.drawRect(Qt::Rect.new(30, -5, 20, 10)) painter.end() end </code> We paint as in Chapter 9. <syntaxhighlight lang="ruby"> def cannonRect() result = Qt::Rect.new(0, 0, 50, 50) result.moveBottomLeft(rect().bottomLeft()) return result end </code> The '''<tt>cannonRect()</tt>''' function returns the rectangle enclosing the cannon in widget coordinates. First we create a rectangle with the size 50 x 50 and then move it so its bottom-left corner is equal to the widget's own bottom-left corner. The [http://doc.qt.nokia.com/latest/qwidget.html#rect-prop Qt::Widget::rect()] function returns the widget's enclosing rectangle in the widget's own coordinates. The top-left corner of the rectangle is always (0, 0). '''[http://www.darshancomputing.com/qt4-qtruby-tutorial/tutorial/t10/t10.rb t10.rb]''' The constructor is mostly the same, but some new bits have been added. <syntaxhighlight lang="ruby"> force = LCDRange.new() force.setRange(10, 50) </code> We add a second '''<tt>LCDRange</tt>''', which will be used to set the force. <syntaxhighlight lang="ruby"> connect(force, SIGNAL('valueChanged(int)'), cannonField, SLOT('setForce(int)')) connect(cannonField, SIGNAL('forceChanged(int)'), force, SLOT('setValue(int)')) </code> We connect the '''<tt>force</tt>''' widget and the '''<tt>cannonField</tt>''' widget, just like we did for the '''<tt>angle</tt>''' widget. <syntaxhighlight lang="ruby"> leftLayout = Qt::VBoxLayout.new() leftLayout.addWidget(angle) leftLayout.addWidget(force) gridLayout = Qt::GridLayout.new() gridLayout.addWidget(quit, 0, 0) gridLayout.addLayout(leftLayout, 1, 0) gridLayout.addWidget(cannonField, 1, 1, 2, 1) gridLayout.setColumnStretch(1, 10) </code> In Chapter 9, we put '''<tt>angle</tt>''' in the lower-left cell of the layout. Now we want to have two widgets in that cell, so we make a vertical box, put the vertical box in the grid cell, and put each of '''<tt>angle</tt>''' and '''<tt>range</tt>''' in the vertical box. <syntaxhighlight lang="ruby"> force.setValue(25) </code> We initialize the force value to 25. === Running the Application === We now have a force control. === Exercises === Make the size of the cannon barrel be dependent on the force. Put the cannon in the bottom-right corner. Try adding a better keyboard interface. For example, make + and - increase and decrease the force and enter shoot. If you're bothered by the way the '''<tt>Left</tt>''' and '''<tt>Right</tt>''' keys work, change that too. [Hint: Reimplement [http://doc.qt.nokia.com/latest/qwidget.html#keyPressEvent Qt::Widget::keyPressEvent()].] [[Category:Ruby]]