Создайте фабрику виджетов в QtPython

Программы на Python
Anonymous
Создайте фабрику виджетов в Qt

Сообщение Anonymous »

Привет~ Я создаю набор пользовательских виджетов, которые расширяют собственные виджеты Qt. Предполагается, что мои пользовательские виджеты создаются на основе источника данных, и все они предоставляют специальную функцию Foobar. Например:

Код: Выделить всё

class CheckBox: public QCheckBox, public Control
{
Q_OBJECT

public:
CheckBox(QWidget* parent = 0);
CheckBox(DataSource* data, QWidget* parent = 0);
virtual ~CheckBox();

virtual void Foobar();
};

class ComboBox: public QComboBox, public Control
{
Q_OBJECT

public:
ComboBox(QWidget* parent = 0);
ComboBox(DataSource* data, QWidget* parent = 0);
virtual ~ComboBox();

virtual void Foobar();
};
Каждому классу виджета соответствует соответствующий класс источника данных, который отвечает за создание виджета. Например:

Код: Выделить всё

class CheckBoxDataSource: public DataSource
{
public:
CheckBoxDataSource();
virtual ~CheckBoxDataSource();

virtual QWidget* createControl(QWidget* parent);
};

class ComboBoxDataSource: public DataSource
{
public:
ComboBoxDataSource();
virtual ~ComboBoxDataSource();

virtual QWidget* createControl(QWidget* parent);
};
После того, как эти классы будут доступны Python, клиенты Python, у которых есть список различных источников данных, будут использовать его следующим образом:

Код: Выделить всё

for data in dataSources:
widget = data.createControl(parent)  # returns a QCheckBox/QComboBox/etc
# at a later time ...
widget.Foobar()
Однако это не сработает, поскольку data.createControl() вернет объект типа QCheckBox или QCombox в PyQt, поэтому клиенты не смогут вызывать widget.Foobar(), поскольку функция Foobar() недоступна в этих классах. Как я могу обойти эту проблему?
Я пробовал приведенные ниже варианты, но ни один из них не работает...
Попытка 1
В Python я попытался привести виджет к нужному классу C++, чтобы можно было вызвать Foobar().

Код: Выделить всё

widget.__class__ = CheckBox
widget.__class__ = ComboBox
В некоторых случаях это работает нормально, в других случаях я получаю сообщение об ошибке AttributeError: объект 'CheckBox' не имеет атрибута 'Foobar', хотя это правильный тип. Интересно, что если я поставлю точку останова на строку и перейду через нее в отладчике, это всегда сработает, без точки останова произойдет сбой, поэтому, похоже, возникла проблема с синхронизацией, которую я не смог выяснить. В любом случае, изменение __class__ опасно, поэтому мне, вероятно, следует этого избегать.
Попытка 2
Если я добавлю виртуальный void Foobar()< /code> в базовый класс Control и объявите createControl(), чтобы он возвращал Control* вместо QWidget*. Это должно позволить клиентам вызывать Foobar() в Python, но они также теряют возможность обрабатывать его как QWidget.
Попытка 3

Код: Выделить всё

widget = CheckBox(data.createControl(parent))
Благодаря обертыванию возвращаемого объекта в другой вызов конструктора виджет в Python теперь должен иметь правильный тип. Но при этом будет создано 2 виджета CheckBox, а не 1, поэтому мне придется «удалить» один из них. Похоже, в этом случае вызывается конструктор копирования. Я не думаю, что смогу переместить его в Python.
Извините, в моем мозгу сейчас полный беспорядок, я думаю, что должен быть лучший дизайн фабрики?

Подробнее здесь: https://stackoverflow.com/questions/788 ... tory-in-qt

Вернуться в «Python»