Russian Qt Forum

Qt => Вопросы новичков => Тема начата: skytrain от Март 11, 2013, 00:44



Название: Наследование классов и обьектов
Отправлено: skytrain от Март 11, 2013, 00:44
Добрый день.
Среда Qt Creator (Qt 4.8) ОС 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 нет реализации.
Константы компиляции определены по одной на каждый заголовочный файл.
Все это затевается для того, что-бы было можно создавать виртуальные функции с последующим выводом их в абстрактный класс.
Можно ли исправить ситуацию или переформулировать задачу.

С уважением.


Название: Re: Наследование классов и обьектов
Отправлено: kambala от Март 11, 2013, 02:13
вынеси общую функциональность в отдельный класс и используй множественное наследование


Название: Re: Наследование классов и обьектов
Отправлено: skytrain от Март 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 файла.

По остальному в голове бардак.
Я постараюсь его выразить позже.
Извините. Сейчас надо спать идти.
Спасибо.


Название: Re: Наследование классов и обьектов
Отправлено: Igors от Март 11, 2013, 09:10
Widget объявлен в namespace Ui, значит в начале PreviewFrame.h надо написать
Код
C++ (Qt)
using Ui::Widget;
 

[/offtop]
Имя "Widget" говорит о скудной фантазии  :)


Название: Re: Наследование классов и обьектов
Отправлено: skytrain от Март 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. Но будет ли правильно так поступать?




Название: Re: Наследование классов и обьектов
Отправлено: skytrain от Март 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. Наверное для него это слишком.

Заранее спасибо.


Название: Re: Наследование классов и обьектов
Отправлено: Bepec от Март 12, 2013, 07:00
Можно вопрос? А что вы хотите получить от QWidget и от QFrame?

Мб вам это наследование и не нужно?


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

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

Да, и желательно более четкий пример классов - с тем что Вы показали трудно что-то советовать


Название: Re: Наследование классов и обьектов
Отправлено: skytrain от Март 12, 2013, 23:37
Можно вопрос? А что вы хотите получить от QWidget и от QFrame?

Мб вам это наследование и не нужно?
Да вы правы. Не нужно и не правильно. Тот код уже переписан.
PreviewFrame теперь наследует абстрактный класс и QFrame. А в конструктор передается указатель на обьект формы, на котором будет отрисовка. (Слава богу с этим разобрался)


Название: Re: Наследование классов и обьектов
Отправлено: skytrain от Март 12, 2013, 23:49
Если Вам нужен объект созданный в дизайнере - лучше достать его по имени. Если он должен иметь тип что Вы хотите - подсуньте дизайнеру свой хедер, так можно. Вообще если опыта маловато - дизайнер лучше отложить.
Я думаю что дизайнер лучше сразу "победить". Потом хлопот будет много... Мне так кажется. Благо время есть.
 
Спасибо.


Название: Re: Наследование классов и обьектов
Отправлено: skytrain от Март 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. Наверное для него это слишком.

Заранее спасибо.


Название: Re: Наследование классов и обьектов
Отправлено: kambala от Март 13, 2013, 01:30
предлагаю словами обрисовать задачу, которая перед тобой стоит, ибо из кода она неясна. после этого станет ясно правильный избран ли подход в принципе.

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

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


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

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

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

P.S. Plase — какое-то странное слово.
Ошибся. В идеале было Place.


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

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


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

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


Название: Re: Наследование классов и обьектов
Отправлено: kambala от Март 13, 2013, 14:11
Пока надо до конца понять что такое Абстрактный класс и с чем его едят.
Сейчас ситуация такова:
Цель - сформировать каркас проекта. Определить общие для всех типов загружаемых данных функции.
Звучит довольно расплывчато. Пока я не увидел что Вы хотите обобщить и для чего нужен абстрактный класс.
+1 стена текста, а непонятно ничего


Название: Re: Наследование классов и обьектов
Отправлено: skytrain от Март 13, 2013, 23:17
Ух...
Стена текста - это не цель.!!!!
Не пойму как организовать классы и вызов нужных функций.
Хочу виджет. На нем Форма(или что-либо квадратное на чем можно рисовать). На форме картинка Внизу кнопки и.т.п
Хочу обработку картинок в программе.
Хочу вынести общую функциональность (загрузку и.т.п) в абстрактный класс.

