LINUX.ORG.RU

[qt][императивщина][НЕНАВИСТЬ] долбаный репарентинг

 ,


0

1
object Test extends Application {
	QApplication.initialize( Array() )
	val area = new QScrollArea
	// работает
	val w = new QWidget
	w.setLayout( new QVBoxLayout {
		addWidget( new QLabel( "1" ) )
		addWidget( new QLabel( "2" ) )
	} )
	
	//не работает!
	val w = new QWidget
	area.setWidget( w )
	w.setLayout( new QVBoxLayout {
		addWidget( new QLabel( "1" ) )
		addWidget( new QLabel( "2" ) )
	} )
	
        //не работает!!!
	val w = new QWidget
	val layout = new QVBoxLayout
	w.setLayout( layout )
	area.setWidget( w )
	layout.addWidget( new QLabel( "1" ) )
	layout.addWidget( new QLabel( "2" ) )

        //казлыуродыненавижу

	area.resize( new QSize( 500, 500 ) )
	area.show
	QApplication.exec
}

как выяснилось проблемы в скрытом репарентинге который осуществляет setWidget. Компилится. Запускается. Не падает. Не ругается. НЕ РАБОТАЕТ. Писал сходу сложный компонент - час долбался пока раставил эти репарентовые вызовы как надо. Казлыуродыненавижу. Вот вам императивщина в полный рост.

Копаюсь походу в трольском коде - фикшу багу для джамби - чуть не поседел от ужоса. В чтениях потока создание буферов в каждом проходе цикла. Попытка буферизировать то что и без них буферизировано в каждой обертке - изза этого перерасход памяти и ненужные тормоза на ио блокировках «чтобы догнать буфер». Неправильное пользование метода available - изза этого неправильный детект конца потока - работает на честом слове потому что поток файловый. Какието подвешенные буферизированные ридеры которые нигде не используются но создаются - а чтение осуществляется из параллельного стрима - работает только потому что ни один использованый буфер не читает апфронт. В корне неверная работа с класлоадерами в ресурсах - изза этого почти нихрена не работает кроме примитивного случая с джарником.

Мои кеды держатся на честном слове!!!

Ужос!

★★★★★

setWidget:

Note that You must add the layout of widget before you call this function; if you add it later, the widget will not be visible - regardless of when you show() the scroll area. In this case, you can also not show() the widget later.

zJes ★★
()

Вообще-то вполне логично, что не работает. Если окно уже создано и помещено на родитель, то (неважно, оно видимо или нет) новые дочерние окна добавляются на него скрытыми и им явно нужно вызвать show(). Сделано это чтобы изменение окна на лету (добавление, удаление, репарентинг) не мелькало перед глазами, показывая окна, которые на следующей итерации будут спрятаны и дёргая 100500 раз пересчёт лейоута после каждого чиха. Догадаться какое окно должно быть скрыто, а какое видимо без явного указания невозможно. Этот use-case подробно описан в документации.

Дополнительный буфер в QIODevice создаётся для ungetch(), да, сомнительный оверхед, возможно он там оставлен для совместимости.

По поводу остального - больше конкретики. Возможно на плюсах эти проблемы давно исправлены.

Dendy ★★★★★
()
Ответ на: комментарий от zJes

>Note that

That's exactly my point.

r ★★★★★
() автор топика
Ответ на: комментарий от tailgunner

>Более интересный вопрос - нафига в Scala нужен Qt?

Цитирую занудного техаского менеджера «для более системного вида».

r ★★★★★
() автор топика
Ответ на: комментарий от Dendy

>которые на следующей итерации будут спрятаны и дёргая 100500 раз пересчёт лейоута после каждого чиха.

Ман свинг. Кутешные девелоперы его манят конечно - но пока недостаточно.

Вообще-то вполне логично, что не работает.


работает:
x.добавить_чайлдов()
x.поместить_в_парент(парент)

не работает:
x.поместить_в_парент(парент)
x.добавить_чайлдов()

Логично? Где? Вся логичность там это то что в никак не связанной операции помещения видгета в парента происходит репарентинг компонентов. Если порядок настолько важен - надо было апи соответственно причесать - чтобы невозможно было совать в лейаут компоненты с неопределенным парентом. А в рантайме посылать нахрен, или хотябы генерить варнинг - что вы напихали чайлдов у которого при отрисовке чужой парент.

А ситуация когда «Компилится. Запускается. Не падает. Не ругается. НЕ РАБОТАЕТ» в настолько связных вызовах - это маразм. Или с другой стороны лучше сказать - это С++:)?

r ★★★★★
() автор топика
Ответ на: комментарий от r

> Логично? Где?

