Control子类对象焦点获取

  1. Button{
  2. id: btn
  3. width: 100
  4. height: 30
  5. focus: false
  6. background: Rectangle{
  7. border.color: btn.focus ? "red":"green"
  8. border.width: 2
  9. }
  10. //设置当前控件如何获取焦点
  11. /*
  12. Qt.TabFocus
  13. The control accepts focus by tabbing.
  14. Qt.ClickFocus
  15. The control accepts focus by clicking.
  16. Qt.StrongFocus
  17. The control accepts focus by both tabbing and clicking.
  18. Qt.WheelFocus
  19. The control accepts focus by tabbing, clicking, and using the mouse wheel.
  20. Qt.NoFocus
  21. The control does not accept focus.
  22. */
  23. // focusPolicy: Qt.StrongFocus //点击或者tab
  24. /*
  25. Control中设置聚焦原因(只读)
  26. focusReason:
  27. Qt.MouseFocusReason
  28. Qt.TabFocusReason
  29. Qt.BacktabFocusReason
  30. Qt.ActiveWindowFocusReason
  31. Qt.PopupFocusReason
  32. Qt.ShortcutFocusReason
  33. Qt.MenuBarFocusReason
  34. Qt.OtherFocusReason
  35. */
  36. onFocusChanged: {
  37. console.log("onFocusChanged: ", focus)
  38. }
  39. onFocusReasonChanged: {
  40. console.log("onFocusReasonChanged: ", focusReason)
  41. console.log("Qt.MouseFocusReason: ", Qt.MouseFocusReason)
  42. console.log("Qt.TabFocusReason: ", Qt.TabFocusReason)
  43. }
  44. Component.onCompleted: {
  45. console.log("focusPolicy: ", focusPolicy)
  46. console.log("Qt.StrongFocus: ", Qt.StrongFocus)
  47. }
  48. }

focus=false; focusPolicy=Qt.TabFocus; 按下tab键时触发focuschanged信号
image.png
当获取焦点开启时,控件默认是获取了焦点focus的,当focus=false后仍旧可以通过点击按钮或者tab键(默认的聚焦策略)可使得按钮获取到焦点,这和我们一般认为的focus=false后这个按键就不能再获取到焦点的认识有点出入,这里引入一个activeFocus活动焦点,这个才是当前获取到的真正有效的焦点,如果当focus=false后这个控件就必须再也不能通过点击、tab等方式获取到焦点的话,就需要通过Control的属性 focusPolicy进行设置使得按钮不能获取到焦点focusPolicy: Qt.NoFocus。需要修改Control子类对象获取焦点的方式通过修改focusPolicy进而实现(这个时候控件获取focus需要按照设置的策略去获取)。

  1. 该属性决定控件如何接收到焦点
  2. focusPolicy : enumeration
  3. Qt.TabFocus 通过tab
  4. The control accepts focus by tabbing.
  5. Qt.ClickFocus 通过鼠标点击
  6. The control accepts focus by clicking.
  7. Qt.StrongFocus 鼠标点击或者tab
  8. The control accepts focus by both tabbing and clicking.
  9. Qt.WheelFocus 控件通过tab键、单击和使用鼠标滚轮接受焦点
  10. The control accepts focus by tabbing, clicking, and using the mouse wheel.
  11. Qt.NoFocus 不能获取焦点,当focus=false时一般会结合该
  12. The control does not accept focus.
  1. 获取焦点原因(只读)
  2. [read-only] focusReason : enumeration
  3. Qt.MouseFocusReason 鼠标
  4. A mouse action occurred.
  5. Qt.TabFocusReason tab
  6. The Tab key was pressed.
  7. Qt.BacktabFocusReason
  8. A Backtab occurred. The input for this may include the Shift or Control keys; e.g. Shift+Tab.
  9. Qt.ActiveWindowFocusReason
  10. The window system made this window either active or inactive.
  11. Qt.PopupFocusReason
  12. The application opened/closed a pop-up that grabbed/released the keyboard focus.
  13. Qt.ShortcutFocusReason
  14. The user typed a label's buddy shortcut
  15. Qt.MenuBarFocusReason
  16. The menu bar took focus.
  17. Qt.OtherFocusReason
  18. Another reason, usually application-specific.

FocusScop

上面描述了一个控件如何获取focus以及如何修改获取focus的方式。下面描述如何控制多个控件的时候如何获取focus。

同级两个控件间焦点的获取

  1. Rectangle{
  2. id: rect
  3. width: 300
  4. height: 50
  5. Text {
  6. id: txt1
  7. focus: true
  8. text: qsTr("txt1 focus: "+txt1.focus + "; activeFocus: " + txt1.activeFocus)
  9. Component.onCompleted: {
  10. console.log("txt1 onCompleted")
  11. }
  12. }
  13. }
  14. Rectangle{
  15. id: rect2
  16. width: 300
  17. height: 50
  18. y: 50
  19. Text {
  20. id: txt2
  21. focus: true
  22. text: qsTr("txt2 focus: "+txt2.focus + "; activeFocus: " + txt2.activeFocus)
  23. Component.onCompleted: {
  24. console.log("txt2 onCompleted")
  25. }
  26. }
  27. }

