Python-SIP не преобразует параметры сигнала для пользовательских типов - PullRequest
0 голосов
/ 12 декабря 2018

Фон

В стиле, не отличном от PyQt, SIP используется для генерации собственных привязок для пользовательской библиотеки, основанной на Qt ( Source ).Я пытаюсь диагностировать проблему, связанную с сигналами, которые предоставляют параметры для пользовательских типов, которые не преобразуются при передаче в соответствующие слоты, и ищу указатели для того, чтобы попробовать.Код с открытым исходным кодом, и я призываю всех, кто попробует его, попробовать себя, но для тех, кто хочет получить немного более краткое / искаженное описание, я сделал здесь лучшую попытку.

Проблема

Давайте начнем с кода Python, который использует сгенерированный модуль, вызывающий проблему ( Пример взаимодействия ).Вот стандартный код соединения сигнал / слот в конструкторе MainWindow, полный исходный код можно найти в mainwindow.py.

class MainWindow(QMainWindow):

    def __init__(self, argv, parent=None):
        # ... snipped other setup code ...

        # connect slot that shows a message in the status bar when a graph is clicked:
        self.customPlot.plottableClick.connect(self.graphClicked)

Определение для QCustomPlot и сигнала plottableClick находятся в sip / core.sip,Обратите внимание, что сигнал plottableClick предоставляет объект QCPAbstractPlottable * в качестве первого параметра.

class QCustomPlot : public QWidget
{

    // ... snipped other methods of QCustomPlot type ...

signals:
  void plottableClick(QCPAbstractPlottable *plottable, int dataIndex, QMouseEvent *event);

Теперь давайте рассмотрим метод слота, в котором и может возникнуть проблема.Когда вызывается слот, возникает исключение, потому что plottable является допустимым PyObject, но у него нет членов типа, что приводит к сбою вызова interface1D:

def graphClicked(self, plottable, dataIndex):
    dataValue = plottable.interface1D().dataMainValue(dataIndex) # fails because plottable has no member method called "interface1D"

Привязки для QCPAbstractPlottable показывают, что член являетсяопределены.

class QCPAbstractPlottable : public QCPLayerable /Abstract/
{

  // ... snipped other methods here ...

  virtual QCPPlottableInterface1D *interface1D();

Кроме того, сгенерированные привязки действительно правильно преобразовывают тип при вызове функций-членов QCustomPlot, таких как QCustomPlot.selectedPlottables (), которая возвращает QList.Это заставляет меня поверить, что проблема связана с сигналами.

Вопрос

После нескольких дней стуча головой об этой проблеме, она начинает выглядетьво многом как SIP не имеет информации, необходимой для распознавания того, что типы, определенные в библиотеке, являются типами, которые она может преобразовывать при передаче в сигнал.

Глядя на исходный код PyQt5, я нашел примерыгде типы, определенные в библиотеке, передаются в качестве параметров сигнала, например, QWidget :: mousePressEvent принимает QMouseEvent *, который является тем же шаблоном, который я пытаюсь воспроизвести в своем собственном сигнале.Однако я не могу найти никакого специального кода SIP-клея, который бы подсказал генератору кода, как преобразовать тип.

Что я сделал не так?

1 Ответ

0 голосов
/ 12 декабря 2018

Как оказалось, ответ был достаточно прост, уловка заключается в использовании директивы % ConvertToSubClassCode .Здесь вы можете вручную написать логику для вывода типа из объекта, используя любую доступную форму rtti, которая может быть qobject_cast, dynamic_cast или любым другим механизмом, а затем установить правильное значение переменной sipType (см. Связанную документацию дляболее подробное объяснение).

...