Виртуальный метод iLoad (Виртуальность наследуется из абстрактного класса).
Код:
хочу сделать обработку кадров. На форме будет показываться кадр и слева будет выбор эффектов. 
А так я до сих пор не понимаю, нафига тебе QFrame... Всё что ты описал в вышестоящем сообщении - это переопределение paintEvent у виджета и... всё?! помоему всё.
Вы абсолютно правы:) Все именно так.

Код в тарболе.
http://rusfolder.com/35456815
Сейчас при компиляции та-же ошибка, что и была в начале темы. Не наследуется класс....
Не судите сильно строго. Нарваться на одну и ту-же ошибку три раза - это перебор.
Спасибо.


Название: Re: Наследование классов и обьектов
Отправлено: skytrain от Март 14, 2013, 03:50
Доброй ночи.
Почему не компилировалось - разобрался. (не нужно включать заголовки там, где достаточно прототипов классов)
Как через указатель на абстрактный класс получить доступ к public ф-ям QFrame - разобрался.
В иерархии объектов и классов разобрался. Все как надо.

В принципе по теме вопросов не имею.
Всем спасибо.

Если кому интересно, то исходники приведу в порядок и скину завтра днем.
И если будут какие замечания\рекомендации - буду  признателен.


Название: Re: Наследование классов и обьектов
Отправлено: Bepec от Март 14, 2013, 06:56
Я б вообще не вникал в ваши абстрактные классы с методами :) Простое наследование от QWidget для вывода, класс обрабатывающий картинки - от QObject'a, класс менеджер (при необходимости) тоже от QObject'a.

И тогда получается у вас картинка будет получена, помещена на QWidget. Кнопочки испускают сигналки в класс-обработчик, QWidget перерисовывается с новыми эффектами.

PS хотя мб я и неправ, кто знает ваши мысли :D


Название: Re: Наследование классов и обьектов
Отправлено: Igors от Март 14, 2013, 09:13
Хочу вынести общую функциональность (загрузку и.т.п) в абстрактный класс.
Виртуальный метод iLoad
Впечатление что чем больше абстрактных классов, виртуальных методов и.т.п. - тем лучше :) По-моему все  наоборот. Конечно если цель потренироваться с этим - на здоровье, но чего это Load (загрузка картинки с диска) виртуальный? Чем отличается этот ф-ционал для разных потомков? Как правило, порождение новых классов должно быть вынужденно, иначе Вы просто "плодите сущности" которые оказываются пустыми/дутыми и никакой смысловой нагрузки не несут.

Об этом можно почитать здесь http://www.insidecpp.ru/antipatterns/interface_bloat/ (http://www.insidecpp.ru/antipatterns/interface_bloat/)


Название: Re: Наследование классов и обьектов
Отправлено: skytrain от Март 15, 2013, 05:44
В общем абстрактный класс был задуман как тренировка + задел на будущее.
Метод загрузки может сильно отличаться входным форматированием. Мы же не пишем программы для одного разрешения, расширения или устройства... например.
Виртуальным методом может быть установка какого либо фильтра.
Я б вообще не вникал в ваши абстрактные классы с методами :) Простое наследование от QWidget для вывода, класс обрабатывающий картинки - от QObject'a, класс менеджер (при необходимости) тоже от QObject'a.
Если честно, то класс менеджер - это пока понятие очень туманное.... для меня.
QFrame и так от QObject'a.
Форму и другие объекты типа кнопок можно увидеть в дизайнере.... скомпоновать например.

И тогда получается у вас картинка будет получена, помещена на QWidget.
PS хотя мб я и не прав, кто знает ваши мысли :D
Но в таком случае я-б думал в направлении создания второго виджета 1-го уровня.
А пока думаю как заставить форму изменять размер вместе с главным окном.
Ну и..
Код:
img.scaled(sizePreview,Qt::KeepAspectRatio,Qt::FastTransformation);
Может что-то упускаю, но мне сдается что у нее нет реализации в самой Qt.
В нее я не могу зайти в отладчике.:) От ее применения картинке ни холодно ни жарко.

Оффтоп но. Почему ui->frame->sizeHint() может возвращать QSize(0, 0) если фрейм внутри компоновщика?


Название: Re: Наследование классов и обьектов
Отправлено: carrygun от Март 15, 2013, 13:44
Фрейм пустой и его "сжало" компановщиком в точку.


Название: Re: Наследование классов и обьектов
Отправлено: Bepec от Март 15, 2013, 13:51
А ещё нужно учесть и функцию в которой sizeHint вызываешь. В конструкторе такая комбинация не прокатит :D