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

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

Страниц: [1] 2 3   Вниз
  Печать  
Автор Тема: вывод данных ,QScrollArea  (Прочитано 19305 раз)
ikar2012
Гость
« : Апрель 24, 2013, 15:07 »

Добрый день!

С QT начал разбираться недавно, поэтому прошу отнестись с пониманием...

Задача следующая:
в дочернее окно (mdi) нужно вывести некие бинарные данные. Что-то наподобие того , как через F3 открыть в Far любой бинарный файл.
с самим mdi. дочерними окнами вроде разобрался.
пытаюсь вывести данные (QByteArray).
Т к данные естественно в рабочую область не помещаются, нужен скроллинг. В окно кидаю QScrollArea, в него кидаю виджет, который наследую от QWidget, переписываю paintEvent(). Данные вывожу через QPainter::drawText(); в принципе данные выводится.
но для того чтобы появился скролинг, насколько я понял, нужно установить размер вложенного виджета. Добавил функцию, в которую перед выводом подаю данные, считаю количество строк и определяю самую длинную строку (строку определяю по 0х0А), изменяю размер вложенного виджета, потом вывожу - при небольшом объеме данных вроде работает. Но при более менее существенном тормозит дико. При этом если вместо своего виджета подставить , например , QTextEdit - все работает нормально, в не зависимости от объема (в него подаю естественно Qstring,но QTextEdit мне не подходит).
Как внутри устроен QTextEdit, тоже понять не удалось. Там куча отсутствующих в доках макросов.
Как добиться желаемого результата? Как устроены в принципе всяческие редакторы и просмотровщики, работающие с символами (байтами).
Я вижу только одно решение пока - обрисовывать только видимую область. Но не понимаю как это сделать. Во-первых у виджета нет viewport(), во-вторых получается что при любой перерисовке нужно пересчитывать весь объем данных - я не знаю как там строки"разложаться". Считать один раз и держать некую разметку в памяти , мне кажется не правильным.

Подскажите, в правильном ли я направлении думаю, и , по возможности, хотя бы подтолкните в сторону примеров.
Записан
dio
Гость
« Ответ #1 : Апрель 24, 2013, 15:29 »

Смотрите в сторону Model/View
http://qt-project.org/doc/qt-4.8/model-view-programming.html
Записан
ikar2012
Гость
« Ответ #2 : Апрель 24, 2013, 15:44 »

не могли бы вы пояснить конкретней

как это может помочь?

у меня несколько типов дочерних окон. В некоторых используются таблицы, как раз через  Model/View. большие таблицы (большое количество столбцов) отрисовываются точно так же с огромными тормозами. я не понимаю что и как нужно (можно) изменить, за исключением использования модели вместо моей "предрасчетной" функции. Но она работает быстро, подозреваю что быстрее чем будет модель. Тормоза именно на "прорисовке"
Кроме того я не понимаю какой можно использовать View в моем случае
« Последнее редактирование: Апрель 24, 2013, 15:50 от ikar2012 » Записан
Командор
Гость
« Ответ #3 : Апрель 24, 2013, 16:18 »

Было бы неплохо привести кусок кода. Точнее то, что делается в paintEvent(). По-хорошему, там нужно нарисовать только те строки, которые раньше были вне области видимости, т.к. то, что было видно, QScrollArea автоматически перерисовывает/сдвигает, область перерисовки передается в функцию paintEvent(). У меня такое ощущение, что через QPainter::drawText() рисуется весь видимый текст, или, еще хуже, вообще весь текст. Вывод всего текста, конечно, "обнуляется", т.е. то, что выводится за пределы видимого реально не рисуется, но ресурсы жрет.
« Последнее редактирование: Апрель 24, 2013, 16:21 от Командор » Записан
ikar2012
Гость
« Ответ #4 : Апрель 24, 2013, 16:39 »

спасибо что откликнулись

да , отрисовывается именно весь текст. Я понимаю что так неправильно. Но как определять видимую область через widget (я нашел только как через QScrollArea, но не совсем понимаю как это связать), и чтот делать с данными - каждый раз предрасчитывать?
Код:
void ViewWidget::paintEvent(QPaintEvent* ev){
qDebug()<<"repaint";
QStyleOption opt;
opt.init(this);
QPainter p(this);
style()->drawPrimitive(QStyle::PE_Widget,&opt,&p,this);

if (data.size()>0){


QFontMetrics metrics(font());
QColor color;
int x =metrics.width(data.at(0));
int y =metrics.height();
int sm =0;
int n_str=1;
p.setPen(QColor(Qt::black));


for (int i = 0; i < data.size(); ++i) {



if ( data.at(i)==10) {n_str++;x=0;}
else {
p.drawText(x, y*n_str, QString( data.at(i)));

sm=metrics.width(data.at(i));
if (sm==0) sm =metrics.width(" ");
x += sm;
}
    }



}
}