В том, что прикрепление виджета к родителю значит блокирование его содержимого, добавляемого после, от автоматического показа.

Или с другой стороны лучше сказать - это С++:)?


Отнюдь. Постараюсь объяснить. Здесь идёт размен одной автоматизации операций на другую. Как вы наверное успели заметить - в Qt отсутствуют операции ручного пересчёта лейоутов, просто кидайте на них виджеты в любом порядке и они гарантированно пересчитаются при первом показе. Так вот, схема «добавить виджеты, а потом спрятать лишние» приведёт к оверхеду на пересчёт лейоута и обновление экрана, отследить который изнутри невозможно, в то время как схема «добавить виджеты, а потом показать нужные» такого недостатка лишена.

Другими словами, иерархия построения окон идёт снизу вверх, как матрёшка, маленькое окошко ложится в большее, а оно, в свою очередь, в ещё большее. Попытка воткнуть дочернее окно в уже сконструированное (которое лежит на родителе) - отдельный use-case, выбивающийся из общего правила, ведь родитель в этот момент понятия не имеет, что вы с окном собираетесь делать дальше. Может менять ему координаты или sizePolicy, что приведёт к ненужным обновлениям и пересчёту лейоута.

Dendy ★★★★★
()

Мои кеды держатся на честном слове!!!

Не паникуй, настоящие мужики сидят на кедах и не боятся падений и глюков

vertexua ★★★★★
()
Ответ на: комментарий от Dendy

> В том, что прикрепление виджета к родителю значит блокирование его содержимого, добавляемого после, от автоматического показа.

А что - давно это лучшая стратегия?

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


Как бы - нет. Еще ничего не показывалось - а все что вкинуто после setWidget - проигнорировано на первом показе.

ведь родитель в этот момент понятия не имеет, что вы с окном собираетесь делать дальше.


И поэтому в свинге сделан метод revalidate который говорит лейауту - а пересчитайся ка ты братан как будет возможность - контент поменялся. И потому добавлять можно что угодно и как угодно.

А в остальном - таки да С++. В условиях кютешной модели с подобными ограничениями прекрасно ложится метод вида

def update(f: QWidget => Unit) = {
f(this) // parent
layout.invalidate
}

но зачем нам эти пацоватые лямбды. Эхххх.

r ★★★★★
() автор топика
Ответ на: комментарий от r

> И поэтому в свинге сделан метод revalidate который говорит лейауту - а пересчитайся ка ты братан как будет возможность - контент поменялся.

Ну вот, только что негодовали на императивный подход, а сейчас хотите следить за каждым изменением окна и вызывать руками revalidate. Такой подход чреват скрытыми ошибками. В то время как последовательность операций вложенности окон имеет стабильный use-case: добавили окна в пределах конструирования родителя - они будут показаны, за пределами в рантайме - будут скрыты.

Dendy ★★★★★
()
Ответ на: комментарий от Dendy

>Ну вот, только что негодовали на императивный подход, а сейчас хотите следить за каждым изменением окна и вызывать руками revalidate

Это ж в режиме «раз уж такая пьянка». Поскольку без лямд это изолировать трудно - ладно бы сделали режим когда можно это контролировать.

В то время как последовательность операций вложенности окон имеет стабильный use-case: добавили окна в пределах конструирования родителя - они будут показаны


Код то посмотри:)

r ★★★★★
() автор топика
Ответ на: комментарий от r

> Код то посмотри:)

