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

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

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Наследование от QTableViewPrivate  (Прочитано 11767 раз)
Jo
Гость
« : Ноябрь 26, 2009, 20:09 »

Наследовался от QTableView и от QTableViewPrivate (над последним, долго думал наследовать или нет решил попробовать). Затем решил переопределить метод paintEvent в потомке от QTableView.

И запнулся на такой проблеме: при использовании метода приватного класса d->drawCell(...) в процессе компановки вылетает: "error LNK2019: ссылка на неразрешенный внешний символ ..." т.е. компановщик не видит реализации унаследованного метода drawCell в моем приватном классе.

Вот упрощенные коды классов.

Приватный класс наследник от QTableViewPrivate
Код:
class MTableViewPrivate: public QTableViewPrivate
{
Q_DECLARE_PUBLIC(MTableView)
public:
MTableViewPrivate() : QTableViewPrivate() {}
};

Наследник от QTableView
Код:
class MTableViewPrivate;
class MTableView : public QTableView
{
Q_OBJECT
public:
    MTableView(QWidget *parent = 0);  
    void paintEvent(QPaintEvent *event);

protected:
    MTableView(MTableViewPrivate &dd, QWidget *parent);

private:
    Q_DECLARE_PRIVATE(MTableView)
    Q_DISABLE_COPY(MTableView)
};

И собственно его реализация:
Код:
MTableView::MTableView(QWidget *parent)
    : QTableView(*new MTableViewPrivate, parent)
{}
MTableView::MTableView(MTableViewPrivate &dd, QWidget *parent)
    : QTableView(dd, parent)
{}
void MTableView::paintEvent(QPaintEvent *event)
{
    Q_D(MTableView);
    [b]d->drawCell(....);[/b]  
}


Открыл хидер QTableViewPrivate, если в этом хидере там где обявлен этот метод поставить { }; т.е. как бы добавляю пустую реализацию этого метода, то все в порядке. Так и не понял почему компановщик не видит его родную раелизацию?

« Последнее редактирование: Ноябрь 26, 2009, 20:16 от Jo » Записан
spectre71
Гость
« Ответ #1 : Ноябрь 26, 2009, 20:30 »

Поищи по по форуму!!!
За последние несколько дней уже раза 3 задавали подобный вопрос про приватные члены QT классов.
Записан
Jo
Гость
« Ответ #2 : Ноябрь 26, 2009, 20:41 »

Все что было я просмотрел. Там не обсуждалась тема наследования от приватного класса.
Да и потом проблема то в том что компановщик не видит реализации методов родительского класса, он видит, что они объявлены, а реализацию не находит вот и ругается. Вопрос только почему?
« Последнее редактирование: Ноябрь 26, 2009, 20:45 от Jo » Записан
Jo
Гость
« Ответ #3 : Ноябрь 26, 2009, 20:59 »

Если по проще объяснить то следующее не может скомпановаться:

Код:
#include "stdafx.h"
#include <QtGui/QApplication>
#include <qtableview.h>
#include <private/qtableview_p.h>

class MTableViewPrivate: public QTableViewPrivate
{
public:
MTableViewPrivate() : QTableViewPrivate() {}
};

int main(int argc, char *argv[])
{
QApplication a(argc, argv);

MTableViewPrivate tvp;
tvp.init();    //  Метод void init() объявлен в родительском классе QTableViewPrivate.

return a.exec();
}

В ответ на это получаю: error LNK2019: ссылка на неразрешенный внешний символ "public: void __thiscall QTableViewPrivate::init(void)"
« Последнее редактирование: Ноябрь 26, 2009, 21:05 от Jo » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #4 : Ноябрь 26, 2009, 21:11 »

Может это звучит наивно но все же:

Если линкуете статически - объяснить не могу. А если динамически - QTableViewPrivate не объявлен как экспортируемый класс, поэтому линкер его и не увидит (хотя Вы закрыли рот компилятору подключив _p.h файл)
Записан
Jo
Гость
« Ответ #5 : Ноябрь 26, 2009, 21:26 »

вся реализация QTableViewPrivate находится в qtableview.cpp
т.е. по идеи он должен видеть её.

Но почему то меня пугает такая запись тролей в qtableview_p.h:

Код:
//
//  W A R N I N G
//  -------------
//
// This file is not part of the Qt API.  It exists purely as an
// implementation detail.  This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//

Это может быть как то связано с проблемой?
Записан
spectre71
Гость
« Ответ #6 : Ноябрь 26, 2009, 21:39 »

Вот пара ссылок, может поможет.

http://habrahabr.ru/blogs/qt_software/76248/
http://qt.osdn.org.ua/data-sharing.html
Записан
Jo
Гость
« Ответ #7 : Ноябрь 26, 2009, 21:57 »

Спасибо за ссылки но с Pimpl проблем нет. Просто ща только понял что даже:

Код:
#include <QtGui/QApplication>
#include <../src/gui/itemviews/qtableview_p.h>

int main(int argc, char *argv[])
{
QApplication a(argc, argv);

QTableViewPrivate tp;
tp.init();    //  Метод void init() объявлен в классе QTableViewPrivate, а его реализация находится в qtableview.cpp

return a.exec();
}

