Russian Qt Forum
Сентябрь 22, 2024, 07:56 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: сигналы и слоты  (Прочитано 13185 раз)
sinj
Гость
« : Май 16, 2009, 09:37 »

Доброго времени суток!
Имеется установленный и настроенный qtcreator. Только - только начал разбираться в qt. С консольными приложениями нет вопросов, но не могу разобраться с приложениями gui. Допустим, имеется задача: форма с кнопкой и текстовой надписью. По нажатию на кнопку хочу скопировать содержимое текстовой надписи в переменную. Помогите реализовать. Желательно в деталях.
Записан
sermp
Гость
« Ответ #1 : Май 16, 2009, 10:07 »

самый простой способ - это в редакторе форм в дизайнере кликнуть по кнопке и выбрать там "Go to slot...", в появившемся окне выбрать нужный слот.
после этого в классе, связанном с этой формой появиться функция вида on_имя_кнопки_слот() - эта функция будет вызвана при нажатии на кнопку. в теле функции должно быть что-то вроде
Код:
QString str = ui->label->text();
Записан
sinj
Гость
« Ответ #2 : Май 18, 2009, 23:13 »

Спасибо большое. То, что надо.
Записан
UsBA
Гость
« Ответ #3 : Май 23, 2009, 23:19 »

У меня также есть вопрос по слотам, поэтому напишу здесь, чтобы новую тему не создавать.
Суть в том, что в книгах по QT4, которыми я располагаю, процесс взаимодействия между объектами объясняется на примерах кода через метод connect.

Например, файл slider.cpp:
Код:
#include <QApplication>
#include <QVBoxLayout>
#include <QLabel>
#include <QSpinBox>
#include <QSlider>

int main(int argc, char *argv[]){
    QApplication app(argc, argv);
   
    QLabel *label = new QLabel;
   
    QSpinBox *spinBox = new QSpinBox;
    spinBox->setMinimum(0);
    spinBox->setMaximum(100);
    spinBox->setSingleStep(5);
   
    QSlider *slider = new QSlider(Qt::Horizontal);
    slider->setRange( spinBox->minimum(),
                      spinBox->maximum() );
    slider->setSingleStep(10);
    slider->setTickPosition(QSlider::TicksBelow);
    slider->setTickInterval(10);
   
    QObject::connect( spinBox, SIGNAL(valueChanged(int)),
                      label, SLOT(setNum(int)) );
    QObject::connect( spinBox, SIGNAL(valueChanged(int)),
                      slider, SLOT(setValue(int)) );
    QObject::connect( slider, SIGNAL(valueChanged(int)),
                      label, SLOT(setNum(int)) );
    QObject::connect( slider, SIGNAL(valueChanged(int)),
                      spinBox, SLOT(setValue(int)) );
   
    spinBox->setValue(20);
   
    QWidget window;
    QVBoxLayout* mainLayout = new QVBoxLayout(&window);
    mainLayout->addWidget(label);
    mainLayout->addWidget(spinBox);
    mainLayout->addWidget(slider);
    window.show();
   
    return app.exec();
}

Файл slider.pro (если кто-то захочет скомпилировать данный пример):
Код:
######################################################################
# Automatically generated by qmake (2.01a) ?? 30. ??? 15:45:50 2008
######################################################################

TEMPLATE = app
TARGET =
DEPENDPATH += .
INCLUDEPATH += .

# Input
SOURCES += slider.cpp

Сама программа slider выглядит в WindowsXPSP2 так:


Сложности с реализацией взаимодействия объектов у меня появились, когда GUI-приложения стал создавать через QT Creator, т.к. эта программа создаёт в проекте несколько файлов и в какой из них прописывать метод connect мне не понятно. В моих книгах этот вопрос не освещён, пришлось 8 часов экспериментировать.   Улыбающийся
В итоге я получил то, что хотел, но только не через метод connect. Спасибо sermp за подсказку про "Go to slot..." !

Моё приложение, на котором я экспериментировал, выглядит так:


Сразу скажу, что скачать архив (29 Кбайт) с проектом можно по ссылке: http://files.mail.ru/HIS4RM
Поэтому полное содержимое файлов я здесь не выкладываю.