image.png
从log中可以看出txt1后完成,focus赋给了后创建完成的txt1,这和qml的设计有关,且这个时候activeFocus也在txt1。

  1. Rectangle{
  2. id: rect
  3. width: 300
  4. height: 50
  5. focus: true
  6. Text {
  7. id: txt1
  8. focus: true
  9. text: qsTr("txt1 focus: "+txt1.focus + "; activeFocus: " + txt1.activeFocus+ "; rect focus: " + rect.focus +"; activeFocus: " + rect.activeFocus)
  10. Component.onCompleted: {
  11. console.log("txt1 onCompleted")
  12. }
  13. }
  14. Component.onCompleted: {
  15. console.log("rect onCompleted")
  16. }
  17. }
  18. Rectangle{
  19. id: rect2
  20. width: 300
  21. height: 50
  22. y: 50
  23. Text {
  24. id: txt2
  25. focus: true
  26. text: qsTr("txt2 focus: "+txt2.focus + "; activeFocus: " + txt2.activeFocus+ "; rect focus: " + rect2.focus +"; activeFocus: " + rect2.activeFocus)
  27. Component.onCompleted: {
  28. console.log("txt2 onCompleted")
  29. }
  30. }
  31. Component.onCompleted: {
  32. console.log("rect2 onCompleted")
  33. }
  34. }

image.png
尝试对Rectangle属性focus设置为true通过log可见无效,子控件不能通过父控件获取到焦点。

  1. FocusScope{
  2. id: rect
  3. width: 300
  4. height: 50
  5. focus: true
  6. Text {
  7. id: txt1
  8. focus: true
  9. text: qsTr("txt1 focus: "+txt1.focus + "; activeFocus: " + txt1.activeFocus)
  10. Component.onCompleted: {
  11. console.log("txt1 onCompleted")
  12. }
  13. }
  14. }
  15. FocusScope{
  16. id: rect2
  17. width: 300
  18. height: 50
  19. y: 50
  20. focus: true
  21. Text {
  22. id: txt2
  23. focus: true
  24. text: qsTr("txt2 focus: "+txt2.focus + "; activeFocus: " + txt2.activeFocus)
  25. Component.onCompleted: {
  26. console.log("txt2 onCompleted")
  27. }
  28. }
  29. }

image.png
修改子控件的父对象为FocusScope,通过log可见FocusScope的子控件都可以获取到焦点,活动焦点(焦点真正所在的控件)的获取与FocusScope的属性focus与控件创建完成的顺序相关,当两个FocusScope 的focus都设置为false时,两个子控件都可获取到焦点focus,但都没法获取到activefocus。当txt1对应的FocusScope的focus=false,txt2对应的FocusScope的focus=true时,txt1、2都可获取到focus,但是由于txt1对应的focus=false,即便txt1是后建立完成的,这时activeFocus也不会赋给txt1,会赋给临近创建的完成的txt2。FocusScope 的属性focus=true表示这个子控件真的能获取到这个活动焦点。
image.png

强制改变activeFocus

  1. forceActiveFocus(Qt::FocusReason reason)
  2. forceActiveFocus()

通过修改Item元素的方法forceActiveFocus() 使得控件强制获取到activeFocus。 activeFocus是只读属性,不可修改。

  1. FocusScope{
  2. id: rect2
  3. width: 300
  4. height: 50
  5. y: 50
  6. focus: true
  7. Text {
  8. id: txt2
  9. focus: true
  10. text: qsTr("txt2 focus: "+txt2.focus + "; activeFocus: " + txt2.activeFocus)
  11. Component.onCompleted: {
  12. console.log("txt2 onCompleted")
  13. }
  14. onFocusChanged: {
  15. console.log("txt2 focus: "+activeFocus)
  16. }
  17. }
  18. MouseArea{
  19. anchors.fill: parent
  20. onClicked: {
  21. // txt2.focus = true
  22. txt2.forceActiveFocus() //强制获取焦点
  23. }
  24. }
  25. }

当使用forceActiveFocus() 强制获取activeFocus时,设置FocusScope 属性focus= false 和Text属性focus=false是无效操作,控件仍旧能够获取到焦点和活动焦点。
从上面也可看出,多个控件可以同时获取到focus,所以判断focus是否为true来确认是否获取到焦点是不准确的,当判断activeFocus(这个操作有点像windows桌面选中多个图标是多个图标都获取到了focus,仅仅是感觉没细究)。

