如何将父窗口小部件焦点重定向到子窗口小部件?

时间:2019-09-10 07:24:12

标签: c++ qt user-interface widget focus

有一个名为FloatingPointPropertyEditor的简单类。它继承自QWidget,并包含一个带有浮点数验证器的QLineEdit实例。

class FloatingPointPropertyEditor : public QWidget
{
    Q_OBJECT

    // ...

private:
    QLineEdit* m_lineEdit;
};

问题是我必须将FloatingPointPropertyEditor实例的焦点重定向到内部QLineEdit实例,然后选择其中的所有文本。也就是说,当FloatingPointPropertyEditor成为焦点时,用户已经可以在QLineEdit实例中输入文本,而无需先单击它。您能解释一下我该怎么做吗?

1 个答案:

答案 0 :(得分:2)

来自Qt。 doc。关于QWidget::focusPolicy

  

focusPolicy:Qt :: FocusPolicy

     

此属性保存小部件接受键盘焦点的方式

     

如果窗口小部件通过制表键接受键盘焦点,则策略为Qt :: TabFocus;如果窗口小部件通过单击接受焦点,则策略为Qt :: ClickFocus;如果窗口小部件同时接受两者,则策略为Qt :: StrongFocus;如果窗口小部件接受两者,Qt :: NoFocus(默认值)它根本不接受焦点。

     

如果小部件处理键盘事件,则必须为其启用键盘焦点。通常这是从小部件的构造函数完成的。例如,QLineEdit构造函数调用setFocusPolicy(Qt :: StrongFocus)。

     

如果窗口小部件具有焦点代理,则焦点策略将传播给它。

关于提到的焦点代理,关于QWidget::setFocusProxy()

  

void QWidget :: setFocusProxy(QWidget * w)

     

将小部件的焦点代理设置为小部件w。如果w为nullptr,则该函数会将此小部件重置为没有焦点代理。

     

某些小部件可以“具有焦点”,但是可以创建子小部件(例如QLineEdit)来实际处理焦点。在这种情况下,小部件可以将行编辑设置为其焦点代理。

     

setFocusProxy()设置在“此小部件”获得焦点时实际上将获得焦点的小部件。如果存在焦点代理,则setFocus()和hasFocus()在焦点代理上运行。


TL; DR

QWidget的默认焦点策略是Qt::NoFocusQLineEdit的默认焦点策略是Qt::StrongFocus。有了它,它应该可以立即使用(尽管有关setFocusProxy()的文档使此恕我直言并不明显)。

可以肯定的是,我做了一个小型演示testQWidgetFocus.cc

#include <QtWidgets>

class Editor: public QWidget {

  private:
    QHBoxLayout _qHBox;
    QLineEdit _qEdit;
    QPushButton _qBtn0;

  public:
    Editor(QWidget *pQParent = nullptr):
      QWidget(pQParent),
      _qBtn0(">|<")
    {
      _qHBox.addWidget(&_qEdit, 1);
      _qBtn0.setFocusPolicy(Qt::NoFocus); 
      _qHBox.addWidget(&_qBtn0);
      setLayout(&_qHBox);
      // signal handler
      connect(&_qBtn0, &QPushButton::clicked,
        [&](bool) { _qEdit.clear(); });
    }
    virtual ~Editor() = default;
    Editor(const Editor&) = delete;
    Editor& operator=(const Editor&) = delete;

};

int main(int argc, char **argv)
{
  qDebug() << "Qt Version:" << QT_VERSION_STR;
  QApplication app(argc, argv);
  QWidget qWinMain;
  QFormLayout qForm;
  QLineEdit qEdit1;
  qForm.addRow("QLineEdit:", &qEdit1);
  Editor qEdit2;
  qForm.addRow("Editor:", &qEdit2);
  qDebug() << "qEdit2.focusPolicy():" << qEdit2.focusPolicy();
  qDebug() << "qEdit2.focusProxy():" << qEdit2.focusProxy();
  Editor qEdit3;
  qForm.addRow("Editor:", &qEdit3);
  qWinMain.setLayout(&qForm);
  qWinMain.show();
  return app.exec();
}

输出:(在VS2017中编译,Qt 5.13)

Qt Version: 5.13.0
qEdit2.focusPolicy(): Qt::NoFocus
qEdit2.focusProxy(): QWidget(0x0)

Snapshot of testQWidgetFocus

Snapshot of testQWidgetFocus (after pressing Tab)

Snapshot of testQWidgetFocus (after pressing Tab)

输出:(在cygwin64中编译)

$ g++ --version
g++ (GCC) 7.4.0

$ qmake-qt5 testQWidgetFocus.pro

$ make && ./testQWidgetFocus  
g++ -c -fno-keep-inline-dllexport -D_GNU_SOURCE -pipe -O2 -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -I. -isystem /usr/include/qt5 -isystem /usr/include/qt5/QtWidgets -isystem /usr/include/qt5/QtGui -isystem /usr/include/qt5/QtCore -I. -I/usr/lib/qt5/mkspecs/cygwin-g++ -o testQWidgetFocus.o testQWidgetFocus.cc
g++  -o testQWidgetFocus.exe testQWidgetFocus.o   -lQt5Widgets -lQt5Gui -lQt5Core -lGL -lpthread 
Qt Version: 5.9.4
qEdit2.focusPolicy(): Qt::FocusPolicy(NoFocus)
qEdit2.focusProxy(): QWidget(0x0)

Snapshot of testQWidgetFocus (in X11)

Snapshot of testQWidgetFocus (after pressing Tab)

Snapshot of testQWidgetFocus (after pressing Tab)

注意:

我更改了涉及的QPushButton的重点政策。因此,它会在跳跳中被跳过(但仍然可以通过单击鼠标来使用)。在不更改其焦点策略的情况下,也可以在跳格中考虑它。


构建脚本:

CMakeLists.txt

project(QWidgetFocus)

cmake_minimum_required(VERSION 3.10.0)

set_property(GLOBAL PROPERTY USE_FOLDERS ON)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

find_package(Qt5Widgets CONFIG REQUIRED)

include_directories("${CMAKE_SOURCE_DIR}")

add_executable(testQWidgetFocus
  testQWidgetFocus.cc)
target_link_libraries(testQWidgetFocus
  Qt5::Widgets)

# define QT_NO_KEYWORDS to prevent confusion between of Qt signal-slots and
# other signal-slot APIs
target_compile_definitions(testQWidgetFocus PUBLIC QT_NO_KEYWORDS)

testQWidgetFocus.pro

SOURCES = testQWidgetFocus.cc

QT += widgets