Посмотрел. Конструирование окна завершается добавлением его на родитель. А теперь на свой код посмотрите вы (-:

Dendy ★★★★★
()
Ответ на: комментарий от nu11

Да уж.


If the QGridLayout is not the top-level layout (i.e. does not manage all of the widget's area and children), you must add it to its parent layout when you create it, but before you do anything with it. The normal way to add a layout is by calling addLayout() on the parent layout.

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

Скрестить пальцы и надейтся что работает.

Как растянуть ВБоск по горизонтали на всю видимую областе скролареи? Никак?

r ★★★★★
() автор топика
Ответ на: комментарий от r

>Скрестить пальцы и надейтся что работает.
если не читать маны, то видимо только так и придется делать. Еще, говорят, бубен помогает.

Как растянуть ВБоск по горизонтали на всю видимую областе скролареи? Никак?

задать для скроллареи какой-нибудь лейаут, не? http://dl.dropbox.com/u/998228/LOR/qt-scroll-layout.png

nu11 ★★★★★
()
Ответ на: комментарий от nu11

>если не читать маны, то видимо только так и придется делать.

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

задать для скроллареи какой-нибудь лейаут, не?


VBox и есть лайаут. Но он лайаутит по вертикали. Обертка его HBox или Grid - не помогает,. Стретчинг внутренних компонентов не помогает.

r ★★★★★
() автор топика

Ээээ... wtf is репарентинг?

ЗЫ: Хотел сам покопаться в Jambi на Скале. Теперь не буду.

Macil ★★★★★
()
Ответ на: комментарий от Macil

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

r ★★★★★
() автор топика
Ответ на: комментарий от r

>Статическую типизацию придумали для того чтобы не вычитывать на каждый чих как решаются те или иные пролблемы
а при чем тут типизация и механизмы работы фреймворка?

Обертка его HBox или Grid - не помогает

неправильно значит оборачивает. Я ж скрин показал, все работает

nu11 ★★★★★
()
Ответ на: комментарий от r

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

nu11 ★★★★★
()
Ответ на: комментарий от nu11

>а при чем тут типизация и механизмы работы фреймворка?


Статическая типизация это механизм как меньше читать манов - когда неправильно просто трудно написать. А"читайте маны где разраб вместо того чтобы написать грамотно сам прредложил читать их милолионам людей" - єто не віход.
Никаких принципиальных причин делать это именно так нет.


Я ж скрин показал, все работает


Положи туда не календарь а лабел. Календарь может сам по себе расползающийся компонент.

r ★★★★★
() автор топика
Ответ на: комментарий от r

>Календарь может сам по себе расползающийся компонент.
нет. Там в общем и кнопка обычная есть, тоже растягивается в ширину, как и задумано

Статическая типизация это механизм как меньше читать манов

:)

Никаких принципиальных причин делать это именно так нет.

это ты так думаешь. Спроси трольтехов, почему так. Или камменты в коде поищи.

nu11 ★★★★★
()

>В чтениях потока создание буферов в каждом проходе цикла.

вот кстати кинь путь файла в сырцах, интересно посмотреть.

nu11 ★★★★★
()
Ответ на: комментарий от nu11

>Я ж скрин показал, все работает

А - так ты на скрине подогнал размер лейаута руками по арею - так и я могу. У тебя расползлись календари внутри лейаута - а надо чтобы сам лейаут расползался. Арея лежит в ресайзабле окне. Размер вьевпорта меняется. Надо чтобы контент всегда расползался на весь вьевпор по горизонтали.

r ★★★★★
() автор топика
Ответ на: комментарий от nu11

/qt-jambi-qtjambi-4_7/java/src/qtjambi/com/trolltech/qt/internal/QClassPathFileEngineHandler.java

например copy

в read в каждом вызове метода.

я люто надеюсь что на плюсах троли пишут лучше чем на жабе.

r ★★★★★
() автор топика
Ответ на: комментарий от r

эта пара copy/read вообще жестяной перл программерской мысли. Если я правильно посчитал там копирование одних и тех же данніх между дв буферами - не меньше трех раз.

Там прямо с первой строки шок - сначала выделим мегабайт памяти - а потом посмотрим а можем ли мы вообще что-то делать. Ага - да - а то у gc работы мало в последнее время.

r ★★★★★
() автор топика

Кстати, а почему именно Qt, а не SWT? Если нужно, чтобы было «системненько», то вроде самое оно?

Macil ★★★★★
()
Ответ на: комментарий от r

>А - так ты на скрине подогнал размер лейаута руками по арею - так и я могу.
не, я не делфикодер чтобы руками лейауты выстраивать. Все автоматически.

nu11 ★★★★★
()
Ответ на: комментарий от r

>я люто надеюсь что на плюсах троли пишут лучше чем на жабе.
а, так там жаба. Ну это значит они тонко намекают, что жаба в любом случае будет тормозить и течь :)

nu11 ★★★★★
()
Ответ на: комментарий от Macil

>Если нужно, чтобы было «системненько»,

SWT ннативненько - но не системненько. Под маки еле выродили аквовскую версию - а вообще оно ним разу не похоже.

r ★★★★★
() автор топика
Ответ на: комментарий от nu11

>не, я не делфикодер чтобы руками лейауты выстраивать. Все автоматически.



У тебя красная рамка лейаута растянута на всю арею а календжарь в ней. То что он так растягивается понятно. Как сам лейаут натянуть.

http://img836.imageshack.us/img836/109/48437285.png

r ★★★★★
() автор топика
Ответ на: комментарий от r
   area.setLayout( new QHBoxLayout { 
      addLayout(
         new QVBoxLayout {
            addWidget( new QLabel( "1" ) ) 
            addWidget( new QLabel( "2" ) ) 
         }
      )
   } )

Как-то так наверное это в коде будет. Я руками давно не создавал виджетов в рантайме, все больше дизигнером пользуюсь.

