Почти всегда стоит задача создать более одной формы. И чаще всего эти формы должны обмениваться данными.
Для примера мы с вами создадим две формы. В первой будет поле ввода и кнопка. В поле ввода мы с вами будем вводить ФИО, а при нажатии на кнопку у нас будет открываться вторая форма, в которой ФИО вводится в 3-х полях, фамилия, имя и отчество. При этом из первой формы во вторую необходимо передать уже введённые данные, дабы не выводить пустую форму. А по нажатию кнопки "Ок" во второй форме передать введённые данные в первую форму.
Итак, для начала создадим стандартное Gui приложение Qt.
Теперь на главной форме в Дизайнере добавим поле ввода (QLineEdit) и кнопку(QBushButton), как показано на рисунке. Имена объектов оставим стандартными, дабы не запутаться.
Теперь нам необходимо создать и добавить вторую форму.
Переходим Файд -> Новый файл или проект... -> Qt -> КлассФормы Qt Designer.
Выбираем Widget, оставляем стандартное имя Form и добавляем в наш проект.
На второй форме добавляем 3 QLineEdit и ButtonBox, имена оставляем стандартными.
И создадим указатель на нашу будущую форму:
Пол дела сделано. Теперь необходимо создать эту самую форму. Для этого, в конструкторе главного окна добавим создание нового объекта.
Теперь нам необходимо по нажатию на кнопку показать 2-ю форму. Для в том же конструкторе подключим сигнал clicked() кнопки к слоту show() нашей формы.
После сборки приложения по нажатию на кнопку вы увидите, вторую форму.
Теперь нам необходимо передать уже введенные данные из первой формы во вторую. Для этого в mainwindow.h добавим сигнал, который будет отправлять введённые данные, и слот, который будет реагировать на нажатие кнопки и вызывать этот сигнал.
signals:
Сигнал определять не надо! (у некоторых такое бывает :) )
А вот слот надо определить.
Запись emit вызывает сигнал sendData, который в свою очередь передаёт "куда-то" данные из lineEdit.
Теперь необходимо подключить к слоту onButtonSend сигнал клика по кнопке, дабы он сработал. Лично я все подключения делаю в конструкторе.
Во второй форме необходимо к чему-то подключить этот сигнал, да ещё и обработать.
В form.h объявляем слот-приемник.
Там же подключите класс QStringList, он нам потребуется. Этот класс предназначен для работы со списком строк.
В form.cpp определяем логику его работы.
Осталось подключить к этому слоту сигнал из главной формы. Для этого в конструкторе в mainwindow.cpp :
Теперь можете компилить и запускать. После ввода в первой форме какого-нибудь текста через пробел и нажатия кнопки, во второй форме будут эти данные разбиты по полям ввода.
Я думаю вы и сами сможете завершить задачу... Надеюсь вторую часть вы напишите сами.. А если не получится, обращайтесь :)
P. S. Если есть пожелание что ещё расписать, пишите, не стесняйтесь. А то я опять уйду в дебри.
Для примера мы с вами создадим две формы. В первой будет поле ввода и кнопка. В поле ввода мы с вами будем вводить ФИО, а при нажатии на кнопку у нас будет открываться вторая форма, в которой ФИО вводится в 3-х полях, фамилия, имя и отчество. При этом из первой формы во вторую необходимо передать уже введённые данные, дабы не выводить пустую форму. А по нажатию кнопки "Ок" во второй форме передать введённые данные в первую форму.
Итак, для начала создадим стандартное Gui приложение Qt.
Теперь на главной форме в Дизайнере добавим поле ввода (QLineEdit) и кнопку(QBushButton), как показано на рисунке. Имена объектов оставим стандартными, дабы не запутаться.
Теперь нам необходимо создать и добавить вторую форму.
Переходим Файд -> Новый файл или проект... -> Qt -> КлассФормы Qt Designer.
Выбираем Widget, оставляем стандартное имя Form и добавляем в наш проект.
На второй форме добавляем 3 QLineEdit и ButtonBox, имена оставляем стандартными.
Теперь будем действовать по порядку. Первый делом
добавим новую форму в уже существующее главное окно. Для этого в mainwindow.h
подключим заголовочный файл формы:
#include "form.h"
И создадим указатель на нашу будущую форму:
private:
Form *myform;
Пол дела сделано. Теперь необходимо создать эту самую форму. Для этого, в конструкторе главного окна добавим создание нового объекта.
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
myform = new Form(); // создаем нашу форму
}
Теперь нам необходимо по нажатию на кнопку показать 2-ю форму. Для в том же конструкторе подключим сигнал clicked() кнопки к слоту show() нашей формы.
connect(ui->pushButton, SIGNAL(clicked()), myform, SLOT(show())); // подключаем сигнал к слоту
После сборки приложения по нажатию на кнопку вы увидите, вторую форму.
Теперь нам необходимо передать уже введенные данные из первой формы во вторую. Для этого в mainwindow.h добавим сигнал, который будет отправлять введённые данные, и слот, который будет реагировать на нажатие кнопки и вызывать этот сигнал.
signals:
void sendData(QString str);
private slots:
void onButtonSend();
Сигнал определять не надо! (у некоторых такое бывает :) )
А вот слот надо определить.
void MainWindow::onButtonSend()
{
emit sendData(ui->lineEdit->text()); // вызываем сигнал, в котором передаём введённые данные
}
Запись emit вызывает сигнал sendData, который в свою очередь передаёт "куда-то" данные из lineEdit.
Теперь необходимо подключить к слоту onButtonSend сигнал клика по кнопке, дабы он сработал. Лично я все подключения делаю в конструкторе.
connect(ui->pushButton, SIGNAL(clicked()), this, SLOT(onButtonSend())); // подключаем клик по кнопке к определенному нами слоту
Во второй форме необходимо к чему-то подключить этот сигнал, да ещё и обработать.
В form.h объявляем слот-приемник.
public slots:
void recieveData(QString str);
Там же подключите класс QStringList, он нам потребуется. Этот класс предназначен для работы со списком строк.
#include <QStringList>
В form.cpp определяем логику его работы.
void Form::recieveData(QString str)
{
QStringList lst = str.split(" "); // Объявляем список строк lst. Разбиваем полученную строку на несколько строк. Разделитель строк - пробел
if (lst.size() > 0) ui->lineEdit->setText(lst.at(0)); // Если в списке 1 и более строк, то 0-ую записываем в первое поле ввода
if (lst.size() > 1) ui->lineEdit_2->setText(lst.at(1)); // Если в списке 2 и более строк, то 1-ую записываем в первое поле ввода
if (lst.size() > 2) ui->lineEdit_3->setText(lst.at(2)); // Если в списке 3 и более строк, то 2-ую записываем в первое поле ввода
}
Осталось подключить к этому слоту сигнал из главной формы. Для этого в конструкторе в mainwindow.cpp :
connect(this, SIGNAL(sendData(QString)), myform, SLOT(recieveData(QString))); // подключение сигнала к слоту нашей формы
Теперь можете компилить и запускать. После ввода в первой форме какого-нибудь текста через пробел и нажатия кнопки, во второй форме будут эти данные разбиты по полям ввода.
Я думаю вы и сами сможете завершить задачу... Надеюсь вторую часть вы напишите сами.. А если не получится, обращайтесь :)
P. S. Если есть пожелание что ещё расписать, пишите, не стесняйтесь. А то я опять уйду в дебри.
Спасибо )
ОтветитьУдалитьЗдравствуйте Сергей, спасибо за статью. Но есть вопрос всё сделал как вы описали и всё прекрасно работало. Но потом по взмаху волшебной палочки всё перестало работать 10 раз проверил, но безуспешно. Может у вас есть какие нибудь мысли по этому поводу?
ОтветитьУдалитьА че говорит?
УдалитьУ меня не выходит обратная передача данных из формы в главное окно, в конекте пишу
ОтветитьУдалитьconnect(this,SIGNAL(form(double)), MainWindow ,SLOT(res(double)));
но выдает ошибку, как мне обратиться к главному окну, в слот определенный в главном окне передать сигнал из формы?
Понимаю, что вы уже скорей всего решили эту проблему, но для других людей с такой же проблемой отвечу:
УдалитьСоединение всех слотов и сигналов надо выполнять в главном окне, так как именно оно знает всё о формах, которые в нём используются. Форма может вообще ничего не знать о других окнах. Поэтому следует делать сразу пару соединений:
connect(this, SIGNAL(sendData(QString)), myform, SLOT(recieveData(QString))); // посылаются данные в форму
connect(myform, SIGNAL(sendData(QString)), this, SLOT(recieveData(QString))); //получаются данные из формы. Вместо this может стоять указатель на другую форму, которой передаём строку.
Возможен такой вариант:
connect(myform, SIGNAL(sendData(QString)), labelFromMainWindow, SLOT(setText(QString))); //полученные из формы данные отобразятся в виджете labelFromMainWindow
Спасибо. Вот ты реально выручил.
УдалитьЭтот комментарий был удален автором.
ОтветитьУдалитьНе совсем понял суть вопроса...
ОтветитьУдалитьЗачем setCentralWidget? почему нельзя для отображения просто использовать метод show() ?
Не компилится
ОтветитьУдалитьC:/2Form/mainwindow.h:28: error: extra qualification 'MainWindow::' on member 'onButtonSend'
Значит где-то сделали ошибку. По данной информации я могу лишь предположить что вы описали метод внутри классов при этом используя ::
УдалитьЧетко! Сергей, пожалуйста продолжайте выпускать статьи, у Вас хорошо получается!)
ОтветитьУдалитьQObject::connect: No such slot Form::onButtonSend() in ..\untitled\mainwindow.cpp:14
ОтветитьУдалитьQObject::connect: No such slot Form::recData(Qstring) in ..\untitled\mainwindow.cpp:15
Подскажите пожалуйста, у меня все компилится, но не передает в дополнительную форму, что не так?
Вам же чётко сообщают - нет таких слотов.
УдалитьМетоды Form::onButtonSend() и Form::recData(Qstring) в описании класса Form должны располагаться в секции public slots, а у вас они, скорей всего, описаны как public
Есть ещё одна маленькая фишка, о которой новички узнают не сразу, ибо она не очевидна, хотя и описана в документации.
ОтветитьУдалитьФома может узнать о том, кто передал ей данные (обычно это именно тот, кому данные надо будет вернуть) непосредственно из слота Form::recieveData(QString):
voidForm::recieveData(QString)
{
QObject *obj = QObject::sender();
// в obj будет лежать указатель на того, кто вызвал этот слот
// Делай с ним, что считаешь нужным. Но это усиливает связь между объектами
}
Ну и в завершение.
ОтветитьУдалитьСоветую всем обратить внимание, что в Qt в качестве параметров функций используется "const QString &", а не "QString". Винда не обращает на это внимание, а вот Линукс засыплет вас ворнингами, среди которых искать сообщения об ошибках становится проблематично.
У меня вопрос, как сделать консоль, что бы после ввода данных, в окошко ввода, их можно было посчитать, там сделать определенные расчеты и в окошко вывода получить ответ, при этом ответ получаем при нажатии на кнопку.
ОтветитьУдалитьВ Pro-файле прописать CONFIG += console. Сам случайно где-то высмотрел. До этого сколько не пытался вывести qDebug() << - ом информацию в консоль, ничего не получалось. Главное, что в примерах нигде этого не видел (кроме этого одного раза) :)
УдалитьЗдравствуйте!!Пожалуйста помогите в вопросе.как можно передать значения ячеек строки (массив) tablewidgetа в другую форму при клике по ячейке из этой строки.Пробовал по клику кнопки-получилось.По клику ячейки -нет..
ОтветитьУдалитьЯ так и не понял, как из другой формы передать данные в первую форму? Из первой во вторую я и без вас могу. И без слотов все это делается.
ОтветитьУдалитьЯ из второй в первую как делать незнаю. Ибо в первой форме:
#include "form2.h"
А во второй форме такой херни нету, и она не знает о существовании второй формы.
Ошибка...(((
ОтветитьУдалитьQObject::connect: No such slot Dialog_io::recieveData(QString) in ../testSql/mainwindow.cpp:124
QObject::connect: (sender name: 'MainWindow')
QObject::connect: (receiver name: 'Dialog_io')
Метод в Dialog_io.h
public slots:
void reciveData(QString str);
Как победить? Спасибо.
Подскажите что делать, если я хочу передать класс, а не стандартные переменные?
ОтветитьУдалитьидти и спрашивать в ответах маил ру
УдалитьНе понимаю, в чем проблема, либо выдает ошибку Cannot connect MainWindow::sendData(bool) to (nullptr)::recieveData(bool), либо вообще крашит программу с текстом "программа экстренно завершила работу, т.к. получила сигнал от системы sigmetation fail"
ОтветитьУдалитьЧто я делаю не так? Мне просто нужно из второй формы (модальной) получить значение булевой переменной. В гл. форме обЪявляю переменную, передаю ее значение во вторую, а оттуда обратно. Еще пробовал просто передать из второй формы значение переменной и уже в главной изменить значения (все connect в главной форме как и писали)
Интересно, не ругается, но и не работает...
ОтветитьУдалить