так же дает ошибку линковки. Ед. что помогло вроде бы, это я выдрал всю реализацию методов QTableViewPrivate из исходника и подшил к проекту. Просто почему то линковщик не видит реализацию методов QTableViewPrivate. Может быть из за того что сказал Igors: "QTableViewPrivate не объявлен как экспортируемый класс" и может его реализации просто нет в Guid4.... ((

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

Сообщений: 11445


Просмотр профиля
« Ответ #8 : Ноябрь 26, 2009, 21:57 »

вся реализация QTableViewPrivate находится в qtableview.cpp
т.е. по идеи он должен видеть её.
Но ведь код qtableview.cpp сидит в dll а не в Вашем exe. Допустим Вы написали

Код:
tvp.init();  
Значит управление должно быть отдано на точку входа в dll. Значит класс/метод должен быть объявлен как экспортируемый (при построении dll) иначе вызывающий его не увидит. Напр. методы QTableView будут видимы потому что этот класс объявлен с Q_GUI_EXPORT. А для QTableViewPrivate - с какой стати?

Но почему то меня пугает такая запись тролей в qtableview_p.h:
...
Это может быть как то связано с проблемой?
Нет, просто прозрачно намекают: не связывайтесь с "_p" хедерами, они могут быть изменены в любое время
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #9 : Ноябрь 26, 2009, 22:00 »

Может быть из за того что сказал Igors: "QTableViewPrivate не объявлен как экспортируемый класс" и может его реализации просто нет в Guid4.... ((
Не путайте - реализация есть но она недоступна для внешнего использования
Записан
Jo
Гость
« Ответ #10 : Ноябрь 26, 2009, 22:23 »

Цитировать
Значит управление должно быть отдано на точку входа в dll. Значит класс/метод должен быть объявлен как экспортируемый (при построении dll) иначе вызывающий его не увидит. Напр. методы QTableView будут видимы потому что этот класс объявлен с Q_GUI_EXPORT. А для QTableViewPrivate - с какой стати?

Ясно огромное спасибо, стало многое понятно.
А как тогда быть, если мне нужно использовать класс QTableViewPrivate? Неужели только писать свою реализацию?
Записан
spectre71
Гость
« Ответ #11 : Ноябрь 26, 2009, 22:27 »

Ясно огромное спасибо, стало многое понятно.
А как тогда быть, если мне нужно использовать класс QTableViewPrivate? Неужели только писать свою реализацию?

Не использовать. Попробуй без него.
А вообще опиши задачу, может подскажем более простое решение.
Записан
Jo
Гость
« Ответ #12 : Ноябрь 26, 2009, 22:40 »

задач вообще несколько:
1. Необходимо из QTableView убрать горизонтальные линии сетки;
2. Реализовать обработчики мыши (что бы подсвечивать строки при наведении курсора, при клике тоже надо менять цвет строк)

Может еще что понадобится так вроде все пока.

Я просто посмотрел в исходнике где сетка рисуется (метод paintEvent в QTableView), ну и подумал если я его чуть почиркаю то получу то что мне надо. Хотел все родное оставить только чуть изменить, а никак, т.к. он пользует методы QTableViewPrivate.

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

Уже задавал подобный вопрос но ответа так и не получил.

Мне бы только путь подсказать, потому что пока кроме как через наследование не вижу....
Записан
spectre71
Гость
« Ответ #13 : Ноябрь 26, 2009, 23:48 »

задач вообще несколько:
1. Необходимо из QTableView убрать горизонтальные линии сетки;
2. Реализовать обработчики мыши (что бы подсвечивать строки при наведении курсора, при клике тоже надо менять цвет строк)

Может еще что понадобится так вроде все пока.

Я просто посмотрел в исходнике где сетка рисуется (метод paintEvent в QTableView), ну и подумал если я его чуть почиркаю то получу то что мне надо. Хотел все родное оставить только чуть изменить, а никак, т.к. он пользует методы QTableViewPrivate.

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

Уже задавал подобный вопрос но ответа так и не получил.

Мне бы только путь подсказать, потому что пока кроме как через наследование не вижу....

1) Насколько я понял ты в исходниках покопался, так что кратко.
Переопределяем у QTableView  paintEvent
Вызываем в своем сперва QTableView::paintEvent(event); таким образом делаем оригинальную отрисовку!
Далее прерисовываем сетку поверх, как это сделать:
- берем код QTableView  paintEvent
- комментируем все что не относится к отрисовке сетки
- Видим например verticalHeader определенный как
  const QHeaderView *verticalHeader = d->verticalHeader;
  Мы делаем
  const QHeaderView *verticalHeader = verticalHeader();
- И аналогично с остальной ерундой.
- Проверили работоспособность, удалили все закомментированное Улыбающийся 

2) Насколько я понял подсветить ячейку при наведении на нее мыши через делегат ты можешь. На вскидку способ подсветить строку:
- Делаем свою модель и делегат
- Кастим(приводим) в делегате модель к своей
- Определяем в делегате что нужно подсветить ячейку
- Вызываем у своей модели спец метод которому указываем номер строки для подсветки
- В этом методе модель выставит флаг для этой строки и сделает emit dataChanged этим ячейкам и ячейкам строки у котрых был флаг раньше
- В делегате проверяем флаг у ячейки и взависимости от флага делаем подсветку или нет
- Не забыть обработать выход мыши за пределы всех ячеек(убрать посветку)

Записан
Jo
Гость
« Ответ #14 : Ноябрь 27, 2009, 00:11 »

Цитировать
1) Вызываем в своем сперва QTableView::paintEvent(event);
так если я вызову родной метод он же мне прорисует всю сетку правильно? т.о. что бы мне оставить только вертикальные линии сетки перед этим придется закрашивать ту сетку которую нарисовал родитель. вообще можно и я рассматривал этот вариант но выглядит как то кривовато.

т.е. как я понимаю так:
    1 - нарисовать все родителем (в том числе и сетку)
    2 - закрасить сетку что нарисовал родитель.
    3 - нарисовать только вертикальные линии

я понял верно?

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

Огромное человеческое спасибо за первые 2 пути.

З.Ы. может наследование и переопределение обоих классов тоже не слишком красивых выход, зато получаю гибкость и полный контроль за моим классом.
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


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