nu11 ★★★★★
()
Ответ на: комментарий от r

А хороший, годный веб-интерфейс это тоже не «системненько»?

Просто джамби брошен на произвол судьбы нокией... И как-то делать ставку на такой продукт...

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

По-моему, вообще гуй должен быть в какой-то отдельной сущности со своим эвент-лупом (а то и в отдельном процессе), с которым общаться с помощью какого-то IPC. Потому что все равно приходится выстраивать MVC. Но даже в этом случае получается (у меня по крайней мере) какое-то аццкое спагетти.

Ну его в болото. Пусть «модельный» код выплевывает JSON, а дальше пусть с ним на стороне клиента еб^W работают.

Macil ★★★★★
()
Ответ на: комментарий от nu11

>Как-то так наверное это в коде будет.

пробовал - не работает:) Дело в том что арея все делает поминимому - и потому любые попытки растянуть это стречами и политиками не дают эффекта (разве что опять таки гдето чтото надо было после чегото иначе нини). То есть никто не запрашивает размер по видимому паренту.

r ★★★★★
() автор топика
Ответ на: комментарий от Macil

>А хороший, годный веб-интерфейс это тоже не «системненько»?

Программа для локалхостов.

Просто джамби брошен на произвол судьбы нокией...


Пилят его - проект не умер. Просто писать на qt/плюсах вообще никакого желания.

r ★★★★★
() автор топика
Ответ на: комментарий от r

Посоветовать питон? :) И системненько и по сути чистый Qt.
А по поводу треда, ты пытаешься доказать что твое интуитивное более верное, чем то что сделали тролтехи?

zJes ★★
()
Ответ на: комментарий от zJes

>Посоветовать питон? :)

не. Суть в том что движек который инкарнируется и в серверах и в кластерах ив апплаянсах и должен инкорнироваться в десктопе на жабоскале. Морда там не особенно сложная - просто эстетов развелось.

r ★★★★★
() автор топика
Ответ на: комментарий от zJes

>А по поводу треда, ты пытаешься доказать что твое интуитивное более верное, чем то что сделали тролтехи?

Ну во первых оно не совсем интуитивное - в том же свинге настолько страных ограничений нет.

Во вторых наличествует ощущение исходящее из опыта что так сделано не по неким обективным причинам - а потому что так уж повелось в этом лесу. Видно что qt доводят до взрослых концепций (некоторые вещи и вообще отлично) понемногу и вычищают - хотябы из чтения доков - на 4.7 и методов многих таких нет как в примерах в доке.

Просто бесит ощущение что это сделано методом «как только заработало - работа закончена». А то что мусор за собой убрать надо и привести в логичное состояние фремворк - как будто и не парился никто. А теперь сами и мучаются в чистках.

r ★★★★★
() автор топика
Ответ на: комментарий от r

Я даже не пытаюсь оправдать... в Qt нелогичностей и «так повелось», мама не горюй. :) Но в данном случае, смотря на твой пример, просто вижу, что ты просто не посмотрел в доку.

zJes ★★
()
Ответ на: комментарий от r

>Программа для локалхостов.

А разве это препятствие для? Вон в платежных аффтоматах вполне себе локалхост.

Macil ★★★★★
()
Ответ на: комментарий от Macil

>А разве это препятствие для?

Скайпообразный формат.

r ★★★★★
() автор топика
Ответ на: комментарий от zJes

ну вообщето смотрел , я сначала в арею леяаутсунул - наблюдал спецэффект - понял что не так - полез в ман - просто не читал от корки до корки. какого фига єто ж не рокет саянс - контрол в скроарею положить. А потому такие нюансы - удручают.

r ★★★★★
() автор топика

Я тут начал скалу изучать и от нефиг делать забрёл на ЛОР и увидел эту тему.

В общем, хотел спросить есть ли где мануал по использованию Qt в Scala?

Или хотябы примеры работающего кода.

SV0L0CH
()
Ответ на: комментарий от r

>пробовал - не работает:)

у меня работает вот так:
[code]
QScrollArea *area = new QScrollArea( this );
QHBoxLayout *layout1 = new QHBoxLayout;
QVBoxLayout *layout2 = new QVBoxLayout;
layout2->addWidget( new QLabel(«bla bla bla») );
layout2->addWidget( new QPushButton( «ololo») );
layout2->addWidget( new QCalendarWidget );
layout2->addWidget( new QCalendarWidget );
layout1->addLayout( layout2 );
area->resize( QSize(400, 200) );
area->setLayout( layout1 );
area->show();
[/code]
Правда надо size hints корректные чтоб скролл был, но главное оно растягивается как тебе нужно.

nu11 ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.