Пишут, да, ибо куда деваться - подстраиваемся под App Layer как водится. Опять же, работодатель боится всего что не С++ (ибо С++ кодеров на рынке чуть не больше чем всех остальных больше взятых) и ему наплевать на то, что С++ не иделален для GUI (что на самом деле правда). Отсюда все эти забавы с XML описанием GUI, скинами и прочей хренью - типа "смысл - отдельно, внешний вид - отдельно".
Писать многоязычные проекты. И "кодеров на C++" близко к конторе не подпускать. Потому что на одной зарплате Q&A Team и тестеров потеряешь больше, чем разница в стоимости кодера и программиста. Не говоря уж о том, что один программист при правильном выборе инструментария заменяет 5-10 кодеров.
Давным давно нужен язык на замену С, с нормальными строками без беды с переполнениями, с встроенными динамическими массивами/хешами. Вроде mars D (http://www.digitalmars.com/d/index.html) ближе всего, однако он не индустриальный стандарт. И вообще сравнительно недавно был глубокой бетой. Не пробовал его использовать?
Это, пожалуй, слишком конфликтные требования для одного хорошего языка. Я бы предпочел интеграцию с низкоуровневым кодом там, где он реально нужен. А это нынче легко делается где угодно, хоть в Java, хоть в C#, хоть в Python.
Не, не конфликтные. И в С и в С++ есть библиотеки с этими функциями. Так что вполне можно реализовать все в одном языке. С разумным, коротким синтаксисом.
Внимание вопрос: где окажется java, если все это можно будет писать на D (или чем-то подобном), и не менее удобно/надежно, чем на java? Ответ: там же где и C, в мусорной корзине. Ибо нафига иметь 2 языка, если третий перекрывает первые оба?
А он не сможет перекрыть оба и остаться удобным/надежным. Вдобавок, флаг в руки реализовать такой набор стандартных библиотек, как в Java SE.
Одно дело "ассемблер высокого уровня" для системного программирования, с указателями, явным управлением динамической памятью и прочими небезопасными делами. Встроенные строки, ассоциативные структуры и garbage collection такому языку противопоказаны: хакерам все равно понадобится что-нибудь отличное от того, что дали им в качестве стандарта. Даже строками в динамической памяти можно управлять более чем одним способом.
Другое дело нормальный управляемый runtime с кучей встроенных удобств и безопасным исполнением. Там уже ни к чему указатели и явное управление памятью.
Использовать первый язык для реализации runtime второго и некоторых особенно критичных библиотек — вот, на мой взгляд, разумное сочетание лучшего из двух миров.
Еще раз: в С (С++ тоже) уже есть библиотеки, имеющие такую функциональность. Почему их стандартизировать и включить в язык противопоказано, мне вовсе не ясно.
вобще-то С и С++ это две огромные разницы а что в сях плохо кроме нуль-терминатед строк, которые достаточно ПРОСТО НЕ ЮЗАТЬ. НУ конечно если бы там были нормальные строки было бы намного лучше, и много хороших людей не погрязли бы в глюках с нулём в текстах...
Э-э. Как бы это сказать. Нормальные строки требуют именно динамических массивов. А от них уж совсем недалеко до хешей и сборщиков мусора. Плюс нормальный, не усложненый синтаксис. Плюс грамотно изначально встроенная система обработки исключительных ситуаций. Вот уже D почти и получился. Ну и для любителей там есть ОО. Но там ОО вполне можно и не пользоваться.
я не большой знаток java, но разве для неё не выполняются те же пункты? Вообще, они, по-моему, справедливы для любого объектно-ориентированного языка. Я пытался GUI на ocaml изобразить - точно на те же косяки налетал.
Дя, конечно, есть в C++ персональные глупости. Но они не специфичны для GUI. Да и хорошим стилем и использованием правильных библиотек - теми же smart pointer'ами они более-менее сглаживаются.
Пункт про "dynamic features" скриптовых языков не развёрнут - а было бы интересно посмотреть.
GUI практически на всём писать можно. C/WinAPI, C++/MFC, Python/wxPython, даже отдельный игровой GUI с биндингом в Lua писать приходилось. Вопрос не в языке, а в качестве библиотек. Главное - не использовать код там, где можно использовать данные, и не использовать лишние данные там, где можно обойтись куда более меньшей информацией.
В сети может и 6 лет она доступна. Но вообще там в начале подзаголовочек есть, указывающий на то, что опубликована она была в 1995 году: "A paper and a talk presented at MacHack'95, The 10th Annual Conference for Leading Edge Developers Southfield, MI, June 22-24, 1995." С того времени много воды утекло и стандарт языка приняли и следующую итерацию в развитии языка начали (как раз в направлении функционального стиля программирования).
Сама же статья меня несколько позабавила. Вывод просто замечательный: в С++ нет многих вещей, но они могут быть на нем эмулированы. Если могут, то в чем проблема!? Напиши хорошую библиотеку (готовую возьми), реализующую требуемый функционал и пользуйся ею всегда. Чем это принципиально отличается от подхода в языке высокого уровня, где все написано на том же С++ или С, но скрыто за синтаксическими конструкциями? А что делать, если на языке высокого уровня что-то реализовано не так, как тебе нужно? Ругать Билла Гейтса? Вот предположим, что в нашем супер-пупер замечательном языке реализована диспетчеризация событий, как в статье предложено. Событие плавно перетекает в вызов виртуального метода порожденного класса, тот же метод родителя вызывается автоматом. ВОПРОС НА ЗАСЫПКУ: а когда будет вызван метод-родителя - до или после того как отработает метод-потомка? А если мне нужны оба варианта? Предположим, потомок рисует фон, тогда родительский метод логично вызвать после. Но если потомок рисует передний план, то лучше родителя дернуть до. А еще бывают случаи, когда родительский код надо полностью выкинуть и нарисовать все свое. Тогда как? Как минимум придется в таком языке реализовывать еще и управление вызовами, например, путем навешивания описательных аттрибутов на объявление метода. И так на каждый чих. Боюсь, что после опыта общения с подобными монстрами С++ начнет казаться простым и логичным. :-)
Не люблю я такие статьи. Очень они мне ограду на кладбище напоминают. В том смысле, что на кладбище ограда есть в любом случае, но от непрерывного увеличения числа могил на нем это не спасает. Что делать-то? Этого как раз и не написано. Вялые ссылки на Tkl/Tk не в счет. Убежден, что в указанных языках тоже есть проблемы с решением определенного класса задач - не понос так золотуха. И если бы меня попросили одним предложением выразить суть обсуждаемой статьи, то я бы сформулировал требуемое так: "Где моя большая кнопка СДЕЛАТЬ ВСЕ, КАК Я ХОЧУ!?"
Честно говоря, я бы запретил ссылаться на статьи по C++, написанные до 1998 года. И повелел бы относиться с подозрением ко всему, что написано после, но не подписано одной из следующих фамилий: Abrahams, Alexandrescu, Austern, Czarnecki, Dewhurst, Gurtovoy, Josuttis, Karlsson, Koenig, Kühl, Langer, Meyers, Moo, Myers, Stepanov, Stroustrup, Sutter, Vandevoorde и прочая :-)
А что делать, если на языке высокого уровня что-то реализовано не так, как тебе нужно? Ругать Билла Гейтса?
А вы не пользуйтесь средствами разработки, продаваемыми Биллом Гейтсом. Пользуйтесь нормальными, где всегда можно опуститься на уровень абстракции ниже, на уровень реализации интерпретатора и реализовать нужную функциональность в виде расширения.
Можно на CPAN посмотреть - захотелось людям - прикрутили объекты, захотелось - прикрутили контракты. В каком стиле хочешь, в таком и пиши. Только послеживай чтобы на разработку инструментария не ушло больше сил, чем сэкономится от его употребления.
Вот предположим, что в нашем супер-пупер замечательном языке реализована диспетчеризация событий, как в статье предложено. Событие плавно перетекает в вызов виртуального метода порожденного класса, тот же метод родителя вызывается автоматом. ВОПРОС НА ЗАСЫПКУ: а когда будет вызван метод-родителя - до или после того как отработает метод-потомка? А если мне нужны оба варианта?
Берем документацию и читаем. Там это должно быть написано. И как порядок поменять - тоже написано. И как заблокировать умолчательное поведение (заметим, что "умолчательное" понятие - существенно более широкое, чем "унаследованное"). В Tk это описано в описаниях команд bind и bindtags.
Вообще, прежде чем ругать подходы, отличные от пиджн-C++ (иначе чем пиджн тот стиль, на котором пишут люди, кругозор которых не простирается за C++ я назвать не могу), стоит посмотреть, а какие есть альтернативы. Для начала изучить SmallTalk, чтобы понять как на самом деле должна быть устроена объектная ориентированность в языке. Потом - Tcl/Tk чтобы понять, что на объектной ориентации свет клином не сошелся и концепция наследования для GUI скорее вредна, чем полезна. Еще крайне полезно что-нибудь функциональное - Erlang, Haskel, Ocaml. Ну и, естественно - Common Lisp, потому что на этом вообще вся культура программирования стоит.
bind по тегам в tk - это как раз пример того, как не надо делать.
Сейчас вот не вспомню, получилось ли у меня в конце концов повесить bind на toplevel окно, но не на его child'ов. Судя по манам - просто это не сделать, только обходить все виджеты ручками.
"Tcl/Tk чтобы понять, что на объектной ориентации свет клином не сошелся и концепция наследования для GUI скорее вредна, чем полезна"
Особенно потешно наблюдать, как авторы биндингов tk к языкам пытаются адаптировать tk-шную иерархию виджетов к своей системе типов.
И вообще, мне сама конструкция <чтото>/tk не нравится, потому что tk за собой неминуемо tcl тянет. Если учесть, что бинлинг может быть неполный - в конце концов приходится писать винегрет из tcl и своего языка. Да и на быстродействие это, мягко говоря, не лучшим образом влияет.
Сейчас вот не вспомню, получилось ли у меня в конце концов повесить bind на toplevel окно, но не на его child'ов.
Замечательная иллюстрация того, почему программисты, искалеченые C++ не могут использовать Tk.
1. Читаем man bindtags
By default, each window has four binding tags consisting of the name of
the window, the window's class name, the name of the window's nearest
toplevel ancestor, and all, in that order.
Соответственно если "повесить bind только на toplevel окно, но не на содержащиеся в нем видгеты" это означает то что я подумал сначала "вызвать bind один раз, и чтобы во всем окне работало", то это дефолтное поведение.
Если же оно значит прямо противоположное: "хочу чтобы данное событе обрабатывалось только если юзер ткнул мышкой в чистое место окна", то так и надо говорить
bind $window <Button-1> { if {[winfo class %W] == "Toplevel"} {...} }
Можно еще (это чуточку надежнее, поскольку вдруг ты захочешь класс окну другой указать) проверять на [winfo toplevel %W] == "%W".
3. "Обойти все видгеты ручками" в Tk это четыре строчки, не считая закрывающих скобок
Вообще основное отличие Tk от других тулкитов заключается в том что необязательно писать GUI. Можно писать программу, которая генерирует необходимый GUI по ходу дела.
Особенно потешно наблюдать, как авторы биндингов tk к языкам пытаются адаптировать tk-шную иерархию виджетов к своей системе типов.
Ага, потешно. Что только не придумают люди, чтобы подогнать задачу под свое средство выражения, вместо того чтобы использовать для каждой задачи подходщяее ей средство выражения. Реализацию длинной арифметики на Tcl я тоже видел.
Хотя в wiki.tcl.tk есть замечательный пример как надо - когда длинная арифметика делается через пайп в dc.
"только если юзер ткнул мышкой в чистое место окна"
В том конкретном случае я хотел обрабатывать закрытие окна. Естественно, обрабатывающая процедура должна была быть вызвана 1 раз, а не столько раз, сколько там детей. Да, возожно, так и сделал, как написано.
"'Обойти все видгеты ручками' в Tk это четыре строчки"
Это в любом языке немного строчек, просто получается как у Жванецкого: "наливаете чай и НЕ кладете туда лимон, понятно?".
"Можно писать программу, которая генерирует необходимый GUI по ходу дела."
Как правило, логика нужна гую, а не наоборот. А закладываясь на "генерирование необходимого гуя", неминуемо задвигаешь его в схему того самого генерования. И очередная идея коллег/начальства обязательно не влезет в эту схему. И начинаются хаки...
Можно только изобрести ещё один враппер для гуя вместо уже имеющегося. Иногда об этом не жалеешь.
А наверное, у вас хорошо... У нас тут уже и веб-дезигнезы стали пикселы считать. :(
Вообще-то закрытие окна обрабатывается вообще не через биндинги а через средства взаимодействия с window manager. wm protocol $window WM_CLOSE. Для того, чтобы писать GUI, нужно иметь некоторое представление о том, как устроена внешняя среда в которой выполняется программа, и в каком месте программа взаимодействует с пользователем непосредственно, а в каком - через другие компоненты системы.
А за считание пикселов - увольнять с волчьим билетом немедленно.
Как-это так, сволочь-дизайнер не позволяет мне увеличить шрифт в два раза? А если я вижу плохо? Особенно меня прикалывают такие web-дизайнеры, которые искренне считают что им известен способ запретить пользователю увеличить шрифт. Я одного порадовал пятком скриншотов из мозиллы, которая, как и положено любой нормальной программе своего пользователя слушается лучше, чем какого-то там дизайнера.
Что касается того что в GUI должна быть логика, то это правильно. Логика там должна быть, а не дизайн. Вернее, дизайн должен занимать подчиеннное положение по отношению к логике. Именно этого позволяет добиться генерация GUI. Потому что логика средств генерации является следствием логики собственно рабочей части программы, то есть логики предметной области.
Описано только WM_DELETE_WINDOW. Он, правда, больше подходит для перехвата и отмены удаления - да, бывают и такие пожелания. Если хотешь, чтобы окно таки изчезло - зови destroy самостоятельно. Вот такой вот event relay.
И не говори мне что я должен читать документацию на Xlib или ICCCM или как его там. Закрытие окна - это событие на уровне приложения. Я в этом достаточно уверен, чтобы искать решение именно на уровне приложения. А то ведь можно дойти и до того, что и мышиные клики будем обрабатывать через "xserver event ....".
По мне, идеальная картина такая: WM_<я не знаю что> ловится внутренним обратчиком, а он в ходе обработки запускает уже события уровня приложения (в том числе Destroy, который меня и интересует). Самое интересное, что всё так и есть, просто использование тегов принуждает к дополнительным извратам.
> Как-это так, сволочь-дизайнер не позволяет мне увеличить шрифт в два раза? А если я вижу плохо?
я после написания одной программы стал все параметры шрифтов и фона хранить в переменных (3-4 типов хватает: заголовки, надписи, иногда особые надписи, поля ввода) - у переменных есть значения по умолчанию (которые мне нравятся), а на каждой клиентской машине в файле конфига можно задать любое другое значение (и шрифт в 2 раза больше) - если об этом заранее думать, то в любой программе можно такое делать, и никаких подсчетов пикселов
Tk, в этом отношении, с 4-мя менеджерами форм большое подспорье - и Borland'овская VCL, и MFC после этого кажутся тихим ужасом
Осталось еще осознать что не нужно заводить собственных механизмов для хранения параметров внешнего вида интерфейса - есть option database, которая умеет и пользоваться стандартным хранилищем, предоставляемым операционной системой (xrdb) и подгружать свои собственные конфигурационные файлы.
> получилось ли у меня в конце концов повесить bind на toplevel окно, но не на его child'ов
я на Perl/Tk подобное решал - внутри bind'a проверял родителей объекта: my $path = $en->PathName; ........ if $path =~ /^(\.toplevel)*(\.frame\d*)*\.entry\d*$/
А вы не пользуйтесь средствами разработки, продаваемыми Биллом Гейтсом. Пользуйтесь нормальными, где всегда можно опуститься на уровень абстракции ниже, на уровень реализации интерпретатора и реализовать нужную функциональность в виде расширения.
Можно на CPAN посмотреть - захотелось людям - прикрутили объекты, захотелось - прикрутили контракты. В каком стиле хочешь, в таком и пиши. Только послеживай чтобы на разработку инструментария не ушло больше сил, чем сэкономится от его употребления.
Но вы так и не ответили на вопрос, чем написание и использование библиотеки на C++ принципиально отличается от дополнения интерпретатора языка высокого уровня. Вам, кажется, Билл Гейтс не понравился? Мне он тоже не нравится, именно поэтому я всуе помянул его, а не Ларри Уолла. Но Perl в контексте нашего обсуждения является неудачным примером. Нет там никаких объектов, контрактов. Есть скаляр, вектор, хэш и все. А вот все остальное появляется после чего!? Правильно! После эмуляции недостающих возможностей средствами языка. Против чего в статье боролись - на то и напоролись. А ведь еще понадобилось интерпретатор научить таким словам как bless. Спустились, что называется на уровень реализации, как вы предлагаете. Вопрос, могу ли я для своих целей модифицировать интерпретатор Perl? Могу. Исходные тексты есть, лицензия не запрещает. А могу я распространять свою программу, зависящую от этих изменений? Нет, не могу, пока изменения не примут в основную ветку кода. Не можете же вы каждого пользователя своего продукта принуждать использовать именно вашу версию Perl. Что мы имеем с C++? Если библиотека меня не устраивает, я ее модифицирую и спокойно использую. Свой вариант можно всегда скомпоновать с программой статически. Если же нужна динамическая компоновка, то тоже никаких проблем. Кладу свою библиотеку в директорию, специфичную для приложения, и гружу оттуда.
Берем документацию и читаем. Там это должно быть написано. И как порядок поменять - тоже написано. И как заблокировать умолчательное поведение (заметим, что "умолчательное" понятие - существенно более широкое, чем "унаследованное"). В Tk это описано в описаниях команд bind и bindtags.
Прочитал. Реализация концепции слот-сигнал в Qt по гибкости и удобству использования не хуже, если не лучше. Вероятно, все сводится к личным вкусам, не так ли?
Вообще, прежде чем ругать подходы, отличные от пиджн-C++ (иначе чем пиджн тот стиль, на котором пишут люди, кругозор которых не простирается за C++ я назвать не могу), стоит посмотреть, а какие есть альтернативы. Для начала изучить SmallTalk, чтобы понять как на самом деле должна быть устроена объектная ориентированность в языке. Потом - Tcl/Tk чтобы понять, что на объектной ориентации свет клином не сошелся и концепция наследования для GUI скорее вредна, чем полезна. Еще крайне полезно что-нибудь функциональное - Erlang, Haskel, Ocaml. Ну и, естественно - Common Lisp, потому что на этом вообще вся культура программирования стоит.
Вся эта часть основана исключительно на ваших предположениях. Почему ругать, а не оппонировать? Что вы знаете о моем стиле программирования? Почему вы уверенны, что я не знаком с функциональным программированием? И почему считаете, что идеи, заложенные в тот же Ocaml и Haskel мне не импонируют? Так что без комментариев.
Но вы так и не ответили на вопрос, чем написание и использование библиотеки Бна C++ принципиально отличается от дополнения интерпретатора языка высокого уровня.
Набором доступных выразительных средств. В C++ хоть наизнанку вывернись, а оператор unless не реализуешь. В Tcl или Lisp - в три строчки.
А могу я распространять свою программу, зависящую от этих изменений? Нет, не могу, пока изменения не примут в основную ветку кода.
Почему? Я вот распространяю со своими программами интерпретатор Tcl. В некоторых случаях пользователь об этом даже не подозревает. Он получает большой бинарник, который запускается и выполняется. А что там внутри - какая ему разница?
В других - он увидит, что в комплекте приложения есть файл с именем tcl84.dll. Но это никак не соотносится с тем, что у него может стоять более другая версия Tcl, которой он будет пользоваться в более других целях.
Хорошо, только насчет "наизнанку вывернись" вы не совсем правы. Вами же предложенная метода сработает железно - изменяем компилятор, чтобы он понимал семантику конструкции unless и все. Никого ведь не волнует, чем я компилирую. А для тех, кого волнует, можно исходники в инет выложить. Другой вопрос, что это действительно способ "наизнанку", затраченные силы не окупятся полученным результатом.
А дискуссия тем временем вырождается в классичесскую holy war. Надо бы остановиться, не находите?
no subject
Date: 2006-01-11 07:14 am (UTC)no subject
Date: 2006-01-12 08:15 am (UTC)no subject
Date: 2006-01-13 01:39 am (UTC)no subject
Date: 2006-01-11 12:39 pm (UTC)Не пробовал его использовать?
no subject
Date: 2006-01-11 01:48 pm (UTC)М-м-м... Java?
no subject
Date: 2006-01-11 01:50 pm (UTC)no subject
Date: 2006-01-11 02:03 pm (UTC)М-м-м... Java SE 5 от Sun? :)
Компилятор.
JIT подойдет?
Что-бы подходил для системно-ориентированого ПО.
Это, пожалуй, слишком конфликтные требования для одного хорошего языка.
Я бы предпочел интеграцию с низкоуровневым кодом там, где он реально нужен. А это нынче легко делается где угодно, хоть в Java, хоть в C#, хоть в Python.
no subject
Date: 2006-01-11 02:16 pm (UTC)no subject
Date: 2006-01-11 02:36 pm (UTC)no subject
Date: 2006-01-11 02:39 pm (UTC)no subject
Date: 2006-01-11 03:03 pm (UTC)no subject
Date: 2006-01-12 12:17 am (UTC)Гибрид коня и трепетной лани
Date: 2006-01-12 01:39 am (UTC)Одно дело "ассемблер высокого уровня" для системного программирования, с указателями, явным управлением динамической памятью и прочими небезопасными делами. Встроенные строки, ассоциативные структуры и garbage collection такому языку противопоказаны: хакерам все равно понадобится что-нибудь отличное от того, что дали им в качестве стандарта. Даже строками в динамической памяти можно управлять более чем одним способом.
Другое дело нормальный управляемый runtime с кучей встроенных удобств и безопасным исполнением. Там уже ни к чему указатели и явное управление памятью.
Использовать первый язык для реализации runtime второго и некоторых особенно критичных библиотек — вот, на мой взгляд, разумное сочетание лучшего из двух миров.
Re: Гибрид коня и трепетной лани
Date: 2006-01-12 02:21 am (UTC)no subject
Date: 2006-01-11 10:20 pm (UTC)по сравнению с С пишется как минимум в 2 раза быстрее
no subject
Date: 2006-01-11 10:37 pm (UTC)no subject
Date: 2006-01-12 08:27 am (UTC)- для Tcl нет cpan'a
- большей частью мои программы являются не просто мордой
no subject
Date: 2006-01-12 08:34 am (UTC)no subject
Date: 2006-01-12 12:12 am (UTC)no subject
Date: 2006-01-12 12:33 am (UTC)а что в сях плохо кроме нуль-терминатед строк, которые достаточно ПРОСТО НЕ ЮЗАТЬ.
НУ конечно если бы там были нормальные строки было бы намного лучше, и много хороших людей не погрязли бы в глюках с нулём в текстах...
no subject
Date: 2006-01-12 12:41 am (UTC)no subject
Date: 2006-01-11 07:36 pm (UTC)Дя, конечно, есть в C++ персональные глупости. Но они не специфичны для GUI. Да и хорошим стилем и использованием правильных библиотек - теми же smart pointer'ами они более-менее сглаживаются.
Пункт про "dynamic features" скриптовых языков не развёрнут - а было бы интересно посмотреть.
no subject
Date: 2006-01-11 08:33 pm (UTC)no subject
Date: 2006-01-11 10:30 pm (UTC)Большая кнопка
Date: 2006-01-12 02:24 am (UTC)The 10th Annual Conference for Leading Edge Developers
Southfield, MI, June 22-24, 1995." С того времени много воды утекло и стандарт языка приняли и следующую итерацию в развитии языка начали (как раз в направлении функционального стиля программирования).
Сама же статья меня несколько позабавила. Вывод просто замечательный: в С++ нет многих вещей, но они могут быть на нем эмулированы. Если могут, то в чем проблема!? Напиши хорошую библиотеку (готовую возьми), реализующую требуемый функционал и пользуйся ею всегда. Чем это принципиально отличается от подхода в языке высокого уровня, где все написано на том же С++ или С, но скрыто за синтаксическими конструкциями? А что делать, если на языке высокого уровня что-то реализовано не так, как тебе нужно? Ругать Билла Гейтса? Вот предположим, что в нашем супер-пупер замечательном языке реализована диспетчеризация событий, как в статье предложено. Событие плавно перетекает в вызов виртуального метода порожденного класса, тот же метод родителя вызывается автоматом. ВОПРОС НА ЗАСЫПКУ: а когда будет вызван метод-родителя - до или после того как отработает метод-потомка? А если мне нужны оба варианта? Предположим, потомок рисует фон, тогда родительский метод логично вызвать после. Но если потомок рисует передний план, то лучше родителя дернуть до. А еще бывают случаи, когда родительский код надо полностью выкинуть и нарисовать все свое. Тогда как? Как минимум придется в таком языке реализовывать еще и управление вызовами, например, путем навешивания описательных аттрибутов на объявление метода. И так на каждый чих. Боюсь, что после опыта общения с подобными монстрами С++ начнет казаться простым и логичным. :-)
Не люблю я такие статьи. Очень они мне ограду на кладбище напоминают. В том смысле, что на кладбище ограда есть в любом случае, но от непрерывного увеличения числа могил на нем это не спасает. Что делать-то? Этого как раз и не написано. Вялые ссылки на Tkl/Tk не в счет. Убежден, что в указанных языках тоже есть проблемы с решением определенного класса задач - не понос так золотуха. И если бы меня попросили одним предложением выразить суть обсуждаемой статьи, то я бы сформулировал требуемое так: "Где моя большая кнопка СДЕЛАТЬ ВСЕ, КАК Я ХОЧУ!?"
Re: Большая кнопка
Date: 2006-01-19 03:02 pm (UTC)Re: Большая кнопка
Date: 2006-01-12 08:12 am (UTC)А что делать, если на языке высокого уровня что-то реализовано не так, как тебе нужно? Ругать Билла Гейтса?
А вы не пользуйтесь средствами разработки, продаваемыми Биллом Гейтсом. Пользуйтесь нормальными, где всегда можно опуститься на уровень абстракции ниже, на уровень реализации интерпретатора и реализовать нужную функциональность в виде расширения.
Можно на CPAN посмотреть - захотелось людям - прикрутили объекты, захотелось - прикрутили контракты. В каком стиле хочешь, в таком и пиши. Только послеживай чтобы на разработку инструментария не ушло больше сил, чем сэкономится от его употребления.
Вот предположим, что в нашем супер-пупер замечательном языке реализована диспетчеризация событий, как в статье предложено. Событие плавно перетекает в вызов виртуального метода порожденного класса, тот же метод родителя вызывается автоматом. ВОПРОС НА ЗАСЫПКУ: а когда будет вызван метод-родителя - до или после того как отработает метод-потомка? А если мне нужны оба варианта?
Берем документацию и читаем. Там это должно быть написано. И как порядок поменять - тоже написано. И как заблокировать умолчательное поведение (заметим, что "умолчательное" понятие - существенно более широкое, чем "унаследованное"). В Tk это описано в описаниях команд bind и bindtags.
Вообще, прежде чем ругать подходы, отличные от пиджн-C++ (иначе чем пиджн тот стиль, на котором пишут люди, кругозор которых не простирается за C++ я назвать не могу), стоит посмотреть, а какие есть альтернативы. Для начала изучить SmallTalk, чтобы понять как на самом деле должна быть устроена объектная ориентированность в языке. Потом - Tcl/Tk чтобы понять, что на объектной ориентации свет клином не сошелся и концепция наследования для GUI скорее вредна, чем полезна. Еще крайне полезно что-нибудь функциональное - Erlang, Haskel, Ocaml. Ну и, естественно - Common Lisp, потому что на этом вообще вся культура программирования стоит.
Re: Большая кнопка
Date: 2006-01-12 07:38 pm (UTC)Сейчас вот не вспомню, получилось ли у меня в конце концов повесить bind на toplevel окно, но не на его child'ов. Судя по манам - просто это не сделать, только обходить все виджеты ручками.
"Tcl/Tk чтобы понять, что на объектной ориентации свет клином не сошелся и концепция наследования для GUI скорее вредна, чем полезна"
Особенно потешно наблюдать, как авторы биндингов tk к языкам пытаются адаптировать tk-шную иерархию виджетов к своей системе типов.
И вообще, мне сама конструкция <чтото>/tk не нравится, потому что tk за собой неминуемо tcl тянет. Если учесть, что бинлинг может быть неполный - в конце концов приходится писать винегрет из tcl и своего языка. Да и на быстродействие это, мягко говоря, не лучшим образом влияет.
Re: Большая кнопка
Date: 2006-01-12 09:37 pm (UTC)Сейчас вот не вспомню, получилось ли у меня в конце концов повесить bind на toplevel окно, но не на его child'ов.
Замечательная иллюстрация того, почему программисты, искалеченые C++ не могут использовать Tk.
1. Читаем man bindtags
By default, each window has four binding tags consisting of the name of the window, the window's class name, the name of the window's nearest toplevel ancestor, and all, in that order.Соответственно если "повесить bind только на toplevel окно, но не на содержащиеся в нем видгеты" это означает то что я подумал сначала "вызвать bind один раз, и чтобы во всем окне работало", то это дефолтное поведение.
Если же оно значит прямо противоположное: "хочу чтобы данное событе обрабатывалось только если юзер ткнул мышкой в чистое место окна", то так и надо говорить
bind $window <Button-1> { if {[winfo class %W] == "Toplevel"} {...} }Можно еще (это чуточку надежнее, поскольку вдруг ты захочешь класс окну другой указать) проверять на [winfo toplevel %W] == "%W".
3. "Обойти все видгеты ручками" в Tk это четыре строчки, не считая закрывающих скобок
proc bindchildren {window args} { eval bind [list $window] $args foreach child [winfo children $window] { eval bindchildren [list $child] $args } }Вообще основное отличие Tk от других тулкитов заключается в том что необязательно писать GUI. Можно писать программу, которая генерирует необходимый GUI по ходу дела.
Особенно потешно наблюдать, как авторы биндингов tk к языкам пытаются адаптировать tk-шную иерархию виджетов к своей системе типов.
Ага, потешно. Что только не придумают люди, чтобы подогнать задачу под свое средство выражения, вместо того чтобы использовать для каждой задачи подходщяее ей средство выражения. Реализацию длинной арифметики на Tcl я тоже видел.
Хотя в wiki.tcl.tk есть замечательный пример как надо - когда длинная арифметика делается через пайп в dc.
Re: Большая кнопка
Date: 2006-01-12 10:30 pm (UTC)В том конкретном случае я хотел обрабатывать закрытие окна. Естественно, обрабатывающая процедура должна была быть вызвана 1 раз, а не столько раз, сколько там детей. Да, возожно, так и сделал, как написано.
"'Обойти все видгеты ручками' в Tk это четыре строчки"
Это в любом языке немного строчек, просто получается как у Жванецкого: "наливаете чай и НЕ кладете туда лимон, понятно?".
"Можно писать программу, которая генерирует необходимый GUI по ходу дела."
Как правило, логика нужна гую, а не наоборот. А закладываясь на "генерирование необходимого гуя", неминуемо задвигаешь его в схему того самого генерования. И очередная идея коллег/начальства обязательно не влезет в эту схему. И начинаются хаки...
Можно только изобрести ещё один враппер для гуя вместо уже имеющегося. Иногда об этом не жалеешь.
А наверное, у вас хорошо... У нас тут уже и веб-дезигнезы стали пикселы считать. :(
Re: Большая кнопка
Date: 2006-01-13 01:17 am (UTC)А за считание пикселов - увольнять с волчьим билетом немедленно.
Как-это так, сволочь-дизайнер не позволяет мне увеличить шрифт в два раза? А если я вижу плохо? Особенно меня прикалывают такие web-дизайнеры, которые искренне считают что им известен способ запретить пользователю увеличить шрифт. Я одного порадовал пятком скриншотов из мозиллы, которая, как и положено любой нормальной программе своего пользователя слушается лучше, чем какого-то там дизайнера.
Что касается того что в GUI должна быть логика, то это правильно. Логика там должна быть, а не дизайн. Вернее, дизайн должен занимать подчиеннное положение по отношению к логике. Именно этого позволяет добиться генерация GUI. Потому что логика средств генерации является следствием логики собственно рабочей части программы, то есть логики предметной области.
Re: Большая кнопка
Date: 2006-01-13 03:03 am (UTC)Описано только WM_DELETE_WINDOW. Он, правда, больше подходит для перехвата и отмены удаления - да, бывают и такие пожелания. Если хотешь, чтобы окно таки изчезло - зови destroy самостоятельно. Вот такой вот event relay.
И не говори мне что я должен читать документацию на Xlib или ICCCM или как его там. Закрытие окна - это событие на уровне приложения. Я в этом достаточно уверен, чтобы искать решение именно на уровне приложения. А то ведь можно дойти и до того, что и мышиные клики будем обрабатывать через "xserver event ....".
По мне, идеальная картина такая: WM_<я не знаю что> ловится внутренним обратчиком, а он в ходе обработки запускает уже события уровня приложения (в том числе Destroy, который меня и интересует). Самое интересное, что всё так и есть, просто использование тегов принуждает к дополнительным извратам.
Re: Большая кнопка
Date: 2006-01-14 02:02 pm (UTC)я после написания одной программы стал все параметры шрифтов и фона хранить в переменных (3-4 типов хватает: заголовки, надписи, иногда особые надписи, поля ввода) - у переменных есть значения по умолчанию (которые мне нравятся), а на каждой клиентской машине в файле конфига можно задать любое другое значение (и шрифт в 2 раза больше) - если об этом заранее думать, то в любой программе можно такое делать, и никаких подсчетов пикселов
Tk, в этом отношении, с 4-мя менеджерами форм большое подспорье - и Borland'овская VCL, и MFC после этого кажутся тихим ужасом
Re: Большая кнопка
Date: 2006-01-15 01:09 am (UTC)Re: Большая кнопка
Date: 2006-01-13 06:14 am (UTC)я на Perl/Tk подобное решал - внутри bind'a проверял родителей объекта:
my $path = $en->PathName;
........ if $path =~ /^(\.toplevel)*(\.frame\d*)*\.entry\d*$/
Re: Большая кнопка
Date: 2006-01-13 10:04 am (UTC)if {$en == $en->toplevel).
Re: Большая кнопка
Date: 2006-01-14 03:45 am (UTC)Re: Большая кнопка
Date: 2006-01-14 01:44 pm (UTC)Re: Большая кнопка
Date: 2006-01-13 12:26 am (UTC)Можно на CPAN посмотреть - захотелось людям - прикрутили объекты, захотелось - прикрутили контракты. В каком стиле хочешь, в таком и пиши. Только послеживай чтобы на разработку инструментария не ушло больше сил, чем сэкономится от его употребления.
Но вы так и не ответили на вопрос, чем написание и использование библиотеки на C++ принципиально отличается от дополнения интерпретатора языка высокого уровня. Вам, кажется, Билл Гейтс не понравился? Мне он тоже не нравится, именно поэтому я всуе помянул его, а не Ларри Уолла. Но Perl в контексте нашего обсуждения является неудачным примером. Нет там никаких объектов, контрактов. Есть скаляр, вектор, хэш и все. А вот все остальное появляется после чего!? Правильно! После эмуляции недостающих возможностей средствами языка. Против чего в статье боролись - на то и напоролись. А ведь еще понадобилось интерпретатор научить таким словам как bless. Спустились, что называется на уровень реализации, как вы предлагаете. Вопрос, могу ли я для своих целей модифицировать интерпретатор Perl? Могу. Исходные тексты есть, лицензия не запрещает. А могу я распространять свою программу, зависящую от этих изменений? Нет, не могу, пока изменения не примут в основную ветку кода. Не можете же вы каждого пользователя своего продукта принуждать использовать именно вашу версию Perl. Что мы имеем с C++? Если библиотека меня не устраивает, я ее модифицирую и спокойно использую. Свой вариант можно всегда скомпоновать с программой статически. Если же нужна динамическая компоновка, то тоже никаких проблем. Кладу свою библиотеку в директорию, специфичную для приложения, и гружу оттуда.
Берем документацию и читаем. Там это должно быть написано. И как порядок поменять - тоже написано. И как заблокировать умолчательное поведение (заметим, что "умолчательное" понятие - существенно более широкое, чем "унаследованное"). В Tk это описано в описаниях команд bind и bindtags.
Прочитал. Реализация концепции слот-сигнал в Qt по гибкости и удобству использования не хуже, если не лучше. Вероятно, все сводится к личным вкусам, не так ли?
Вообще, прежде чем ругать подходы, отличные от пиджн-C++ (иначе чем пиджн тот стиль, на котором пишут люди, кругозор которых не простирается за C++ я назвать не могу), стоит посмотреть, а какие есть альтернативы. Для начала изучить SmallTalk, чтобы понять как на самом деле должна быть устроена объектная ориентированность в языке. Потом - Tcl/Tk чтобы понять, что на объектной ориентации свет клином не сошелся и концепция наследования для GUI скорее вредна, чем полезна. Еще крайне полезно что-нибудь функциональное - Erlang, Haskel, Ocaml. Ну и, естественно - Common Lisp, потому что на этом вообще вся культура программирования стоит.
Вся эта часть основана исключительно на ваших предположениях. Почему ругать, а не оппонировать? Что вы знаете о моем стиле программирования? Почему вы уверенны, что я не знаком с функциональным программированием? И почему считаете, что идеи, заложенные в тот же Ocaml и Haskel мне не импонируют? Так что без комментариев.
Re: Большая кнопка
Date: 2006-01-13 01:21 am (UTC)Но вы так и не ответили на вопрос, чем написание и использование библиотеки Бна C++ принципиально отличается от дополнения интерпретатора языка высокого уровня.
Набором доступных выразительных средств. В C++ хоть наизнанку вывернись, а оператор unless не реализуешь. В Tcl или Lisp - в три строчки.
А могу я распространять свою программу, зависящую от этих изменений? Нет, не могу, пока изменения не примут в основную ветку кода.
Почему? Я вот распространяю со своими программами интерпретатор Tcl. В некоторых случаях пользователь об этом даже не подозревает. Он получает большой бинарник, который запускается и выполняется. А что там внутри - какая ему разница?
В других - он увидит, что в комплекте приложения есть файл с именем tcl84.dll. Но это никак не соотносится с тем, что у него может стоять более другая версия Tcl, которой он будет пользоваться в более других целях.
Re: Большая кнопка
Date: 2006-01-13 03:00 am (UTC)А дискуссия тем временем вырождается в классичесскую holy war. Надо бы остановиться, не находите?
Re: Большая кнопка
Date: 2006-01-13 11:58 pm (UTC)Re: Большая кнопка
Date: 2006-01-13 06:19 am (UTC)в первую очередь скоростью написания программ, что я и написал выше, - для коммерческих реализаций это очень важный параметр