Can't get focus back in a TextField
-
I have a simple QML form that contains one TextField, some buttons, labels and a clickable link (mouse area). The TextField works fine until I open a child form (via QQuickView inside a QDialog using PyQt5) by clicking clicking on a MouseArea. After the second form is closed the TextField can no longer get the input focus.
I used the following to check the focus in the TextField:
@
text: activeFocus ? "I have active focus!" : "I do not have active focus"
@I have tried setting the "focus" to true from code when the child form is closed but that doesn't help.
Is there something fundamental that I am missing? How can I return the focus to the TextField on the first form when the child form is closed?
-
I am not sure about the issue but you probably want to try calling forceActiveFocus() and not just setting the "focus" property as they mean different things.
-
Using forceActiveFocus() doesn't help either. I will make a miminal example.
By the way, where is the detailed documentation for forceActiveFocus()?
"The documentation for 5.1 is missing.":http://qt-project.org/doc/qt-5.1/qtquick/qquickitem.html#forceActiveFocus -
Here is a working (or not as is the case here) example. When run from Qt Creator (qmlscene) it works as expected. When run from Python using QQuickView, the TextField in parent.qml does not get the focus back after the child window has been opened and closed.
@
// parent.qml
import QtQuick 2.1
import QtQuick.Controls 1.0Rectangle {
width: 640 height: 480 signal closed Button { text: qsTr("Open child window") anchors.horizontalCenter: parent.horizontalCenter anchors.verticalCenter: parent.verticalCenter onClicked: { child.visible = true } } TextField { id: text_field1 x: 93 y: 299 width: 471 height: 22 placeholderText: "Text Field" text: activeFocus ? "I have active focus!" : "I do not have active focus" } Child { id: child visible: false modality: Qt.WindowModal } Button { id: button1 x: 488 y: 397 text: "Close" onClicked: { closed() } }
}
@@
// Child.qml
import QtQuick 2.1
import QtQuick.Controls 1.0
import QtQuick.Window 2.0Window {
width: 500
height: 300TextField { id: text_field1 x: 73 y: 189 width: 227 height: 22 placeholderText: "Text Field" } Button { id: button1 x: 373 y: 187 text: "OK" onClicked: { close() } }
}
@@
// example.py
import sys
from PyQt5 import QtWidgets, QtCore, QtQuick
from PyQt5.QtWidgets import QDialog, QWidgetdef qt5_qml_dir():
import os
import subprocess
qmldir = subprocess.check_output(["qmake", "-query",
"QT_INSTALL_QML"]).strip()
if len(qmldir) == 0:
raise RuntimeError('Cannot find QT_INSTALL_QML directory, "qmake -query '
+ 'QT_INSTALL_QML" returned nothing')
if not os.path.exists(qmldir):
raise RuntimeError("Directory QT_INSTALL_QML: %s doesn't exist" % qmldir)# On Windows 'qmake -query' uses / as the path separator # so change it to \\. if sys.platform.startswith('win'): import string qmldir = string.replace(qmldir, '/', '\\') return qmldir
class FocusTest(QDialog):
def __init__(self, parent=None): super(FocusTest, self).__init__(parent) self._parent = parent view = QtQuick.QQuickView() self._view = view view.setResizeMode(QtQuick.QQuickView.SizeViewToRootObject) # add the Qt Quick library path view.engine().addImportPath(qt5_qml_dir()) view.setSource(QtCore.QUrl('parent.qml')) w = QWidget.createWindowContainer(view, self) w.setMinimumSize(view.size()) w.setMaximumSize(view.size()) r = view.rootObject() self._root = r r.closed.connect(self.onClosed) def onClosed(self): self._view.close() self.accept()
if name=="main":
app = QtWidgets.QApplication(sys.argv)
s = "Test placeholder"
label = QtWidgets.QLabel(s, None)
label.setAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
label.setWindowTitle(s)
label.resize(800, 400)
label.show()s = FocusTest(label) s.accepted.connect(label.close) s.open() app.exec_()
@
-
I have "reported this as a bug.":https://bugreports.qt-project.org/browse/QTBUG-34414
-
Can't you just do it like this:
@
Child {
id: child
visible: false
modality: Qt.WindowModal
onVisibleChanged: {
if(visible === false){
text_field1.forceActiveFocus();
}
}
}
@That should set the focus back to the textfield if the Child is closed (and not visible any more). This is more or less what Jens was suggesting I think.
-
Thanks, I tried doing that from code but it didn't work. The above doesn't work either.
-
I have temporarily worked around this problem by hiding the parent form when the child form is shown and then showing it again when the child form is closed.