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

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

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Наследование классов и обьектов  (Прочитано 13693 раз)
skytrain
Гость
« : Март 11, 2013, 00:44 »

Добрый день.
Среда Qt Creator (Qt 4.Крутой ОС Linux
Суть вопроса:
Есть Форма Ui_widget.h
Автосозданный класс
Код:
#include <QWidget>
#include<ui_widget.h>
namespace Ui {
class Widget;
}
class PreviewFrame;
class Widget : public QWidget
{
    Q_OBJECT  
public:
    explicit Widget(QWidget *parent=0);
    ~Widget();
    // virtual void iLoad();  Хочется сделать ее виртуальной
private:
    Ui::Widget *ui;
     PreviewFrame * ptrWiget;
public slots:
    void MySlot();
};
И класс PreviewFrame
Код:
#include<widget.h>
============
class PreviewFrame : public QFrame // А хочется public Widget
{
    Q_OBJECT
public:
    explicit PreviewFrame(QWidget *parent);
    void iLoad();
    QImage img;
protected:
    void paintEvent(QPaintEvent *event);
Qframe * ptrFrame;
private:
};
Есть ли возможность Widget сделать базовым для PreviewFrame. и сделать так, что-бы были доступны открытые функции QFrame через указатель.
Если я указываю public Widget, то получаю сообщение о необходимости реализации класса Widget.
В widget.h нет реализации.
Константы компиляции определены по одной на каждый заголовочный файл.
Все это затевается для того, что-бы было можно создавать виртуальные функции с последующим выводом их в абстрактный класс.
Можно ли исправить ситуацию или переформулировать задачу.

С уважением.
Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4744



Просмотр профиля WWW
« Ответ #1 : Март 11, 2013, 02:13 »

вынеси общую функциональность в отдельный класс и используй множественное наследование
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
skytrain
Гость
« Ответ #2 : Март 11, 2013, 04:48 »

Если так, то:
1. Увы, но я не до конца понимаю механизм взаимодействия класса Widget и формы дизайнера.
В каких классах можно\нужно использовать конструкцию
Код:
namespace Ui {
class SomeClass;
}
для доступа к объектам формы.

2. Если можно.... В двух РУССКИХ словах о методе setupUi(this);

3. И все-таки почему (Кроме невозможности наследования от двух классов наследующих QObject. На это ругается перепроцессор) нельзя указать Widget как базовый класс в моем примере. Я ловлю другую ошибку.
/home/scytrain/develop/project/mywidget/previewframe.h:9: ошибка: expected class-name before '{' token
а если перед описанием класса стоит прототип Widget, то
/home/scytrain/develop/project/mywidget/previewframe.h:10: ошибка: invalid use of incomplete type 'struct Widget'
Суть которых сводится отсутствию реализации Widget
Можно ли поправить это хитрым образом определив константы компиляции в двух файлах заголовков (Чтоб компилятор думал что файл у него один) или другими методами. Например настройками .pro файла.

По остальному в голове бардак.
Я постараюсь его выразить позже.
Извините. Сейчас надо спать идти.
Спасибо.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #3 : Март 11, 2013, 09:10 »

Widget объявлен в namespace Ui, значит в начале PreviewFrame.h надо написать
Код
C++ (Qt)
using Ui::Widget;
 

[/offtop]
Имя "Widget" говорит о скудной фантазии  Улыбающийся
Записан
skytrain
Гость
« Ответ #4 : Март 11, 2013, 23:48 »

В ответ на
using Ui::Widget; в начале класса получаю
/home/scytrain/develop/project/mywidget/previewframe.h:10: ошибка: 'Ui' has not been declared

P.S Извините не было инклюда формы.

 А при размещении в начале класса
Код:
namespace Ui {
class PreviewFrame;
==========
private:
    Ui::PreviewFrame *ui2;
}
Я получаю доступ к объектам формы через *ui2. Но будет ли правильно так поступать?


« Последнее редактирование: Март 12, 2013, 01:27 от skytrain » Записан
skytrain
Гость
« Ответ #5 : Март 12, 2013, 03:08 »

И вот собственно к чему пришли...
В том моменте где были неясности соответственно нашлись ошибки.
Код:
class Widget;
}
class PreviewFrame;
class CommonPlase;
class Widget : public QWidget
{
    Q_OBJECT   
public:
    explicit Widget(QWidget *parent=0);
    ~Widget();
private:
    Ui::Widget *ui;
    PreviewFrame * ptrWiget;
   CommonPlase * ptrPlase;
public slots:
    void MySlot();
};

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    ptrPlase=new PreviewFrame(ui->frame);
    ptrPlase->iLoad();
    qDebug() << ui->frame->parent();
    qDebug() << ui->pushButton->parent();
    QObject::connect(ui->pushButton, SIGNAL(clicked()), this, SLOT(MySlot()));
}
void Widget::MySlot()
{
    qDebug() << ui->frame->geometry();
   // QRect rec(QPoint(0,0), QSize(200,200));
    ptrWiget->setGeometry(ui->frame->geometry()); // Ошибка здесь!!!!
    ptrWiget->update();
}
Widget::~Widget()
{
    delete ui;
}
Указатели CommonPlase * ptrPlase; и PreviewFrame * ptrWiget; являются членами класса Widget
Естественно что ptrWiget никакого отношения к форме пока не имеет.
По логике вещей, если ptrWiget = new PreviewFrame(ui->frame), то мы получим два указателя на объекты потомки frame(По объектной модели qt) И второй отрисует изображение поверх первого, при клике.
А два объекта вроде как не нужно......
Если можно наставьте на путь истинный. Как можно разрешить ситуацию?
Можно-ли не использовать ptrWiget и дать возможность использовать паблики QFrame'а указателю ptrPlase?
Но наверно я хочу странного.... так как CommonPlase абстрактный класс..