特殊指定控件状态切换

  1. // FocusScope
  2. Rectangle
  3. {
  4. id: rect
  5. width: 300
  6. height: 100
  7. focus: true
  8. Button {
  9. id: btn1
  10. width: 100
  11. height: 50
  12. focus: true
  13. background: Rectangle{
  14. // border.color: btn1.focus ? "red":"green"
  15. border.color: btn1.activeFocus ? "red":"green" //activeFocus体现了唯一性
  16. border.width: 2
  17. }
  18. }
  19. }
  20. // FocusScope
  21. Rectangle
  22. {
  23. id: rect2
  24. width: 300
  25. height: 100
  26. y: 150
  27. focus: true
  28. Button {
  29. id: btn2
  30. width: 100
  31. height: 50
  32. focus: true
  33. background: Rectangle{
  34. // border.color: btn2.focus ? "red":"green"
  35. border.color: btn2.activeFocus ? "red":"green"
  36. border.width: 2
  37. }
  38. }
  39. }

image.png
这里使用activeFocus在同级中只能一个控件唯一的获取到特性,这里同级的Rectangle 能区别activeFocus不是FocusScope实现的。可通过 鼠标点击和tab键进行选中控件的切换,这时默认focusPolicy决定的,当需要设置只能点击进行切换时,如下设置:

  1. // FocusScope
  2. Rectangle
  3. {
  4. id: rect
  5. width: 300
  6. height: 50
  7. focus: true
  8. Button {
  9. id: btn1
  10. width: 100
  11. height: 50
  12. focus: true
  13. focusPolicy: Qt.NoFocus
  14. background: Rectangle{
  15. // border.color: btn1.focus ? "red":"green"
  16. border.color: btn1.activeFocus ? "red":"green" //activeFocus体现了唯一性
  17. border.width: 2
  18. }
  19. onFocusChanged: {
  20. console.log("btn1 onFocusChanged: ", focus)
  21. }
  22. onActiveFocusChanged: {
  23. console.log("btn1 onActiveFocusChanged: ", activeFocus, "; focus: ", focus)
  24. }
  25. onClicked: {
  26. btn1.forceActiveFocus()
  27. }
  28. }
  29. }
  30. // FocusScope
  31. Rectangle
  32. {
  33. id: rect2
  34. width: 300
  35. height: 50
  36. y: 80
  37. focus: true
  38. Button {
  39. id: btn2
  40. width: 100
  41. height: 50
  42. focus: true
  43. focusPolicy: Qt.NoFocus
  44. background: Rectangle{
  45. // border.color: btn2.focus ? "red":"green"
  46. border.color: btn2.activeFocus ? "red":"green"
  47. border.width: 2
  48. }
  49. onFocusChanged: {
  50. console.log("btn2 onFocusChanged: ", focus)
  51. }
  52. onActiveFocusChanged: {
  53. console.log("btn2 onActiveFocusChanged: ", activeFocus, "; focus: ", focus)
  54. }
  55. onClicked: {
  56. btn2.forceActiveFocus()
  57. }
  58. }
  59. }

image.png
通过如下修改focusPolicy的也可做到这个效果:

  1. // FocusScope
  2. Rectangle
  3. {
  4. id: rect
  5. width: 300
  6. height: 50
  7. focus: true
  8. Button {
  9. id: btn1
  10. width: 100
  11. height: 50
  12. focus: true
  13. focusPolicy: Qt.ClickFocus
  14. background: Rectangle{
  15. // border.color: btn1.focus ? "red":"green"
  16. border.color: btn1.activeFocus ? "red":"green" //activeFocus体现了唯一性
  17. border.width: 2
  18. }
  19. onFocusChanged: {
  20. console.log("btn1 onFocusChanged: ", focus)
  21. }
  22. onActiveFocusChanged: {
  23. console.log("btn1 onActiveFocusChanged: ", activeFocus, "; focus: ", focus)
  24. }
  25. // onClicked: {
  26. // btn1.forceActiveFocus()
  27. // }
  28. }
  29. }
  30. // FocusScope
  31. Rectangle
  32. {
  33. id: rect2
  34. width: 300
  35. height: 50
  36. y: 80
  37. focus: true
  38. Button {
  39. id: btn2
  40. width: 100
  41. height: 50
  42. focus: true
  43. focusPolicy: Qt.ClickFocus
  44. background: Rectangle{
  45. // border.color: btn2.focus ? "red":"green"
  46. border.color: btn2.activeFocus ? "red":"green"
  47. border.width: 2
  48. }
  49. onFocusChanged: {
  50. console.log("btn2 onFocusChanged: ", focus)
  51. }
  52. onActiveFocusChanged: {
  53. console.log("btn2 onActiveFocusChanged: ", activeFocus, "; focus: ", focus)
  54. }
  55. // onClicked: {
  56. // btn2.forceActiveFocus()
  57. // }
  58. }
  59. }

image.png
在上的基础上修改focusPolicy: Qt.TabFocus可实现通过tab键切换的效果。