Russian Qt Forum

Программирование => С/C++ => Тема начата: Racot от Апрель 14, 2012, 15:59



Название: Общение между двумя объектами!
Отправлено: Racot от Апрель 14, 2012, 15:59
Код:
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow1 *w = new MainWindow1();
    MainWindow2 *w2 = new MainWindow2();

    w->show();

    return a.exec();
}

У меня есть 2 формы классов MainWindow1 и MainWindow2.На каждой есть по кнопке, по нажатию которой должна появляется другая форма, а эта скрывается. То есть в слоте обработки нажатия на кнопку должно быть примерно так:
Код:
void MainWindow1::on_pushButton_clicked()
{
  w2->show();
  w1->hide(); 
}

но класс MainWindow1 ничего же не знает о объекте w2. Как это делается? Можно MainWindow1 *w и
MainWindow2 *w2 объявлять глобально.Но я читал что  это не правильно.(тем более допустим в java нет глобальных переменных, но там же как то это реализовывается). В общем кто реализовывал многооконные интерфейсы - помогите!!


Название: Re: Общение между двумя объектами!
Отправлено: alexis031182 от Апрель 14, 2012, 16:19
Вам нужно просто в обоих объектах класса MainWindow сохранять указатели друг на друга. Напишите в MainWindow функцию, например:
Код:
void MainWindow::setCorrespondingWindow(MainWindow *mw)
{
_mw = mw;
}
А в заголовочном mainwindow.h объявите указатель на объект:
Код:
MainWindow _mw;
Как только создадите объекты обоих окон, выполните для каждого вышеуказанную функцию, которая и предоставит доступ каждого окна к другому.


Название: Re: Общение между двумя объектами!
Отправлено: kambala от Апрель 14, 2012, 16:29
как по мне, лучше это делать через отдельный класс-менеджер


Название: Re: Общение между двумя объектами!
Отправлено: Racot от Апрель 14, 2012, 16:46
Как только создаю в каждом из классов указатели друг на друга.....то компилятор мне выдаёт -

Цитировать
..\Temp_pro\/mainwindow2.h:15: error: ISO C++ forbids declaration of 'MainWindow1' with no type
..\Temp_pro\/mainwindow2.h:15: error: expected ';' before '*' token

alexis031182  вы сами пробывали?


Цитировать
как по мне, лучше это делать через отдельный класс-менеджер
что есть класс-менеджер???


Название: Re: Общение между двумя объектами!
Отправлено: alexis031182 от Апрель 14, 2012, 16:56
как по мне, лучше это делать через отдельный класс-менеджер
Да, конечно. А ещё можно вообще обойтись без сохранения указателей друг на друга и решить задачу через сигнал/слоты.
Код:
MainWindow1 *w = new MainWindow1();
MainWindow2 *w2 = new MainWindow2();
connect(w, SIGNAL(my_sygnal()), w2, SLOT(my_slot()));
connect(w2, SIGNAL(my_sygnal()), w, SLOT(my_slot()));
А внутри слота my_slot() через qobject_cast<MyWindow*>(sender()) получать указатель на вызвавшего переключение окно.


Название: Re: Общение между двумя объектами!
Отправлено: kambala от Апрель 14, 2012, 16:59
Как только создаю в каждом из классов указатели друг на друга.....то компилятор мне выдаёт -

Цитировать
..\Temp_pro\/mainwindow2.h:15: error: ISO C++ forbids declaration of 'MainWindow1' with no type
..\Temp_pro\/mainwindow2.h:15: error: expected ';' before '*' token

alexis031182  вы сами пробывали?


Цитировать
как по мне, лучше это делать через отдельный класс-менеджер
что есть класс-менеджер???
1. допиши в заголовочных файлах соответственно class MainWindow1 и class MainWindow2
2. отдельный класс (возможно наследник QObject), который будет показывать и скрывать нужное окно


Название: Re: Общение между двумя объектами!
Отправлено: alexis031182 от Апрель 14, 2012, 17:03
alexis031182  вы сами пробывали?
:) не надо просто копипастить. Попробуйте разобраться.

Указанная ошибка говорит о том, что Вы не добавили объявления классов друг на друга в их заголовки.


Название: Re: Общение между двумя объектами!
Отправлено: Racot от Апрель 14, 2012, 17:04
Цитировать
1. допиши в заголовочных файлах соответственно class MainWindow1 и class MainWindow2