Наверно лучше немного переделать структуру проекта чтоб не ловить эту ошибку. Но как - это пока выше меня.
Сейчас у меня почти все действия в конструкторе Widget. Наверное для него это слишком.

Заранее спасибо.
Записан
Bepec
Гость
« Ответ #6 : Март 12, 2013, 07:00 »

Можно вопрос? А что вы хотите получить от QWidget и от QFrame?

Мб вам это наследование и не нужно?
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #7 : Март 12, 2013, 09:43 »

Я получаю доступ к объектам формы через *ui2. Но будет ли правильно так поступать?
Ну еще не получаете если он private. А поступать так неправильно. Ui (namespace) обозначает ту область где будет резвиться дизайнер, т.е. тамошние классы будут создаваться/удаляться интерактивно. Привязываясь к ним Вы можете оказаться в неудобном положении если в дизайнере что-то изменилось.

Если Вам нужен объект созданный в дизайнере - лучше достать его по имени. Если он должен иметь тип что Вы хотите - подсуньте дизайнеру свой хедер, так можно. Вообще если опыта маловато - дизайнер лучше отложить.

Да, и желательно более четкий пример классов - с тем что Вы показали трудно что-то советовать
Записан
skytrain
Гость
« Ответ #8 : Март 12, 2013, 23:37 »

Можно вопрос? А что вы хотите получить от QWidget и от QFrame?

Мб вам это наследование и не нужно?
Да вы правы. Не нужно и не правильно. Тот код уже переписан.
PreviewFrame теперь наследует абстрактный класс и QFrame. А в конструктор передается указатель на обьект формы, на котором будет отрисовка. (Слава богу с этим разобрался)
Записан
skytrain
Гость
« Ответ #9 : Март 12, 2013, 23:49 »

Если Вам нужен объект созданный в дизайнере - лучше достать его по имени. Если он должен иметь тип что Вы хотите - подсуньте дизайнеру свой хедер, так можно. Вообще если опыта маловато - дизайнер лучше отложить.
Я думаю что дизайнер лучше сразу "победить". Потом хлопот будет много... Мне так кажется. Благо время есть.
 
Спасибо.
Записан
skytrain
Гость
« Ответ #10 : Март 13, 2013, 00:06 »

Заголовки классов.

Код:
#ifndef COMMONPLASE_H
#define COMMONPLASE_H
//#include <QObject>
class CommonPlase
{
public:
    CommonPlase();
  //  ~CommonPlase();
    virtual void iLoad()=0;
};
#endif // COMMONPLASE_H

#ifndef PREVIEWFRAME_H
#define PREVIEWFRAME_H
#include <QWidget>
#include <widget.h>
#include<QFrame>
#include<QPainter>
#include<ui_widget.h>
#include"commonplase.h"
namespace Ui {
class PreviewFrame;
//using Ui::Widget;
}
class PreviewFrame : public QFrame, public CommonPlase
{
    Q_OBJECT
public:
    explicit PreviewFrame(QWidget *parent);
    void iLoad();                                                 // Виртуальная
    QImage img;
    PreviewFrame *ptrPreviewFrame;
protected:
    void paintEvent(QPaintEvent *event);
private:
    //Ui::PreviewFrame *ui2;
};
#endif // PREVIEWFRAME_H

#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include<previewframe.h>
#include<ui_widget.h>
namespace Ui {
class Widget;
}
class PreviewFrame;
class CommonPlase;
class Widget : public QWidget
{
    Q_OBJECT
public:
    explicit Widget(QWidget *parent=0);
    ~Widget();
private:
    Ui::Widget *ui;
    PreviewFrame * ptrWiget;
    //friend class PreviewFrame;
   CommonPlase * ptrPlase;
public slots:
    void MySlot();
};
#endif // WIDGET_H