« Последнее редактирование: Апрель 24, 2013, 16:42 от ikar2012 » Записан
Командор
Гость
« Ответ #5 : Апрель 24, 2013, 17:03 »

Нужно анализировать параметр QPaintEvent *ev, а точнее ev->region->boundingRect() - это часть виджета, который нужно перерисовать. Соответственно, раз у нас есть метрика шрифта или задана высота строки, то можно вычислить диапазон строк, которые нужно нарисовать.
Записан
dio
Гость
« Ответ #6 : Апрель 24, 2013, 17:05 »

не могли бы вы пояснить конкретней

как это может помочь?
Во-первых будет правильная отрисовка, только видимой области;
Во-вторых возможно реализовать частичную подгрузку данных;
Цитировать
To create models that populate incrementally, you can reimplement fetchMore() and canFetchMore().

Цитировать
Кроме того я не понимаю какой можно использовать View в моем случае

Например, QTableView. С помощью делегатов можно реализовать вид, любой сложности.
Записан
ikar2012
Гость
« Ответ #7 : Апрель 24, 2013, 19:41 »

Нужно анализировать параметр QPaintEvent *ev, а точнее ev->region->boundingRect() - это часть виджета, который нужно перерисовать. Соответственно, раз у нас есть метрика шрифта или задана высота строки, то можно вычислить диапазон строк, которые нужно нарисовать.
спасибо, завтра попробую ( сегодня уже никак)
Записан
Bepec
Гость
« Ответ #8 : Апрель 24, 2013, 19:45 »

Хорошо когда человек делает свой собственный велосипед.

Повторю совет dio - почитайте про model-View.

PS объем работы по написанию собственной model-View у вас будет колоссальный Показает язык
Записан
ikar2012
Гость
« Ответ #9 : Апрель 24, 2013, 19:58 »

не могли бы вы пояснить конкретней

как это может помочь?
Во-первых будет правильная отрисовка, только видимой области;
Во-вторых возможно реализовать частичную подгрузку данных;
Цитировать
To create models that populate incrementally, you can reimplement fetchMore() and canFetchMore().

Цитировать
Кроме того я не понимаю какой можно использовать View в моем случае

Например, QTableView. С помощью делегатов можно реализовать вид, любой сложности.

Пока при выводе в таблицу это еще медленней получается, т к накладные расходы на класс модели, на более сложный класс qtableview. И как сделать чтобы была отрисовка была "правильной" я не нашел. Если вручную все отслеживать - то мой подход ничем отличаться не будет с точки зрения удобства и трудоемкости кода, но будет требовать существенно менее ресурсов, т к более простые классы