Суть работы проги в том, что при нажатии на кнопку в текстовой строке должен появиться (заданный) текст.
С экспериментами с методом connect у меня прога не заработа, а после выполнения на кнопке "Go to slot..." ! в редакторе форм (см. выше пост от sermp), появились первые положительные результаты: в два файла у меня прописался дополнительный код о слоте. Но этого тоже оказалось мало для нормальной работы приложения и кнопка по-прежнему не работала.
В итоге я внёс небольшие изменения в 3 файла проекта.

В первом файле (сюда слот прописался автоматически) - mainwindow.h:
Код:
private slots:
    void on_pushButton_clicked();

Во втором файле (пришлось добавить строку) - mainwindow.cpp:
Код:
void MainWindow::on_pushButton_clicked()
{
    ui->printText("12345-qwerty"); // эту строку добавил
}

Третий файл - ui_mainwindow.h:
Код:
// эти строки добавлены в класс Ui_MainWindow
void printText(QString str)
    {
        Ui_MainWindow::lineEdit->setText(str);
    }

После указанных поправок программа заработала.

А теперь о минусах.
Вверху файла ui_mainwindow.h есть предупреждающая надпись, на которую я не сразу обратил внимание:
Код:
WARNING! All changes made in this file will be lost when recompiling ui file!

Как оказалось файл ui_mainwindow.h переписывается после внесения любых изменений в форму GUI-приложения (а я размер кнопки изменил). Причём изменения, сделанные мною, не сохранились и пришлось снова прописывать в этот файл метод printText(QString str).
У меня возникла мысль, чтобы не зависеть от содержимого файла ui_mainwindow.h можно использовать свойство "наследование" от Ui_MainWindow, и к потомку от Ui_MainWindow добавить метод printText(QString str). Только после нескольких экспериментов с наследованием у меня ничего не вышло.  Улыбающийся

Вопрос в связи с этим такой: другие способы заставить работать кнопку есть?

Думаю, что данный вопрос будет интересен многим новичкам...
« Последнее редактирование: Май 24, 2009, 23:14 от Black Wolf » Записан
break
Гипер активный житель
*****
Offline Offline

Сообщений: 846


Просмотр профиля
« Ответ #4 : Май 24, 2009, 00:28 »

Сори за заранее резкийт тон! Но вы охинею несете - внимательнее читайте книгу про Qt. Скажите автора и вам будет сообщено на какой странице подробно написано о слотах, сигналах, кнопках.

Работаю с "Qt 4" 2 года - ни разун не пришлось лезть в файлы ui_ moc_ qrc_ и даже в целях разобраться не приходилось там копаться, так как все отлично освещено в документации - кромет того есть QtAssistent откуда тупо можно рабочие куски кода брать. Он же у вас стоит?

0) в стандартном случае кадой форме соответствует h и cpp файл - то есть это CPP- класс описанный стандартным способом + Qt правила для виджетов - в h файл надо заинклудить файл

#include "ui_XXXX.h"

где XXXXX - базовое имя файла ui

то есть

MyForm.ui - конструируем дизайнером форму
MyForm.h - создаем сами или через QtCreator (он вроде уже научился New->DesignerForm Class)
внутри этого h файла

#include "ui_MyForm.ui"
CMyForm: public QWidget
{
Q_OBJECT;
Ui::NameOfMainWidget_In_MyFormUI m_ui;
CInstrMainWindow( QWidget *parent = 0 ) : QWidget( parent )
{
   m_ui.setupUi( this );

}
}

естественно конструктор классан не обязан быть в файле h - я всегда его вношу в
MyForm.cpp - кот. также создастся через (New->DesignerForm Class) или вручную

NameOfMainWidget_In_MyFormUI - это имя того самого верхнего виджета в ui файле которое вы ему дадите в дизайнере

1) коннект не прокатывает у вас т.к. плохо читали доку - нен надо указывать имена параметров - только их типы, также не забывайте указывать макросы SLOT и SIGNAL