// Для ясности выкладываю конструктор Widget

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    ptrPlase=new PreviewFrame(ui->frame);
    ptrPlase->iLoad();
    qDebug() << ui->frame->parent();
    qDebug() << ui->pushButton->parent();
    QObject::connect(ui->pushButton, SIGNAL(clicked()), this, SLOT(MySlot()));

}
void Widget::MySlot()
{
    qDebug() << ui->frame->geometry();
/*По логике вещей, если внутри слота ptrWiget = new PreviewFrame(ui->frame), то
мы получим два указателя на объекты потомки frame(По объектной модели qt)
И второй отрисует изображение поверх первого, при клике.
А два объекта вроде как не нужно......*/    
    ptrWiget->setGeometry(ui->frame->geometry());
    ptrWiget->update();
}

Если можно наставьте на путь истинный. Как можно разрешить ситуацию? (Коментарии в коде.)
Можно-ли не использовать ptrWiget и дать возможность использовать паблики QFrame'а указателю ptrPlase?
Или через указатели как то до них добраться....
Но наверно я хочу странного.... так как CommonPlase абстрактный класс..

Наверно лучше немного переделать структуру проекта чтоб не ловить эту ошибку. Но как - это пока не соображу как лучше.
Сейчас у меня почти все действия в конструкторе Widget. Наверное для него это слишком.

Заранее спасибо.
« Последнее редактирование: Март 13, 2013, 00:43 от skytrain » Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4744



Просмотр профиля WWW
« Ответ #11 : Март 13, 2013, 01:30 »

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

не приведены реализации метода iLoad() чтобы понять ради чего он вообще задумывался.

P.S. Plase — какое-то странное слово.
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
skytrain
Гость
« Ответ #12 : Март 13, 2013, 01:55 »

Хочется до конца освоить механизмы взаимодействия объектов и классов.
Главная задача - воспроизводить видео и картинки через спец фильтры. Но она еще далеко.
Пока надо до конца понять что такое Абстрактный класс и с чем его едят.
Сейчас ситуация такова:
Цель - сформировать каркас проекта. Определить общие для всех типов загружаемых данных функции.
Есть виджет. На нем должна быть нарисована картинка и перерисована по нажатии кнопки. (В дальнейшем планируется перенести этот код в какое либо событие.)
Я конструкцией
ptrPlase=new PreviewFrame(ui->frame);
Присваиваю указателю на абстрактный класс адрес объекта, который будет отображен на форме.
Функция virtual iLoad()=0; это член абстрактного класса CommonPlase и переопределена в PreviewFrame ( Я думаю что она должна быть общей)
Проблема!!!
В слоте надо(для эксперимента) изменить размер отображаемого объекта и отрисовать снова вызовом update()
Но... Указатель на абстрактный класс не наследует public функций QFrame.
А если создавать полновесный экземпляр отображаемого объекта класса PreviewFrame, то он отрисует картинку поверх первой. А это кажется не гуд...
Как можно грамотно это победить?

и... если можно своими словами. Как правильнее в этой ситуации использовать абстрактный класс и обеспечить взаимодействие объектов.  

Надеюсь будет понятно....
Спасибо.!!!

P.S. Plase — какое-то странное слово.
Ошибся. В идеале было Place.
« Последнее редактирование: Март 13, 2013, 02:07 от skytrain » Записан
Bepec
Гость
« Ответ #13 : Март 13, 2013, 06:51 »

Вы напишите что в результате хотите получить. Если слов нехватает - пейнт в руки и нарисуйте. Что-то типа,
Код:
хочу сделать обработку кадров. На форме будет показываться кадр и слева будет выбор эффектов. 

А так я до сих пор не понимаю, нафига тебе QFrame... Всё что ты описал в вышестоящем сообщении - это переопределение paintEvent у виджета и... всё?! помоему всё.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #14 : Март 13, 2013, 09:42 »

Пока надо до конца понять что такое Абстрактный класс и с чем его едят.
Сейчас ситуация такова:
Цель - сформировать каркас проекта. Определить общие для всех типов загружаемых данных функции.
Звучит довольно расплывчато. Пока я не увидел что Вы хотите обобщить и для чего нужен абстрактный класс.

Есть виджет. На нем должна быть нарисована картинка и перерисована по нажатии кнопки. (В дальнейшем планируется перенести этот код в какое либо событие.)
Ну и сделайте в Вашем классе 2 члена картинки - оригинальную (грузим 1 раз) и текущую, которую отображаем, напр в разных масштабах. Пока не наблюдаю даже 1 виртуального метода  Улыбающийся
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


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