WedX - журнал о программировании и компьютерных науках

В qt, как мне реализовать виджет, который остается совместимым с переменными в коде

Вот пример SpinBox, который записывает свои изменения в базовые переменные. Основная проблема, с которой я сталкиваюсь, заключается в том, что valueChanged вызывается при создании виджета. Есть ли более элегантный способ сделать это? Я думаю, что это странно, что я подключил виджет сам к себе, но valueChanged не является виртуальным.

class ValueWriterInt: public QSpinBox {
    Q_OBJECT

public:
    ValueWriterInt(vector<int*> const& value): myValue(value) { 
        QObject::connect(this, SIGNAL(valueChanged(int)), this, SLOT(valueChanged(int)));
    }
    ~ValueWriterInt() {}

private slots:
    void    valueChanged(int new_value) {
        for (auto it = myValue.begin(); it != myValue.end(); ++it)
            **it = new_value;
    }

private:
    vector<int*>        myValue;
};
04.05.2009

Ответы:


1

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

Теперь, выразив мнение, что рефлексивное соединение по своей сути не является неэлегантным, я собираюсь предложить менее чем «элегантное» решение для предотвращения вызова valueChanged после построения. У вас может быть флаг, чтобы определить, был ли объект только что создан, и вернуться раньше, чтобы предотвратить запуск кода сразу после создания. В вашем примере:

class ValueWriterInt: public QSpinBox {
Q_OBJECT

public:
    ValueWriterInt(vector<int*> const& value): myValue(value), myAfterInit(true) { 
        QObject::connect(this, SIGNAL(valueChanged(int)), this, SLOT(valueChanged(int)));
    }
    ~ValueWriterInt() {}

private slots:
    void        valueChanged(int new_value) {
        if (myAfterInit) {
            myAfterInit = false;
            return;
        }
        for (auto it = myValue.begin(); it != myValue.end(); ++it)
                **it = new_value;
    }

private:
    vector<int*>                myValue;
    boolean                     myAfterInit;
};

Это не так уж плохо решение. По крайней мере, это даст вам желаемое поведение до тех пор, пока (и если) вы не найдете более элегантный метод.

04.05.2009
  • Спасибо. Это то, что я в конечном итоге сделал, но это очень обнадеживает независимое подтверждение. valueChanged вызывается намного чаще, чем я думал. Например, вызов setIndexWidget вызывает вызов valueChanged для виджета. Бул помогает и здесь. Еще раз спасибо! 05.05.2009

  • 2

    Так чего вы пытаетесь достичь здесь? Да, valueChanged не является виртуальным — почему это должно быть так, ваши объекты должны напрямую подключать свои собственные слоты к любым сигналам, на которые они хотят реагировать, нет?

    04.05.2009
  • Виртуальные вызовы значительно более эффективны, чем сигналы/слоты. Однако это не имеет большого значения для всего, что связано с пользовательским интерфейсом. 04.05.2009
  • Я пытаюсь создать панель параметров, где пользовательские виджеты на панели живут в дереве. Это оказывается намного сложнее, чем я думал... 06.05.2009

  • 3

    Я не вижу другой альтернативы, кроме как использовать соединения SIGNAL-SLOT. Однако я бы изменил название слота, чтобы оно не совпадало с именем сигнала.

    Интересно, как слот называется, даже если подключение еще не сделано. Я подозреваю, что изменение имени слота решит эту проблему.

    04.05.2009
  • Два хороших момента. Спасибо. В конце концов, я изменил имя, чтобы быть уверенным. И я понял, что сигнал вызывался, когда виджет вставлялся в дерево с помощью setIndexWidget(). 05.05.2009
  • Совершенно нормально, если при построении вызывается valueChanged(int). Ведь это сигнал, а не слот. 22.06.2009
  • Новые материалы

    Как проанализировать работу вашего классификатора?
    Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

    Работа с цепями Маркова, часть 4 (Машинное обучение)
    Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

    Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
    Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..

    Использование машинного обучения и Python для классификации 1000 сезонов новичков MLB Hitter
    Чему может научиться машина, глядя на сезоны новичков 1000 игроков MLB? Это то, что исследует это приложение. В этом процессе мы будем использовать неконтролируемое обучение, чтобы..

    Учебные заметки: создание моего первого пакета Node.js
    Это мои обучающие заметки, когда я научился создавать свой самый первый пакет Node.js, распространяемый через npm. Оглавление Глоссарий I. Новый пакет 1.1 советы по инициализации..

    Забудьте о Matplotlib: улучшите визуализацию данных с помощью умопомрачительных функций Seaborn!
    Примечание. Эта запись в блоге предполагает базовое знакомство с Python и концепциями анализа данных. Привет, энтузиасты данных! Добро пожаловать в мой блог, где я расскажу о невероятных..

    ИИ в аэрокосмической отрасли
    Каждый полет – это шаг вперед к великой мечте. Чтобы это происходило в их собственном темпе, необходима команда астронавтов для погони за космосом и команда технического обслуживания..


    Для любых предложений по сайту: [email protected]