кроме того слоты вашего классы должны быть в соответствующей секции, класс должен быть унаследован от QObject, но еще и макрос внутри него должен быть Q_OBJECT; - как в форме выше.

MyClass : public QObject
{
Q_OBJECT;
QTimer m_timer;
private slots:
scuko();
}

где-то в коде:

   connect( &m_timer, SIGNAL(timeout()), this, SLOT(scuko()) );

3) есть специальный механизм автоматического распознавания и приконнекчивания слотов, то есть если есть класс формы - наподобие описанного выше, и в нем есть кнопка btnFuck(размещенная дизайнером на форме в ui и там же прописано это имя) можно написать в классе

CMyForm: public QWidget
{
Q_OBJECT;
Ui::NameOfMainWidget_In_MyFormUI m_ui;
CInstrMainWindow( QWidget *parent = 0 ) : QWidget( parent )
{
   m_ui.setupUi( this );

}
private slots:
void on_btnFuck_pressed();
void on_btnFuck_clicked(bool bChecked);
//и любые варианты с именем этой кнопки и поддерживаемыми ее классом сигналами
}


И забудьте про ""Go to slot..."" - это вас только запутает - делфи получится а не C++
Записан
UsBA
Гость
« Ответ #5 : Май 24, 2009, 23:07 »

Но вы охинею несете
Это не ахинея, а неоптимальное решение поставленной задачи, т.к. программа-то работает.

Скажите автора и вам будет сообщено на какой странице подробно написано о слотах, сигналах, кнопках
1. QT4 на примерах / Земсков В.Ю.,  СПб, БВХ-Петербург, 2008 г., 608 стр.
2. QT4: программирование GUI на C++ / Жасмин Бланшет, Марк Саммерфилд, Москва, КУДИЦ-ПРЕСС, 2007 г., 641 стр. (примерно)
3. QT4 профессиональное программирование на C++ / Макс Шлее, СПб, БВХ-Петербург, 2007 г., 880 стр.

#include "ui_MyForm.ui"
Может имеется в виду файл: ui_MyForm.h ?

1) коннект не прокатывает у вас т.к. плохо читали доку - нен надо указывать имена параметров - только их типы
Действительно, в connect у меня были имена.

где-то в коде:
   connect( &m_timer, SIGNAL(timeout()), this, SLOT(scuko()) );
Напишите, пож-та, правило (хотя бы основанное на вашем опыте программирования на QT), где можно/нужно прописывать connect. Фраза "где-то" не понятна.
Судя по примерам в книге [1] connect прописывается в классе, в который входят объекты формы приложения (а это файл ui_xxxx.h), т.е. кнопки, переключатели, полосы прокрутки (и пр.) и их свойства: размер, тип шрифта, цвет и т.д. Или я ошибаюсь?

Объясню причину, по которой я полез в файл ui_mainwindow.h
Создавая GUI своей проги в редакторе форм QT Creator я обратил внимание на закладку "Signals and slots editor", см.рис.:



Я открыл эту вкладку и стал прописывать signal для кнопки pushButton и slot для текстового поля lineEdit. И самое интересное, что во всплывающем списке я не нашёл slot с названием setText() для QLineEdit. Меня это удивило, т.к. в примерах из книг медот setText() применялся с объектом QLineEdit.

Тогда я полез в справку QT Assistant. В поиске набрал "QLineEdit" и затем прошел по первой ссылке "Qt 4.5: QLineEdit Class Reference". Там я посмотрел список "Public Slots", в котором был "void setText ( const QString & )".

Почему тогда в редакторе форм QT Creator я не смог прописать слот setText()? В общем этого я не понял и начал экспериментировать, благодаря чему и добрался до файла ui_mainwindow.h   Улыбающийся
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #6 : Май 25, 2009, 09:16 »

потому что у void clicked() и void setText(QString &) разные параметры
Записан
break
Гипер активный житель
*****
Offline Offline

Сообщений: 846


Просмотр профиля
« Ответ #7 : Май 26, 2009, 06:16 »

1)

Цитировать
#include "ui_MyForm.ui"
Может имеется в виду файл: ui_MyForm.h ?
-------- ДА (вот вы уже разбираетесь) - код писал здесь непроверяя и запарился

