Qt5, не проходит сигнал/слот
Народ, столкнулся с проблемой не проходит сигнал/слот в след конструкции:
classes.hpp
Может стоит начать с того, что выкинуть iostream и использовать qDebug?
Ну и вызывать send по таймеру, а не в цикле. Вы же блочите поток. Но это так, мысли в слух.
Собака порылась у тебя в цикле. Ты должен периодически вызывать в нем http://doc.qt.io/qt-5/qabstracteventdispatcher.html#processEvents ибо это cooperative multitasking.
если оставить итерацию одну — все тоже самое. QThread в своем методе run вызывает exec как бы .
не имеет большого значения, да и таймер ни к чему. Задача простая — запустить поток в рамках Qt и писать из него в controller
А вот когда ты делаешь QObject::connect(pThread, &QThread::started, pWriter, &Writer::write ); живущими в одном потоке после pWriter->moveToThread( pThread ); с Qt::BlockingQueuedConnection ты закономерно получаешь дедлок.
Да, а контроллер то у тебя живет в основном потоке? И кто же там вызывает обработчик событий, пока выполняется main?
значит контроллер нужно засунуть в отдельный поток 🙂
Если ты изображаешь модель акторов, то да.
UPD: timer лучше не создавать в конструкторе, но для данного случая и так норм.
Я честно попробовал осилить твой код, но ясно одно: если ты продолжишь кодить в таком стиле, и так работать с потоками — твои макароны будут глючить и падать или что-то не вызывать.
Года 4 назад я так же неряшливо работал с потоками, не понимая сути их правильного использования в Qt совместно с сигналами-слотами и получал тонны нелепых ситуаций несрабатывания сигналов, дедлоков и тому подобного.
На ЛОРе была тема, не могу найти но там подробно было, а пока вот тебе статья: https://habrahabr.ru/post/150274/ — пока я так не начал делать, потоки вызывали страдания.
Спасибо, сработало:) контроллер был без очереди сообщений
Добавил ProcessEvents? Или что? Явно что-то делаешь не так, где же event loop. Странный способ работы с Qt.
Очередь то «у него» была, просто события из неё никто не доставал и не обрабатывал, т.к. http://doc.qt.io/qt-5/qapplication.html#exec ты не вызывал.
Обращу внимание на другой момент. Метод connect() возвращает значение. А значит это значение надо проверять. Соблюдение технологической культуры — это важно.
У него ж «новый синтаксис», если уж скомпилилось то точно соединится и заработает, разве не?
Ты должен периодически вызывать в нем
И лучше писать так чтобы ничего не вызывать, потому что это костыль.
Нет, скомпилится и не будет работать если в качестве объектов передаются нульпойнтеры ☺
Источник
Не работает связь сигнал-слот
Помощь в написании контрольных, курсовых и дипломных работ здесь.
Не работает сигнал\слот, не удается вывести данные на форму
Не работает сигнал\слот. Другими обходными путями тоже не получилось вывести данные на форму. В.
Сигнал и слот
Подскажите пожалуйста функция connect это единственная функцию взаимодействия с пользователем? Как.
Сигнал-слот
Есть кусок кода QFile file(«3.txt»); QVector > numbers; .
Сигнал и слот
Всем привет, нужна помощь. Подскажите пожалуйста, как реализовать некий процесс: у меня есть на.
Аналогичная проблема:
Слот типа — public. данный слот представляет собой функцию записи в файл. Если ее вызывать из main — файл записывается. Если использовать в качестве слота — нет. Использование private-слотов типа изменения надписи на кнопках тоже срабатывают. Получается я что-то упустил именно при связке сигнала с public-слотом
Бьюсь уже день — не могу понять в чем ошибка. Буду благодарен за подсказки).
Я в Qt далеко не асс, но иногда помогает вот что.
Уничтожение всех всех *.o
Уничтожение всех moc-файлов
Аккуратно посмотреть все ли *.h прописаны в pro
То же с *.cpp ( и *.c)
qmake
make
(это все для работы в командной строке)
ЗЫ. Время перетрансляции ничтожно по сравнению с временем, которое мы тратим на то чтобы понять, а где же эта дурацкая ошибка.
Добавлено через 55 минут
Ну и конечно, надо проверять наличие макроса Q_OBJECT в каждом из h-файлов, где есть эти слоты и сигналы (не более одного раза на файл)
Здравствуйте! Хоть я и не знаток ООП и QT, но здесь присоветую (5 коп).
Байт, oxotnik и polimorf96 посоветовали верно.
В main соединяются сигналами и слотами (public) «равнозначные» объекты, предварительно там же созданные.
Внутри же классов (с Q_OBJECT) сигналами и слотами (private) соедняются сигналы и локальные слоты класса.
Нужно инклудить только *.h файлы и работать последовательно с созданными объектами = создал+навешал+соединил!
Причем в сам *.h нужно включать только необходимые хейдеры, остальные небходимо выносить в *.cpp — если к примеру они там задействуются = для быстроты компиляции программы. Когда же пересоздаются ошники не знаю сам = этап мне не понятен — нет закономерности, вроде!
Almaz1988, fd = open . выведи сам fd = может он и не нашелся по пути и rezult тоже выведи == интересно же.
Я даже не знаю, как относиться к классам без конструктора = может создать его, хотя бы пустым.
Добавлено через 9 минут
Almaz1988, может стоит объеденить два класса вообще в один?
Удачи.
Источник
Сигналы и слоты в Qt
Введение
В программировании графического интерфейса, когда мы меняем один виджет, мы часто хотим что бы другой виджет получил об этом уведомление. В общем случае, мы хотим что бы объекты любого типа могла общаться с другими. Например, если пользователь нажимает кнопку Закрыть, мы вероятно хотим что бы была вызвана функция окна close().
Другие библиотеки добиваются такого рода общения используя обратный вызов. Обратный вызов это указатель на функцию, таким образом, если мы хотим что бы функция уведомила нас о каких-нибудь событиях, мы передаем указатель на другую функцию (обратновызываемую) этой функции. Функция в таком случае делает обратный вызов когда необходимо. Обратный вызов имеет два основных недостатка. Во-первых, он не является типобезопасным. Мы никогда не можем быть уверены что функция делает обратный вызов с корректными аргументами. Во-вторых, обратный вызов жестко связан с вызывающей его функцией, так как эта функция должна точно знать какой обратный вызов надо делать.
Сигналы и слоты
В Qt используется другая техника — сигналы и слоты. Сигнал вырабатывается когда происходит определенное событие. Слот это функция, которая вызывается в ответ на определенный сигнал. Виджеты Qt имеют много предопределенных сигналов и слотов, но мы всегда можем сделать дочерний класс и добавить наши сигналы и слоты в нем.
Механизм сигналов и слотов типобезопасен. Сигнатура сигнала должна совпадать с сигнатурой слота-получателя. (Фактически слот может иметь более короткую сигнатуру чем сигнал который он получает, так как он может игнорировать дополнительные аргументы). Так как сигнатуры сравнимы, компилятор может помочь нам обнаружить несовпадение типов. Сигналы и слоты слабо связаны. Класс, который вырабатывает сигнал не знает и не заботится о том, какие слоты его получат. Механизм сигналов и слотов Qt гарантирует, что если мы подключим сигнал к слоту, слот будет вызван с параметрами сигнала в нужное время. Сигналы и слоты могут принимать любое число аргументов любого типа. Они полностью типобезопасны.
Все классы, наследуемые от QObject или его дочерних классов (например, QWidget) могут содержать сигналы и слоты. Сигналы вырабатываются объектами когда они изменяют свое состояние так, что это может заинтересовать другие объекты. При этом он на знает и не заботится о том что у его сигнала может не быть получателя.
Слоты могут быть использованы для получения сигналов, но они так же нормальные функции-члены. Так же как объект не знает ничего о получателях своих сигналов, слот ничего не знает о сигналах, которые к нему подключены. Это гарантирует что полностью независимые компоненты могут быть созданы с помощью Qt.
Мы можем подключать к одному слоту столько сигналов, сколько захотим, также один сигнал может быть подключен к стольким слотам, сколько необходимо. Так же возможно подключать сигнал к другому сигналу (это вызовет выработку второго сигнала немедленно после появления первого).
Сигналы и слоты вместе составляют мощный механизм создания компонентов.
Небольшой пример
- class Counter
- <
- public :
- Counter()
- int value () const
- void setValue( int value );
- private :
- int m_value;
- >;
* This source code was highlighted with Source Code Highlighter .
- #include
- class Counter : public QObject
- <
- Q_OBJECT
- public :
- Counter()
- int value () const
- public slots:
- void setValue( int value );
- signals:
- void valueChanged( int newValue);
- private :
- int m_value;
- >;
* This source code was highlighted with Source Code Highlighter .
- void Counter::setValue( int value )
- <
- if ( value != m_value) <
- m_value = value ;
- emit valueChanged( value );
- >
- >
* This source code was highlighted with Source Code Highlighter .
- Counter a, b;
- QObject::connect(&a, SIGNAL(valueChanged( int )),
- &b, SLOT(setValue( int )));
- a.setValue(12); // a.value() == 12, b.value() == 12
- b.setValue(48); // a.value() == 12, b.value() == 48
* This source code was highlighted with Source Code Highlighter .
Вызов a.setValue(12) вырабатывает сигнал valueChanged(12), который получит объект b в свой слот setValue() slot, т.е. будет вызвана функция b.setValue(12). Тогда b вырабатывает такой же сигнал valueChanged(), но так как он не подключен ни к одному слоту, это сигнал будет проигнорирован.
Отмечу что функция setValue() устанавливает новое значение и вырабатывает сигнал только есть value != m_value. Это предотвращает бесконечный цикл в случае кругового соединения (например, если бы b.valueChanged() был бы подключен к a.setValue()).
Сигнал вырабатывается для каждого соединения. Если соединение продублировать, два сигнала будут выработаны. Соединение всегда можно разорвать использовав функцию QObject::disconnect().
Приведенный выше пример показывает как объекты могут работать вместе без необходимости знать что-либо друг о друге. Что бы задействовать это, объекты должны быть соединены вместе и это может быть достигнуто простым вызовом функции QObject::connect() или с помощью свойства автоматического соединения программы uic.
Компилирование примера
Мета-объектный компилятор (meta-object compiler, moc) просматривает описание классов в файлах исходных кодов и генерирует код на C++, который инициализирует мета-объекты. Мета-объекты содержат имена все сигналов и слотов, так же как и указатели на эти функции.
Запуская программу moc для описания класса, содержащего сигналы и слоты, мы получаем файл исходных кодов, который должен быть скомпилирован и слинкован с другими объектными файлами приложения. При использовании qmake, правила для автоматического вызова moc будут добавлены в Makefile проекта.
Сигналы
Сигналы вырабатываются объектами когда они изменяют свое состояние так, что это может заинтересовать другие объекты. Только класс, который определяет сигнал или его потомки могут вырабатывать сигнал.
Когда сигнал вырабатывается, слот, к которому он подключен обычно выполняется немедленно, так же как и нормальный вызов процедуры. Когда это происходит, механизм сигналов и сигналов и слотов полностью независим от любого цикла событий графического интерфейса. Выполнение кода, следующего за выпуском сигнала произойдет сразу после выхода из всех слотов. Ситуация слегка отличается когда используются отложенные соединения (queued connections); в этом случае код после ключевого слова emit продолжает выполнение немедленно, а слоты будут выполнены позже.
Если несколько слотов подключены к одному сигналу, слоты будут выполнены один за другим в произвольном порядке после выработки сигнала.
Сигналы автоматически генерируются программой moc и не должны быть реализованы в исходном коде. Они могут не возвращать значение (т. е., используем тип void).
Замечание по поводу аргументов: опыт показывает, что сигналы и слоты легче повторно использовать при написании программ, если они не используют специальных типов. Например, если бы сигнал QScrollBar::valueChanged() использовал бы специальный тип вроде гипотетического QScrollBar::Range, он мог бы быть подключенным только к слотам, спроектированным специально для него.
Слоты
Слот вызывается когда вырабатывается сигнал, с которым он связан. Слот это обычная функция в C++ и может вызываться обычным способом; единственная его особенность, что с ним можно соединсять сигналы.
Так как слоты это нормальные функции-члены, они следуют обычным правилам C++ при прямом вызове. Тем не менее, как слоты, они могут быть вызваны любым компонентом, независимо от их уровней доступа, через соединение сигнал-слот. Это значит, что сигнал, выработаный объектом произвольного класса может вызвать защищенный (private) слот объекта несвязанного с ним класса.
Слоты так же можно объявлять виртуальными, что иногда бывает довольно удобно.
По сравнению с обратными вызовами, сигналы и слоты слегка медленнее из-за увеличенной гибкости, которую они обеспечивают, хотя разница для реальных приложений незаметна. В общем, выработка сигнала, который подключен к некоторым слотам, в среднем в 10 раз медленнее, чем вызов получателя напрямую, при вызове не виртуальной функции. Эти накладные расходы требуются для нахождения объекта, для безопасного перебора всех его соединений (т. е. проверка что последующий получатель не был уничтожен во время выпуска сигнала) и передачи любых параметров в общем виде. Хотя вызов десяти невиртуальных процедур может показаться дорогим, это менее затратно, чем, например, операция создания или удаления объекта. Пока мы создаем строку, вектор или список, что неявно требует создание объекта, затраты сигналов и слотов отвечают за очень маленькую долю в затратах среди всех вызовов процедур.
То же самое верно делаете ли вы системный вызов в слот или косвенно вызываете более десяти функций. На i586-500, мы можем вырабатывать около 2,000,000 сигналов в секунду, соединенных с одним слотом или 1,200,000 в секунду, при соединении в двумя слотами. Простота и гибкость механизма сигналов и слотов окупает дополнительные затраты, которые пользователь программы даже не заметит.
Следует заметить, что библиотеки, которые определяют переменные с именами signal или slot, могут вызывать предупреждения или ошибки компилятора при компиляции вместе с программой, написанной на Qt. Что бы решить данную проблему, необходимо убрать определение мешающегося символа препроцессора с помощью директивы #undef.
Метаобъектная информация
- if (widget->inherits( «QAbstractButton» )) <
- QAbstractButton *button = static_cast (widget);
- button->toggle();
- >
* This source code was highlighted with Source Code Highlighter .
- if (QAbstractButton *button = qobject_cast (widget))
- button->toggle();
* This source code was highlighted with Source Code Highlighter .
Реальный пример
- #ifndef LCDNUMBER_H
- #define LCDNUMBER_H
- #include
- class LcdNumber : public QFrame
- <
- Q_OBJECT
* This source code was highlighted with Source Code Highlighter .
- public :
- LcdNumber(QWidget *parent = 0);
* This source code was highlighted with Source Code Highlighter .
- signals:
- void overflow();
* This source code was highlighted with Source Code Highlighter .
- public slots:
- void display( int num);
- void display( double num);
- void display( const QString &str);
- void setHexMode();
- void setDecMode();
- void setOctMode();
- void setBinMode();
- void setSmallDecimalPoint( bool point);
- >;
- #endif
* This source code was highlighted with Source Code Highlighter .
Слоты это функции, используемые для получения информации об изменениях состояний других виджетов. LcdNumber использует их, как показано в коде выше, для установки отображаемого числа. Так как функция display() часть интерфейса класса с остальной программой, этот слот публичный.
Стоит отметить что функция display() перегружена. Qt выберет подходящую версию при соединении сигнала и слота. С обратным вызовом нам бы пришлось искать пять разных имен и контролировать типы самостоятельно.
Некоторые незначительные функции-члены были опущены в данном примере.
Продвинутое использование сигналов и слотов
- signalMapper = new QSignalMapper( this );
- signalMapper->setMapping(taxFileButton, QString( «taxfile.txt» ));
- signalMapper->setMapping(accountFileButton, QString( «accountsfile.txt» ));
- signalMapper->setMapping(reportFileButton, QString( «reportfile.txt» ));
- connect(taxFileButton, SIGNAL(clicked()),
- signalMapper, SLOT (map()));
- connect(accountFileButton, SIGNAL(clicked()),
- signalMapper, SLOT (map()));
- connect(reportFileButton, SIGNAL(clicked()),
- signalMapper, SLOT (map()));
* This source code was highlighted with Source Code Highlighter .
- connect(signalMapper, SIGNAL(mapped( const QString &)),
- this , SLOT(readFile( const QString &)));
* This source code was highlighted with Source Code Highlighter .
Источник