Вы не могли бы привести пример. Возможно я чего-то не понимаю - каким образом будет правильная отрисовка реализована?
И каким образом к моей задаче можно прикрутить динамическую подгрузку?
Не могли бы вы хотя бы на уровне каркаса пример привести. Только с учетом моей задачи ( бинарные данные - отображаю в виде строк, конец строки это 0x0a. С учетом того что данные бинарные, ни количество строк, ни их длина заранее не известны. Естественно строки могут быть абсолютно разными по размеру.
Или хотя бы описать как в моем случае организовывать подгрузку ( ведь может оказаться что у меня две строки - одна 100000 символов, другая 5, узнаю я это только после предварительного анализа данных, когда пройдусь поиском на 0x0а).
Записан
ikar2012
Гость
« Ответ #10 : Апрель 24, 2013, 20:03 »

Хорошо когда человек делает свой собственный велосипед.

Повторю совет dio - почитайте про model-View.

PS объем работы по написанию собственной model-View у вас будет колоссальный Показает язык
так я и не хочу изобретать собственный,  я прошу конкретного совета. Про модель читал, я даже использую этот подход и довольно активно. Модели пишу сам, наследуясь от QAbstractTableModel. Но либо я что-то не понимаю, либо это не работает. Оно тормозит точно также - отрисовывая всю таблицу. Если не понимаю- то именно это я и прошу объяснить. Ни в одном примере model /view не выводится большие объемы, тем более неоднородных по длине данных , и не контролируется область вывода . Мне нужен просто аналог qtextedit, , но с возможностью не спотыкаться о 0x00, и с возможностью отсвечивать по своему каждый символ ( как реализовать через модель я знаю, но не вижу просто пока преимуществ - у меня основная проблема - время отрисовки). И какой все-таки view использовать, выводе через qtableview это будет не совсем похоже на то, что нужно, т к все символы будут друг под другом в независимости от своих размеров- а нужно чтобы выводилось в виде, как выводится текст - т е когда положение символа зависит от его физических размеров
« Последнее редактирование: Апрель 24, 2013, 20:13 от ikar2012 » Записан
Bepec
Гость
« Ответ #11 : Апрель 24, 2013, 20:22 »

М... Нарисуйте чего вы хотите, тогда я дам вам ответ.

На 4 миллионах строк данных, модель-Вью работает бодренько - незаметно для человека.

НО! некоторые её методы реализованы так, что отсекают всю полезность модели. Тот же ресайз то контент и прочая Улыбающийся

PS вы мне код не даёте посмотреть и просите сказать что не так - вам это не кажется странной надеждой на телепатию собеседника? Показает язык
Записан
ikar2012
Гость
« Ответ #12 : Апрель 24, 2013, 20:28 »

М... Нарисуйте чего вы хотите, тогда я дам вам ответ.

На 4 миллионах строк данных, модель-Вью работает бодренько - незаметно для человека.

НО! некоторые её методы реализованы так, что отсекают всю полезность модели. Тот же ресайз то контент и прочая Улыбающийся

PS вы мне код не даёте посмотреть и просите сказать что не так - вам это не кажется странной надеждой на телепатию собеседника? Показает язык

Код смогу только завтра. Какой кусок нужен? Как на текущий момент пытаюсь рисовать приведено выше. Задачу просто можно описать так - берем любой файл ( бинарный в общем случае) открываем и видим его содержимое в окошечке, с возможностью прокрутки. Точно так же как , например , открыв его в Far через F3

Собственно вопрос - в подходе с моделью во что отображать и как контролировать отрисовку (определять viewport или что-то аналогичное) и что лучше ( и правильней) каждый раз при перерисовке заново делать пред расчет строк ( это вроде довольно быстро, пока по крайней мере) или лучше расчитывать и хранить шаблон. Что будет в одном случае и в другом понятно, но как обычно делают. Как например сделано в том же qtextedit?
« Последнее редактирование: Апрель 24, 2013, 20:37 от ikar2012 » Записан
Bepec
Гость
« Ответ #13 : Апрель 24, 2013, 20:45 »

Кхм. Я вас немного не понимаю чего именно вы хотите. Какой идеальный вариант?

update: Мммм. Вы хотите кататься по файлу? Показает язык Да, готовые модели Qt такой возможности не предоставляют, но... Но если поставить Скроллбар, связать его с textEdit и seek'ом ехать по файлу, такое вполне возможно, я думаю.
« Последнее редактирование: Апрель 24, 2013, 20:48 от Bepec » Записан
ikar2012
Гость
« Ответ #14 : Апрель 24, 2013, 21:01 »

Кхм. Я вас немного не понимаю чего именно вы хотите. Какой идеальный вариант?

update: Мммм. Вы хотите кататься по файлу? Показает язык Да, готовые модели Qt такой возможности не предоставляют, но... Но если поставить Скроллбар, связать его с textEdit и seek'ом ехать по файлу, такое вполне возможно, я думаю.
Да, Вы в принципе правильно поняли. Я хочу "кататься по файлу" но TextEdit не подходит, т к он не может с бинарными данными ( проще говоря он "спотыкается" о 0x00, считая это концом, т к работает со стрингами) можно на лету конечно нули вырезать/заменять, но для данной задачи это не очень походит, можно пихать через stream, но тогда нули  теряются. Скролбар проблему не решит, потому как при отображали бинарный файл может быть не только большой по вертикали, но и по горизонтали QScrollArea как раз здесь очень к месту ( если я правильно понял практически все стандартные view используют qabstractscrollarea).
Я в принципе представляю что надо делать - вопрос только как получить реальные текущие размеры отображаемой области. Для моей реализации выше ответ вроде дали ( завтра проверю). Если вы знаете как это сделать через предложению схему с моделью - мне это тоже интересно, т к возможно в будущем облегчит дальнейшее наращивание функционала. - но  не смог подобрать подходящи view , и пока понимаю где и как получать размер viewport

Upd. Упустил. Seek не подходит в принципе , тк мне нужно отображать файл не каким-то частями ( я поэтому и писал выше, как можно воспользоваться порционным получением), а некими логическими строчками, которые заранее не известны ( последовательность заканчивающаяся 0x0a). Такую задачу обычно решает чтение текстового файла построчно, но здесь мешает такому подходу наличие не отображаемых символов ( например 0x00) , а так же непредсказуемо большая длина строки в некоторых случаях. (Если в файле 1 Мб не встретиться 0x0a- то он весь будет одной строкой)
« Последнее редактирование: Апрель 24, 2013, 21:49 от ikar2012 » Записан
Страниц: [1] 2 3   Вверх
  Печать  
 
Перейти в:  


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