Найти - Пользователи
Полная версия: Отслеживаение приобретения/потери фокуса виджета
Начало » GUI » Отслеживаение приобретения/потери фокуса виджета
1 2
mitya_s_v
Хочу обрабатывать приобретение/потерю фокуса своего виджета. Для QLineEdit способ работает, а вот для самодельного QSelectPath нет, почему так происходит, ну или как выйти из этой ситуации?
import sys
from PyQt4 import QtGui, QtCore
class Example(QtGui.QWidget):
    def __init__(self):
        super(Example, self).__init__()
        self.initUI()
        self.inFocus = ('', '')  # Элемент (и его данные), который последним был в фокусе
    def initUI(self):
        self.setGeometry(300, 300, 280, 170)
        self.setWindowTitle('Hello!')
        self.a = QtGui.QLineEdit(self)
        self.a.installEventFilter(self)
        self.a.move(60, 50)
        self.a.setFocus()
        self.b = QSelectPath(self)
        self.b.installEventFilter(self)
        self.b.move(60, 100)
    def eventFilter(self, obj, event):
        if obj == self.inFocus[0]:
            if event.type() == QtCore.QEvent.FocusOut:
                print('Фокус потерян')
        else:
            if event.type() == QtCore.QEvent.FocusIn:
                self.inFocus = (obj, obj.text())
                print('В фокусе')
        return False
class QSelectPath(QtGui.QWidget):
    """
    Виджет для выбора пути к папке
    """
    def __init__(self, parent=None):
        super(QSelectPath, self).__init__(parent)
        self.buildWidget()
    def buildWidget(self):
        mainLayout = QtGui.QHBoxLayout()
        mainLayout.setContentsMargins(0, 0, 0, 0)  # Убираем внешние отступы у компановщика
        self.path = QtGui.QLineEdit(self)
        self.path.setReadOnly(True)
        overview = QtGui.QPushButton('Обзор', self)
        self.connect(overview, QtCore.SIGNAL('clicked()'), self.chooseFile)
        mainLayout.addWidget(self.path)
        mainLayout.addWidget(overview)
        self.setLayout(mainLayout)
    def chooseFile(self):
        """
        Открывает диалоговое окно выбора папки
        """
        path = QtGui.QFileDialog.getExistingDirectory(self, 'Выберите папку')
        if path:
            self.path.setText(path)
    def text(self):
        return self.path.text()
    def setText(self, string):
        self.path.setText(string)
if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    window = Example()
    window.show()
    sys.exit(app.exec_())
Rodegast
self.b.setFocusPolicy(QtCore.Qt.StrongFocus)
mitya_s_v
Rodegast
Добавил это к своему коду и ничего не изменилось.
Rodegast
Ну ладно… Вот тебе полный вариант.
import sys
from PyQt4 import QtGui, QtCore
class Example(QtGui.QWidget):
    def __init__(self):
        super(Example, self).__init__()
        self.initUI()
        self.inFocus = ('', '')  # Элемент (и его данные), который последним был в фокусе
    def initUI(self):
        self.setGeometry(300, 300, 280, 170)
        self.setWindowTitle('Hello!')
        self.a = QtGui.QLineEdit(self)
        self.a.installEventFilter(self)
        self.a.move(60, 50)
        self.a.setFocus()
        self.b = QSelectPath(self)
        self.b.setFocusPolicy(QtCore.Qt.StrongFocus)
        self.b.installEventFilter(self)
        self.b.move(60, 100)
    def eventFilter(self, obj, event):
        if obj == self.inFocus[0]:
            if event.type() == QtCore.QEvent.FocusOut:
                print('Фокус потерян')
        else:
            if event.type() == QtCore.QEvent.FocusIn:
                self.inFocus = (obj, obj.text())
                print('В фокусе')
        return False
class QSelectPath(QtGui.QWidget):
    """
    Виджет для выбора пути к папке
    """
    def __init__(self, parent=None):
        super(QSelectPath, self).__init__(parent)
        self.buildWidget()
    def buildWidget(self):
        mainLayout = QtGui.QHBoxLayout()
        mainLayout.setContentsMargins(0, 0, 0, 0)  # Убираем внешние отступы у компановщика
        self.path = QtGui.QLineEdit(self)
        self.path.setReadOnly(True)
        self.path.setFocusPolicy(QtCore.Qt.NoFocus)
        overview = QtGui.QPushButton('Обзор', self)
        overview.setFocusPolicy(QtCore.Qt.NoFocus)
        self.connect(overview, QtCore.SIGNAL('clicked()'), self.chooseFile)
        mainLayout.addWidget(self.path)
        mainLayout.addWidget(overview)
        self.setLayout(mainLayout)
    def chooseFile(self):
        """
        Открывает диалоговое окно выбора папки
        """
        path = QtGui.QFileDialog.getExistingDirectory(self, 'Выберите папку')
        if path:
            self.path.setText(path)
    def text(self):
        return self.path.text()
    def setText(self, string):
        self.path.setText(string)
if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    window = Example()
    window.show()
    sys.exit(app.exec_())
mitya_s_v
Во, вот так уже работает. Спасибо!
Kyrym
Дабы не плодить темы.
Есть окно QWidget, в нём разные элементы (поля, кнопки и т.д.). По умолчанию при запуске программы становится активным самый первый элемент. Захотел изменить ситууацию, перевести фокус на нужное мне поле, например, self.pole_2. Прописал вот так:
 self.pole_2 = QLineEdit()