2)

Цитировать
где-то в коде:
   connect( &m_timer, SIGNAL(timeout()), this, SLOT(scuko()) );
Напишите, пож-та, правило (хотя бы основанное на вашем опыте программирования на QT), где можно/нужно прописывать connect. Фраза "где-то" не понятна

Если есть форма и нан ней "кнопка" и "лабел" - и скажем при нажатии на кнопку надо вывести что-то в "лабел" - и это действие постоянно для этой формы - то "коннект" можно прописать в конструкторе класса формы! В большинтве случаев я делаю именно так, но дело в том что в Qt есть не только визуальные компоненты, а в том числе таймеры, потоки, сокеты, и другие классы имеющие сигналы и слоты, и которые часто создаются в процессе работы программы динамически, в зависимости от действий пользоователя. Скажем есть кнопка - "установить соединение с серверов" - при ее нажатии должен создасться экземпляр класса QTcpSocket - и для дальнейшей работы должны связаться его сигналы с какими нибудь слотами из наших собственных классов. Естественно в конструкторе такое не сделать (только если собственный классн не будет создавать этоот сокет). Поэтому написал "где-то в коде". Очивидно это значит - где то после создания объекта и до того места где его сигналы должны ловиться. Да и с элементами интерфейса такое может быть т.к. формы могут динамически строиться и заранее не известно сколько будет "кнопок", "баттонов" и т.д. - а вот какие будут у них сигналы известно...

3)

Цитировать
Это не ахинея, а неоптимальное решение поставленной задачи, т.к. программа-то работает.
Не соглашусь - "неоптимальное" - это значит медленное но не "неправильное". А это решение именно "неправильное". Все надо использовать по инструкции (если она есть и сделана с умом) - если взять лопату и копать черенком - то задачу тоже решить можно, особенно если копать не вам и времени навалом.

если вы лезете в ui_____XXX qrc___XXX moc_XXX файлы сгенерированные предкомпиляторами - то это 100% неправильный путь!!!- можете меня не слушать - это вам любой кутешник скажет. вообще забудьте на 1 год о том что они есть - а потом и не понадобиться вспоминать.
Записан
UsBA
Гость
« Ответ #8 : Май 27, 2009, 00:21 »

потому что у void clicked() и void setText(QString &) разные параметры
Правильно ли я понял, что с помощью connect сигнал void clicked() и слот setText(QString &) не соединить?
То есть следующий ниже код работать не будет ?
Код:
connect( myButton, SIGNAL(clicked()), myLineEdit, SLOT(setText(QString &)) );

то "коннект" можно прописать в конструкторе класса формы!
Спасибо! Теперь понятнее.
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #9 : Май 27, 2009, 09:43 »

код работать будет. Если у слота парамаметров меньше, то лишние игнорируются. Нельзя соединить именно в креаторе (видимо защита от дурака)
Записан
Blayder
Гость
« Ответ #10 : Июль 18, 2009, 15:05 »

Раз поехали тут по сигналам и слотам, то я тож хочу присоединиться Улыбающийся
Примитивная задачка:
 - имеем кнопку, имеем слот.
Слот должен принимать 2 параметра, т.е. допустим mySlot(QString&, int &);
Насколько я сообразил, то единственным вариантом может быть:
 - для конекта к кнопке создаем беспараметровый слот, в теле которого прописываем необходимую задачу, как простую функцию?

По идее задача у меня такова на данный момент:
 - По нажатии кнопки передать ф-ции индэкх комбобокса и текст из LineEdit;
 Посоветуете, как это сделать по культурному?
Записан
ритт
Гость
« Ответ #11 : Июль 18, 2009, 15:51 »

сделать приватный слот, соединить его с сигналом clicked() конпки, и из него же эмитить некий сигнал mySignal(QString&, int &)
Записан
Blayder
Гость
« Ответ #12 : Июль 18, 2009, 16:08 »

Точно, хорошая мысль!
Благодарю за наводку  Веселый
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.057 секунд. Запросов: 23.