Qt/C++ - confused about caller/callee, object ownership
I am creating a GUI to manipulate a robot arm. The location of the arm can be described by 6 floats (describing the positions of the various arm joints.
The interface consists of a QGraphicsView with a diagram of the arm (which can be clicked to change the arm position - adjusting the 6 floats). The interface also has 6 lineEdit boxes, to also adjust those values separately.
When the graphics view is clicked, and when the line edit boxes are changed, I'd like the line edit boxes / graphics view to stay in synchronisation.
This brings me to confusion about how to store the 6 floats, and trigger events when they're updated. My current idea is this:
- The robot arm's location should be represented by a class, RobotArmLocation. Objects of this class then have methods such as obj.Shoul开发者_运维百科derRotation() and obj.SetShoulderRotation().
- The MainWindow has a single instance of RobotArmLocation.
Next is the bit I'm more confused about, how to join everything up. I am thinking:
The MainWindow has a ArmLocationChanged slot. This is signalled whenever the location object is changed.
The diagram class will have a SetRobotArmLocation(RobotArmLocation &loc). When the diagram is changed, it's free to change the location object, and fire a signal to the ArmLocationChanged slot.
- Likewise, changing any of the text boxes will fire a signal to that ArmLocationChanged slot. The slot then has code to synchronise all the elements.
This kind of seems like a mess to me, does anyone have any other suggestions? I've also thought of the following, does it have any merrit?
- The RobotArmLocation class has a ValueChanged slot, the diagram and textboxes can use that directly, and bypass the MainWindow directly (seems cleaner?)
thanks for any wisdom!
Except for really simple cases (e.g. a label that shows the value of a slider) my experience has been to stay away from inter-component signal/slot connections inside Qt Designer. Rather, have the component firing the signal of interest connect to a slog defined in the top level QWidget class you're subclassing (i.e. QMainWidow
, etc... let's just call it the Form
class). You can also go the other way: if you have a custom signal in the Form
class, you can connect it with Qt Designer to one of the public widget slots.
To be specific using your example:
- I'm going to assume that you have subclassed
QMainWindow
andQGraphicsView
. Let's call the subclassesRobotMainWindow
andRobotView
. RobotMainWindow
contains theQLineEdit
fields andRobotView
. The way you specifyRobotView
in Qt Designer is to insert aQWidget
and use the Promote to... feature to tell Qt that theQWidget
should be replaced at compile time with your customRobotView
.- Name the
QLineEdit
fieldsedit1
,edit2
...edit6
. - In the Qt Designer signal/slot editor define slots in
RobotMainWindow
to be called when the value in aQLineEdit
changes. There are some more elegant ways of doing this, but for simplicity let's say you define 6 slots namedsetValue1(float)
,setValue2(float)
, etc. - In the source code for
RobotMainWindow
, go declare and define these slots, such that they update your arm, shoulder, whatever. - Also in the source code, define a signal
valueChanged()
(or multiple for each field, your choice). Have the slots you definedemit valueChanged()
. - Back in Qt Designer you can now link the appropriate signal from each
QLineEdit
to the corresponding slot inRobotMainWindow
. - Back in the signal/slot editor add the
valueChanged()
signal to theRobotMainWindow
(so Qt Designer knows about it). Connect this signal to a new slot inRobotView
, using the procedure above, so it can update the rendering. - Repeat all of this for handling changes from
RobotView
to the editing fields (viaRobotMainWindow
.
In short, I think you'll find everything more straight-forward if your route the signals through your Form
subclass (which I think of as the Controller in MVC parlance).
精彩评论