в том то и беда что заголовочные файлы добавлены(((((((


Название: Re: Общение между двумя объектами!
Отправлено: Racot от Апрель 14, 2012, 17:07
mainwindow1.h

#ifndef MAINWINDOW1_H
#define MAINWINDOW1_H

#include <QMainWindow>
#include "mainwindow2.h"

namespace Ui {
    class MainWindow1;
}

class MainWindow1 : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow1(QWidget *parent = 0);
    ~MainWindow1();

 /*   void get_win2(MainWindow2 *win2)
    {
      mw2= win2;
    }*/

private slots:
    void on_pushButton_clicked();

private:
    Ui::MainWindow1 *ui;
    MainWindow2 *mw2;
};

#endif // MAINWINDOW1_H

//////////////////////////////////////////////////////////////////////////////////////////////////////////

mainwindow2.h

#ifndef MAINWINDOW2_H
#define MAINWINDOW2_H

#include <QMainWindow>
#include "mainwindow1.h"

namespace Ui {
    class MainWindow2;
}

class MainWindow2 : public QMainWindow
{
    Q_OBJECT



public:
    explicit MainWindow2(QWidget *parent = 0);
    ~MainWindow2();

private:
    Ui::MainWindow2 *ui;
    MainWindow1 *mw1;
};

#endif // MAINWINDOW2_H

ничего не копипастил.......вот выдаёт ошибку


Название: Re: Общение между двумя объектами!
Отправлено: alexis031182 от Апрель 14, 2012, 17:11
А зачем Вам там namespace, да плюсом ещё и указатель на самого себя?


Название: Re: Общение между двумя объектами!
Отправлено: Racot от Апрель 14, 2012, 17:15
Цитировать
А зачем Вам там namespace, да плюсом ещё и указатель на самого себя?

Вы про это?

namespace Ui {
    class MainWindow1;
}

private:
    Ui::MainWindow1 *ui;

так это QtCreator сам код создаёт.дело точно не в этом.


Название: Re: Общение между двумя объектами!
Отправлено: alexis031182 от Апрель 14, 2012, 17:21
Вы про это?
...
Да.

так это QtCreator сам код создаёт.дело точно не в этом.
А ну понял. Я не пользуюсь этим функционалом, поэтому обратил внимание, что вроде показалось мне излишним. Ну да ладно. Так-то вроде всё верно написано. Попробуйте очистить проект и заново пересобрать.


Название: Re: Общение между двумя объектами!
Отправлено: Racot от Апрель 14, 2012, 17:27
очистил.пересобрал. та же ошибка.


Название: Re: Общение между двумя объектами!
Отправлено: alexis031182 от Апрель 14, 2012, 17:29
В обоих файлах:
Код:
namespace Ui {
class MainWindow;
class MainWindow2;
}


Название: Re: Общение между двумя объектами!
Отправлено: kambala от Апрель 14, 2012, 17:32
Код
C++ (Qt)
// mainwindow1.h
 
#ifndef MAINWINDOW1_H
#define MAINWINDOW1_H
 
#include <QMainWindow>
#include "mainwindow2.h"
 
namespace Ui {
   class MainWindow1;
}
 
class MainWindow2; // тут должен быть "противоположный" класс
 
class MainWindow1 : public QMainWindow
...


Название: Re: Общение между двумя объектами!
Отправлено: Racot от Апрель 14, 2012, 17:39
Цитировать
class MainWindow2; // тут должен быть "противоположный" класс

а я думал что если хедер вставил то и объявлять не надо класс.....

Всем спасибо! помогло!!!!!!!


Название: Re: Общение между двумя объектами!
Отправлено: kambala от Апрель 14, 2012, 18:24
вот как раз хедер лучше подключать не в .h, а в .cpp


Название: Re: Общение между двумя объектами!
Отправлено: Racot от Апрель 14, 2012, 18:50
и то верно ;D


Название: Re: Общение между двумя объектами!
Отправлено: Igors от Апрель 15, 2012, 10:00
Решение сохранять указатели будет работать, но оно немногим лучше глобальных переменных. В обоих случаях 2 класса "знают" друг о друге, образуется "зависимость". Пока задача достаточно проста все нормально. Но предположим появился MainWindow3, т.е. переключаться надо уже между 3 формами. Переделать указатели будет совсем не легко.

Более капитальное (и правильное) решение указал kambala. Просто можно не спешить с классом-менеджером, а пока сделать так

- кнопки в окнах испускают сигналы
- в main (пока) эти сигналы связываются со слотами hide/show окон

Когда возникнет необходимость в более сложном переключении - мы свяжем сигналы уже с чем-то другим (там видно будет), но нам не придется кромсать  MainWindow1(2, 3)


Название: Re: Общение между двумя объектами!
Отправлено: alexis031182 от Апрель 15, 2012, 10:44
...
Более капитальное (и правильное) решение указал kambala. Просто можно не спешить с классом-менеджером, а пока сделать так

- кнопки в окнах испускают сигналы
- в main (пока) эти сигналы связываются со слотами hide/show окон
...
Кнопки на формах, а значит любую из них нельзя подключить к "противостоящей" форме. Соответственно, только через самопальные сигналы форм. Впрочем, труда здесь безусловно немного.


Название: Re: Общение между двумя объектами!
Отправлено: Racot от Апрель 17, 2012, 20:45
Гм.........я уже думал что "познал смысл жизни".......но Igors (похоже что умный мужик) опять меня запутал. А как делается там где нет сигналов и слотов(не в QT)??? Я просто не силён в ООП и хотел добраться до истины - "как делается это у нормальных людей?". Наверняка это тривиальная задача сделать интерфейс из нескольких главных окон(которая проделывалась тысячи раз тысячами людьми).
И я почти был уверен что это делается средствами ООП и C++(это же просто общение двух объектов).


Название: Re: Общение между двумя объектами!
Отправлено: Tonal от Апрель 18, 2012, 09:50
Сигналы/слоты тоже не содержат ничего магического. Там указатели на объекты и их функции. Просто в рамках Qt это автоматизировано с помощью дополнительных ключевых слов и генерации кода - специализированного препроцессора.

В чистом С/С++ весь этот код нужно писать руками. Правда есть некоторое количество библиотек сокращающих писанину. :)

В Qt можно придерживаться простого правила:
Дочерний виджет не знает интерфейса родителя, а родительский знает интерфейс дочернего.
Это приводит к тому, что дочерний посылает сигналы, когда ему есть, что сказать, а родительский вызывает функции дочерних, когда ему это зачем-то нужно. :)
Т. е. родительский выступает для своих дочерних менеджером, о котором писал kambala.
Иногда, можно в родительском просто связать сигнал/слоты дочерних, иногда требуется какая-то более сложная обработка.