self.pole_2.setFocus()
и никакой реакции.
Потом в скобки класса прописал self, убрал метод setFocus() и всё заработало. Т.е. так:
 self.pole_2 = QLineEdit(self)
Получается, что setFocus() вообще не нужен.
Растолкуйте, пожалуйста, почему так? Т.е. как здесь работает self, и почему setFocus() не нужен (и когда его надо прописывать)?
KriO
Если в окне на какой-то кнопке будет установлен setAutoDefault(True), то фокус автоматически установится на эту кнопку, тогда на первый элемент фокус нужно будет установить принудительно, а так автоматически устанавливается фокус на первого потомка, которому в принципе можно установить фокус. Вы указали родителя своему первому элементу, окно стало знать, кому установить фокус. Еще, если в окне есть стандартные кнопки QButtonBox, то фокус автоматически установится на первую кнопку в этом боксе.
Kyrym
А как здесь передать фокус полю 1?
 # Python 3
# -*- coding: utf-8 -*-
import sys
from PyQt4 import QtCore, QtGui
from PyQt4.QtGui import (QWidget, qApp, QAction, QApplication, QHBoxLayout, QVBoxLayout,
                             QGridLayout, QLabel, QLineEdit, QTextEdit, QPushButton, QComboBox,
                             QCheckBox, QRadioButton, QFrame, QScrollArea, QTabWidget, QSizePolicy,
                             QGroupBox)
from PyQt4.QtGui import QIcon, QPixmap, QPalette, QTextCursor
from PyQt4.QtCore import QSize
# ЦВЕТА ПОЛЕЙ
sss_vivod = ("background-color: #456173; color: #f2f2f0; font: 14pt 'Courier New'")
# ГРАФИКА
class Window(QWidget):
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        self.resize(200, 200) # шир / выс окна
        self.setWindowTitle('Заголовок') # Заголовок
        
        # БЛОК РАЗМЕТКИ
        vbox = QVBoxLayout()
        vbox_1 = QVBoxLayout()
        # --- ---
        viewport_1 = QWidget()
        viewport_1.setLayout(vbox_1)
        
        self.pole_1 = QLineEdit(self)
        self.pole_1.setFocus()
        vbox_1.addWidget(self.pole_1)
        # ---
        self.pole_2 = QLineEdit()
        vbox_1.addWidget(self.pole_2)
        viewport_2 = QWidget()
        # --- ---
        self.tab = QTabWidget()
        self.tab.addTab(viewport_1, 'Вкладка 1')
        self.tab.addTab(viewport_2, 'Вкладка 2')
        vbox.addWidget(self.tab)
        
        # ---
        self.setLayout(vbox)
   
# КОНЕЦ
if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = Window()   
    window.show()
    sys.exit(app.exec_())
    
 
PEHDOM
Kyrym
А как здесь передать фокус полю 1?
та также идем и ичтаем сначала документацию, http://doc.crossplatform.ru/qt/4.8.x/html-qt/qwidget.html#setFocus
Gives the keyboard input focus to this widget (or its focus proxy) if this widget or one of its parents is the active window
перевод:
Дает фокус ввода с клавиатуры для этого виджета (или его фокус-прокси), если этот виджет или один из его родителей является активным окном
вот в таком виже работает:
  # Python 3
# -*- coding: utf-8 -*-
import sys
from PyQt4 import QtCore, QtGui
from PyQt4.QtGui import (QWidget, qApp, QAction, QApplication, QHBoxLayout, QVBoxLayout,
                             QGridLayout, QLabel, QLineEdit, QTextEdit, QPushButton, QComboBox,
                             QCheckBox, QRadioButton, QFrame, QScrollArea, QTabWidget, QSizePolicy,
                             QGroupBox)
from PyQt4.QtGui import QIcon, QPixmap, QPalette, QTextCursor
from PyQt4.QtCore import QSize
# ЦВЕТА ПОЛЕЙ
sss_vivod = ("background-color: #456173; color: #f2f2f0; font: 14pt 'Courier New'")
# ГРАФИКА
class Window(QWidget):
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        self.resize(200, 200) # шир / выс окна
        self.setWindowTitle('Заголовок') # Заголовок
        # БЛОК РАЗМЕТКИ
        vbox = QVBoxLayout()
        vbox_1 = QVBoxLayout()
        # --- ---
        viewport_1 = QWidget(self)
        viewport_1.setLayout(vbox_1)
        self.pole_1 = QLineEdit(self)
        self.pole_1.setFocus()
        vbox_1.addWidget(self.pole_1)
        # ---
        self.pole_2 = QLineEdit()
        vbox_1.addWidget(self.pole_2)
        viewport_2 = QWidget()
        # --- ---
        self.tab = QTabWidget(self)
        self.tab.addTab(viewport_1, 'Вкладка 1')
        self.tab.addTab(viewport_2, 'Вкладка 2')
        vbox.addWidget(self.tab)
        # ---
        self.setLayout(vbox)
# КОНЕЦ
if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = Window()
    window.show()
    sys.exit(app.exec_())
а теперь поиграем в игру найди две разницы с вашим кодом.

Kyrym
Во вьюпорт я пробовал ставить self, а в QTabWidget - нет.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB