QLineEdit в ячейке QTableWdiget не теряет фокус - PullRequest
0 голосов
/ 25 апреля 2020

Я сейчас пытаюсь сделать графический интерфейс, используя PyQt5. До сих пор все работало нормально (в конце концов, у меня есть некоторый опыт в этом деле), но я уже несколько дней борюсь с этой проблемой и нигде не могу найти решение.

В моем Приложение Я отображаю FigureCanvas из matplotlib (вместе с различными другими виджетами), где у меня есть ключевое событие, связанное с функцией, которая выбирает точку щелчком мыши и сохраняет эту точку в QTableWidget. Тем не менее, я хочу, чтобы пользователь мог редактировать значение y, полученное с помощью валидатора, поэтому я изменил второй столбец с хранения QTableWidgetItem на виджет QLineEdit. Все работает, за исключением того, что когда я нажимаю клавишу ВВОД после редактирования виджета QLineEdit в таблице, фокус не меняется должным образом (я установил фокус на go обратно на холст, но ячейка остается активной с мигающим курсором).

В том же приложении у меня есть другой виджет QLineEdit в другом месте макета, который работает, как и ожидалось. Когда я нажимаю клавишу ввода в этом поле, функция, подключенная к сигналу returnPressed, отправляет фокус обратно на холст.

Может кто-нибудь помочь мне разобраться, что происходит?

Также я Я не понимаю, почему приложение запускается с фокусом на QLineEdit, когда я явно устанавливаю фокус на холст при создании основного кадра. Вы знаете, как это исправить?

Я сократил свое приложение до минимального примера, вставленного ниже, и поведение остается тем же.

Просто подведу итог:

  1. Я нажимаю на холст и нажимаю 'a', который вызывает функцию 'add_point'.
  2. Затем я щелкаю точку на графике, которая создает новую строку в виджете и устанавливает фокус на второй столбец. .
  3. Я ввожу любое значение с плавающей запятой, которое мне нужно, и нажимаю Enter.
  4. Затем вызывается функция print_val, но фокус не возвращается на холст, как ожидалось. Курсор продолжает мигать в ячейке таблицы.

  5. Когда я редактирую самый левый QLineEdit (вне таблицы) и нажимаю Enter, вызывается функция 'fun c' и правильно отправляется фокусируемся обратно на холст.

Почему два экземпляра QLineEdit ведут себя по-разному?

Для справки, вывод функции 'print_val' дает мне: TableWidget имеет фокус? Редактор False Cell имеет фокус? Ложь

Заранее спасибо!

import sys
from matplotlib.backends.backend_qt5agg import FigureCanvas, NavigationToolbar2QT as NavigationToolbar
from matplotlib.figure import Figure

from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *



class GraphicInterface(QMainWindow):
    def __init__(self, parent=None):
        QMainWindow.__init__(self, parent)
        self.setWindowTitle('Test')
        self._main = QWidget()
        self.setCentralWidget(self._main)

        # Create Toolbar and Menubar
        toolbar = QToolBar()
        toolbar.setMovable(False)
        toolbar_fontsize = QFont()
        toolbar_fontsize.setPointSize(14)

        quit_action = QAction("Close", self)
        quit_action.setFont(toolbar_fontsize)
        quit_action.setStatusTip("Quit the application")
        quit_action.triggered.connect(self.close)
        quit_action.setShortcut("ctrl+Q")
        toolbar.addAction(quit_action)


        # =============================================================
        # Start Layout:
        layout = QHBoxLayout(self._main)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(0)

        self.line_editor = QLineEdit("3")
        self.line_editor.setValidator(QIntValidator(1, 100))
        self.line_editor.returnPressed.connect(self.func)
        layout.addWidget(self.line_editor)

        # Create Table for Pixel Identifications:
        pixtab_layout = QVBoxLayout()
        label_pixtab_header = QLabel("Pixel Table\n")
        label_pixtab_header.setAlignment(Qt.AlignCenter)
        self.linetable = QTableWidget()
        self.linetable.verticalHeader().hide()
        self.linetable.setColumnCount(2)
        self.linetable.setHorizontalHeaderLabels(["Pixel", "Wavelength"])
        self.linetable.setColumnWidth(0, 80)
        self.linetable.setColumnWidth(1, 90)
        self.linetable.setFixedWidth(180)
        pixtab_layout.addWidget(label_pixtab_header)
        pixtab_layout.addWidget(self.linetable)
        layout.addLayout(pixtab_layout)

        # Create Figure Canvas:
        right_layout = QVBoxLayout()
        self.fig = Figure(figsize=(6, 6))
        self.canvas = FigureCanvas(self.fig)
        self.canvas.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.canvas.updateGeometry()
        self.canvas.mpl_connect('key_press_event', self.on_key_press)
        self.canvas.setFocusPolicy(Qt.StrongFocus)
        self.canvas.setFocus()
        right_layout.addWidget(self.canvas)
        self.mpl_toolbar = NavigationToolbar(self.canvas, self)
        right_layout.addWidget(self.mpl_toolbar)
        layout.addLayout(right_layout)

        # Plot some random data:
        self.ax = self.fig.add_subplot(111)
        self.ax.plot([0, 1, 5, 10, 20], [-1, 2, -4, 5, -2])

    def on_key_press(self, e):
        if e.key == "a":
            self.add_point()

    def add_point(self):
        print("Select point...")
        point = self.fig.ginput(1)
        x0, _ = point[0]
        rowPosition = self.linetable.rowCount()
        self.linetable.insertRow(rowPosition)
        item = QTableWidgetItem("%.2f" % x0)
        item.setFlags(Qt.ItemIsEnabled)
        item.setBackground(QColor('lightgray'))
        self.linetable.setItem(rowPosition, 0, item)

        y_item = QLineEdit("")
        y_item.setValidator(QDoubleValidator())
        y_item.returnPressed.connect(self.print_val)
        self.linetable.setCellWidget(rowPosition, 1, y_item)
        self.linetable.cellWidget(rowPosition, 1).setFocus()

    def print_val(self):
        rowPosition = self.linetable.rowCount()
        editor = self.linetable.cellWidget(rowPosition-1, 1)
        y_in = float(editor.text())
        print(" Table value: %.2f" % y_in)
        # and set focus back to canvas:
        self.canvas.setFocus()
        # Check which widget has focus:
        focus_widget = self.focusWidget()
        print(focus_widget.__class__)
        print("TableWidget has focus?  %r" % self.linetable.hasFocus())
        print("Cell editor has focus?  %r" % editor.hasFocus())

    def func(self):
        # dome some stuff
        print(self.line_editor.text())
        # and set focus back to canvas:
        self.canvas.setFocus()


if __name__ == '__main__':
    # Launch App:
    qapp = QApplication(sys.argv)
    app = GraphicInterface()
    app.show()
    qapp.exec_()

1 Ответ

1 голос
/ 25 апреля 2020

Если вы хотите проверить информацию о QTableWidget, нет необходимости вставлять QLineEdit, но использовать тот, который создан делегатом, и установить там QValidator:

class ValidatorDelegate(QtWidgets.QStyledItemDelegate):
    def createEditor(self, parent, option, index):
        editor = super(ValidatorDelegate, self).createEditor(parent, option, index)
        if isinstance(editor, QtWidgets.QLineEdit):
            editor.setValidator(QtGui.QDoubleValidator(editor))
        return editor

А затем открыть редактор с помощью метод редактирования вида, для изменения фокуса вы можете использовать делегат closeEditor:

import sys
from matplotlib.backends.backend_qt5agg import (
    FigureCanvas,
    NavigationToolbar2QT as NavigationToolbar,
)
from matplotlib.figure import Figure


from PyQt5 import QtCore, QtGui, QtWidgets


class ValidatorDelegate(QtWidgets.QStyledItemDelegate):
    def createEditor(self, parent, option, index):
        editor = super(ValidatorDelegate, self).createEditor(parent, option, index)
        if isinstance(editor, QtWidgets.QLineEdit):
            editor.setValidator(QtGui.QDoubleValidator(editor))
        return editor


class GraphicInterface(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(GraphicInterface, self).__init__(parent)
        self.setWindowTitle("Test")
        self._main = QtWidgets.QWidget()
        self.setCentralWidget(self._main)

        # Create Toolbar and Menubar
        toolbar = QtWidgets.QToolBar(movable=False)
        toolbar_fontsize = QtGui.QFont()
        toolbar_fontsize.setPointSize(14)

        quit_action = QtWidgets.QAction("Close", self)
        quit_action.setFont(toolbar_fontsize)
        quit_action.setStatusTip("Quit the application")
        quit_action.triggered.connect(self.close)
        quit_action.setShortcut("ctrl+Q")
        toolbar.addAction(quit_action)

        self.line_editor = QtWidgets.QLineEdit("3")
        self.line_editor.setValidator(QtGui.QIntValidator(1, 100))

        label_pixtab_header = QtWidgets.QLabel(
            "Pixel Table\n", alignment=QtCore.Qt.AlignCenter
        )

        self.linetable = QtWidgets.QTableWidget()
        self.linetable.verticalHeader().hide()
        self.linetable.setColumnCount(2)
        self.linetable.setHorizontalHeaderLabels(["Pixel", "Wavelength"])
        self.linetable.setColumnWidth(0, 80)
        self.linetable.setColumnWidth(1, 90)
        self.linetable.setFixedWidth(180)

        delegate = ValidatorDelegate(self.linetable)
        self.linetable.setItemDelegate(delegate)

        layout = QtWidgets.QHBoxLayout(self._main)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(0)
        layout.addWidget(self.line_editor)

        pixtab_layout = QtWidgets.QVBoxLayout()
        pixtab_layout.addWidget(label_pixtab_header)
        pixtab_layout.addWidget(self.linetable)
        layout.addLayout(pixtab_layout)

        # Create Figure Canvas:
        right_layout = QtWidgets.QVBoxLayout()
        self.fig = Figure(figsize=(6, 6))
        self.canvas = FigureCanvas(self.fig)
        self.canvas.setSizePolicy(
            QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding
        )
        self.canvas.updateGeometry()
        self.canvas.mpl_connect("key_press_event", self.on_key_press)
        self.canvas.setFocusPolicy(QtCore.Qt.StrongFocus)
        self.canvas.setFocus()
        right_layout.addWidget(self.canvas)
        self.mpl_toolbar = NavigationToolbar(self.canvas, self)
        right_layout.addWidget(self.mpl_toolbar)
        layout.addLayout(right_layout)

        delegate.closeEditor.connect(self.canvas.setFocus)

        # Plot some random data:
        self.ax = self.fig.add_subplot(111)
        self.ax.plot([0, 1, 5, 10, 20], [-1, 2, -4, 5, -2])

    def on_key_press(self, e):
        if e.key == "a":
            self.add_point()

    def add_point(self):
        print("Select point...")
        point = self.fig.ginput(1)
        if not point:
            return
        x0, _ = point[0]

        row = self.linetable.rowCount()
        self.linetable.insertRow(row)

        item = QtWidgets.QTableWidgetItem("%.2f" % x0)
        item.setFlags(QtCore.Qt.ItemIsEnabled)
        item.setBackground(QtGui.QColor("lightgray"))
        self.linetable.setItem(row, 0, item)

        index = self.linetable.model().index(row, 1)

        self.linetable.edit(index)


if __name__ == "__main__":
    # Launch App:
    qapp = QtWidgets.QApplication(sys.argv)
    app = GraphicInterface()
    app.show()
    qapp.exec_()
...