Прохождение класса через настройку сигнала/слота в Qt

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

Это устанавливает сигнал для прохождения класса

signals:
    void selected(const ControlIcon *controlIcon);

это соединение слота/сигнала

connect(controllerList->serialController, SIGNAL(selected(const ControlIcon*)),
        infoView, SLOT(serialControllerSelected(const ControlIcon*)));

Я испускаю сигнал из класса, который нужно передать

emit selected(this);

Вот код для вызова данных члена класса

QLabel *ASCIIStringHolder = new QLabel;
ASCIIStringHolder->setText(controlIcon->m_ASCIIString);

В метке ничего не отображается, и когда я устанавливаю точку останова, я вижу, что внутри m_ASCIIString ничего нет.

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

Любая помощь будет оценена по достоинству.


person CoutPotato    schedule 25.01.2011    source источник
comment
Вы установили точку останова внутри слота serialControllerSelected()? Здесь есть что-то странное; serialController это ControlIcon*?   -  person maxelost    schedule 26.01.2011
comment
Извините, я забыл упомянуть об этом. SerialController — это дочерний класс ControlIcon, так что да. Кроме того, сигнал отправляется и принимается нормально (достигнуты точки останова внутри слота), поэтому ошибки нет.   -  person CoutPotato    schedule 26.01.2011


Ответы (3)


Механизм сигнала/слота Qt нуждается в метаинформации о ваших пользовательских типах, чтобы иметь возможность отправлять их в испускаемых сигналах. Для этого зарегистрируйте свой тип с помощью qRegisterMetaType<MyDataType>("MyDataType");

Обратитесь к официальной документации QMetaType для получения дополнительной информации об этом.

person Nekuromento    schedule 25.01.2011
comment
Это верно только при передаче по значению и использовании соединения в очереди или автоматического соединения с разными потоками. OP использует указатели, так что это не должно быть проблемой. - person Sergei Tachenov; 26.01.2011
comment
когда я использую команду, я получаю эту ошибку: «QLabel:: Qlabel (const QLabel &)» является частным. ControlIcon и SerialController наследуются от QLabel. Любые идеи? - person CoutPotato; 26.01.2011
comment
@CoutPotato, чтобы зарегистрировать метатип, он должен иметь конструктор копирования. Компилятор пытается сгенерировать значения по умолчанию, но терпит неудачу из-за того, что конструктор копирования QLabel является закрытым (это сделано намеренно, чтобы отключить копирование). Но, как я уже сказал, вам это нужно только тогда, когда вы передаете по значению (что в любом случае является плохой идеей для QWidgets) и соединение ставится в очередь, что полезно только в многопоточных приложениях. - person Sergei Tachenov; 26.01.2011

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

Во-вторых, просто ради интереса, пытались ли вы получить доступ к отправителю, используя qobject_cast<ControlIcon*>(sender()) в слоте? Так это обычно делается, если сигнал не передает this в качестве аргумента. Как это:

QLabel *ASCIIStringHolder = new QLabel;
// this is instead of the argument to the slot:
ControlIcon *controlIcon = qobject_cast<ControlIcon*>(sender());
ASCIIStringHolder->setText(controlIcon->m_ASCIIString); 
person Sergei Tachenov    schedule 26.01.2011
comment
У меня только одна тема, так что они определенно в одной и той же. Я не уверен, где именно вы говорите поместить qobject_cast, но я попробую несколько способов и отчитаюсь. - person CoutPotato; 26.01.2011
comment
@CoutPotato, sender(), при вызове из слота возвращает указатель на объект, сгенерировавший сигнал, из-за которого был вызван слот. Таким образом, вы можете просто иметь слот без аргументов и по-прежнему иметь доступ к отправителю, но вам, очевидно, нужно привести его к фактическому типу, чтобы использовать его. - person Sergei Tachenov; 26.01.2011
comment
@CoutPotato, посмотрите мое редактирование, например код. Однако, если ваше приложение является однопоточным и вы делаете emit selected(this);, в поведении не должно быть никакой разницы. Похоже, у вас есть ошибка где-то еще, может быть, повреждение памяти или что-то в этом роде. Нет ничего плохого в фрагментах кода, которые вы разместили. - person Sergei Tachenov; 26.01.2011
comment
Не повезло, сигнал был отправлен и получен, но все члены ControlIcon были пусты. РЕДАКТИРОВАТЬ: не читал новые комментарии, попробую еще раз через несколько минут. - person CoutPotato; 26.01.2011

Сигнал не может быть объявлен как передающий класс, а затем фактически передать дочерний элемент этого класса. Я изменил signal, slot и connect() на SerialController (дочерний элемент ControllerIcon), и все заработало нормально.

person CoutPotato    schedule 27.01.2011
comment
Это неверно в общем случае. Если бы вы передавали значения, это была бы другая история, но вы просто передаете адрес. Я только что проверил его на фиктивном примере, и он работает для меня. SerialController случайно не использует множественное наследование? Может быть что-то о перевыравнивании указателей, хотя мне непонятно, почему это может вызвать какие-то проблемы. - person Sergei Tachenov; 27.01.2011
comment
SerialController наследуется только от ControlIcon. Вы убедились, что некоторые данные, содержащиеся в фиктивном классе, были переданы? Мне удалось заставить программу скомпилироваться и работать нормально, но данные не были переданы (в слоте был создан пустой значок ControlIcon). - person CoutPotato; 27.01.2011
comment
существовали ли в базовом классе последовательного контроллера данные, которые вы проверяли? - person chikuba; 23.04.2012