Pull to refresh

Comments 42

Авторы пошли еще дальше и включили абстрактный интерфейс рисования, близкий по внешнему интерфейсу к Gdk. В рамках этого интерфейса присутствует, например, Xwt.Drawing.Color, отличный и от System.Drawing.Color, и от Gdk.Color.
Вот чем им System.Drawing не угодил, работает же везде (Cairo в качестве бакэнда у libgdiplus). Так и приходится колдовать с созданием Bitmap-ов, указывающих на один физический участок памяти.
Для меня это тоже было разочарованием, но причина, как я полагаю, совершенно очевидная — в MonoDevelop уже были куски кода на Mono.Cairo.
На момент 4х лет назад System.Drawing был написан осьминогами. Цвета перепутаны, точку без дополнительного гемора не нарисовать, аналога bitblt не было вообще, индексированные палитры не поддерживались. Сейчас не знаю.
Цвета перепутаны
Это как?
аналога bitblt не было вообще
Вам надо картинки рисовать или дёргать куски с одного Graphics на другой? Первое делается через graphics.DrawImage, второе в общем случае невозможно, потому что Graphics может быть не только поверх битмапа. Если хотите двойную буферизацию, создавайте Graphics поверх Bitmap и уже этот битмап рисуйте через DrawImage.

С портабельностью на никсах я заметил ровно две проблемы
1) тупит изменение размера картинок, на выходе очень некрасиво
2) нельзя зеркалировать картинки, задавая целевому прямоугольнику отрицательные размеры
> Это как?
А вот так ) Значения именованных цветов не совпадали с реальностью — ис того, что помню darkgray светлее чем gray.

> Вам надо картинки рисовать или дёргать куски с одного Graphics на другой?
Таки надо было дёргать куски Graphics. Делал велоконтрол для отображения древовидной структуры. Нужно было при открытии/закрытии структуры сдвигать часть изображения. Пришлось дёргать bitblt (вот в эту трубу, похоже, вся переносимость на Mono и улетает). Двойная буферизация — средствами WinForms.

Что характерно, с этой задачей bitblt превосходно справлялся: достаточно было просто передать ему хэнд контекста из Graphics.

А уж рисовать точки прямоугольниками — это вообще нечто.
Таки надо было дёргать куски Graphics. Делал велоконтрол для отображения древовидной структуры. Нужно было при открытии/закрытии структуры сдвигать часть изображения. Пришлось дёргать bitblt (вот в эту трубу, похоже, вся переносимость на Mono и улетает)
Вы его откуда брали, из текущего состояния экрана? Это не очень хорошая идея как бы. Если не брать с экрана, то никаких проблем с реализацией двойной буферизации со своим Graphics поверх битмапа я не вижу. В целом же решение типа «сдвигать часть изображения» выглядит как костыль.
Да не было там битмаба, там был Graphics юзерконтрола и включённая буферизация у него же ) То есть, я тупо рисовал на контроле в событии отрисовки. bitblt делал для эко контекста из самого в себя, нехватающее дорисовывал. В принципе, это даже работало и нормально выглядело.
В принципе, это костыль. Хотите использовать уже отрисованные данные — делайте Graphics.FromBitmap, рисуйте на нём и используйте потом исходный битмап в качестве источника. Сферический же Graphics в вакууме может вообще не использовать внутри битмап — он может представлять принтер, например.
Тут возникает встречный вопрос: зачем нужна эта высокоуровневая абстракция, если всё равно приходится спускаться вниз на конкретную реализацию? А вдруг я захочу нарисовать тоже самое именно на контексте принтера? Имхо, костыль тут как раз FromBitmap. Впрочем, и вызов bitblt тут костыль… И за это System.Drawing мне и не нравится — без костылей не обойтись.
высокоуровневая абстракция
Потому что это абстракция не над картинкой, это абстракция над «штукой, на которой можно рисовать», нигде не сказано, что её при этом можно использовать в качестве источника. Хотите нечто, на чём можно рисовать и использовать в качестве источника? Создайте источник и прикрепите к нему контекст рисования, это логично и правильно с архитектурной точки зрения.
А вдруг я захочу нарисовать тоже самое именно на контексте принтера?
То же самое в контексте принтера вы не можете нарисовать без своей буферизации, потому что ваш код хочет читать данные с контекста рисования, а с принтера нельзя читать.
Вы же не жалуетесь на то, что из сокета нельзя прочитать ранее отправленные данные, верно?
Graphics в случае принтера рисуется в векторе. Там нельзя просто так взять, и использовать растровый битмап. И на кой хрен там буферизация-то? Каждая страница отрисовывается 1 раз в специальном классе…
Если я верно помню, с контекста Graphics можно читать всегда. Вызываете берёте getHdc, получаете хэндл контекста и используете WinAPI.
Если я верно помню, с контекста Graphics можно читать всегда.
BitBlt обычно не в может прочитать с hDC принтера. Более того, она в ряде случаев туда и писать оказывается не в состоянии.
Точно не скажу, конкретно с контекстом принтера bitblt я не использовал. В любом случае, непонятно, что им мешало сделать так, как это реализовано в Stream: разные виды потоков могут не поддерживать запись или произвольное чтение, но api есть для всего, + набор флагов, позволяющий проверить возможности конкретного потока не проверяя его класс.
Во-первых, вопрос на засыпку: а оно работает под моно в *nix? Судя по коду — нет. А раз так — импорт функции с pinvoke.net/ скопипастить не проблема.
Во-вторых — вы опоздали на… *считает* 4 года.

— Хм. Чукча не читатель. Но каким образом оно совместимо с этим самым импортом виндовой API-функции, написанной под .NET?
1) На windows моно использует системную gdiplus.dll
2) На *nix hDC ненастоящий и является как раз контекстом Cairo. BitBlt через dllmap направляется на libgdiplus.so, где и происходит эта обработка. Этот персонаж сей патч очень долго продвигал в апстрим (костыль для какой-то проприетарщины).
Я боюсь, что это костыль для очень большого числа софта. stackoverflow просто наполнен советами использовать bitblt для копирования части контекста.
Полностью согласен.
В GDIPlus нельзя элементарно нарисовать точку, нельзя стереть участок картинки, совсем,
как можно было создать такую ограниченную графическую библиотеку?
В GDIPlus нельзя элементарно нарисовать точку
Строго говоря отсутствие PSet призвано сократить количество говнокода, таким образом работающего с битмапом попиксельно. Если очень хочется — сделайте себе extension-метод, который заполняет прямоугольник единичного размера.
нельзя стереть участок картинки, совсем

Документацию вы не читали, совсем.
g.CompositingMode = CompositingMode.SourceCopy;    
g.FillRectangle(Brushes.Transparent,x,y,width,height);
Он реализует какие-нибудь серьёзные парадигмы в плане реализации интерфейса (типа MVVM, MVC, шаблоны из WPF, HTML+CSS, сигналы+слоты Qt, универсальные виджеты KDE Plasma и пр.)? Есть какая-нибудь крутая фишка? Или это просто примитивный многоплатформенный WinForms?
сигналы+слоты Qt
Зачем они вам в языке, поддерживающем события?
типа MVVM, MVC
Model-View-Presenter и Model-View-Presenter-ViewModel вполне успешно применимы на тех же Windows Forms, DataBinginds у контролов вполне хватает для привязки к свойствам модельки, поддерживающей INotifyPropertyChanged. Зачем вам для этого дополнительная поддержка со стороны тулкита, мне не особо ясно.
Крутая фишка — это native look&feel на Windows, Linux и Mac OS, с поддержкой родных диалоговых окон, системных кастомизаций и т.д. Выглядит и пахнет он в точности как Gtk#, даже немного лучше — сделаны нормальные обертки для сложных виджетов вроде ListView/TreeView. MVVM/MVC/шаблоны — это то, что можно автоматизировать, используя существующий код Xwt.
Я не увидел — bindings есть/будут/нет?
Нет, сейчас их нету. Биндинги — это инфраструктура WPF, которой в Mono вообще нет, или есть в зачаточном состоянии. Эта инфраструктура могла бы появится в рамках Moonlight, но его закрыли. Теперь либо Moonlight переработают в Xwt, либо сделают свои велосипеды. В любом случае рано или поздно они появятся и в Gtk.
Их не стали копировать, потому что их код просто ужасен, хуже даже чем винапи. Так что правильно сделали.
MonoDevelop 4 — это тот, который Xamarin Studio?
Только что закончил проект на .NET под Win / WPF + Mac / MonoMac-Cocoa. Эта штука спасла бы меня, а так пришлось писать отдельные фронтэнды :(
Думаю, она еще слишком сырая, чтобы на ней делать проекты уже сейчас.
Если Xamarin действительно на ней написан, то должно быть уже вполне юзабельно.
Насколько мне известно, MonoDevelop(Xamarin Studio) пока не завершили полный переход на XWT. На данный момент меню(приложения и контекстное), Android дизайнер и iOS дизайнер(в альфе), а так же файловые диалоги уже реализованы через XWT. Часть остается на gtk с тюнингом от Xamarin.
Фиговина любопытная, и определённо есть, где её применить. Однако в рамках этой штуки вряд ли удастся реализиовать реально сложный интерфейс, потому что она будет наибольшим общим делителем. Вообще, в .NET так делать не принято: исторически сложился подход, что для каждой среды свой родной слой UI. Кода больше, разумеется, но результат того стоит.

Что получается в противном случае — прекрасно видно на примере Java: десктопные приложения работают на любой оси, но выглядят одинаково чужеродно абсолютно везде. В результате для десктопной разработки джава популярной не стала. (Не в курсе, что там с JavaFX происходит, и насколько он выглядит родным на всех поддерживаемых осях. Если кто знает, просвятите.)
Пример не очень, в отличие от Java, здесь вроде как везде родные компоненты ОС в конечном итоге
Мне с трудом верится, что удастся сделать полноценный UI фреймворк, полностью оставаясь в рамках наибольшего общего делителя. Это значит, что при добавлении сложных фич будет имитация поведения одного фреймворка костылями в другом. Ну или XWT будет настолько примитивен, что дальше чекбоксов и кнопок он недалеко уйдёт, что тоже не очень вдохновляющий вариант развития событий.
Последний вариант, на мой взгляд, наиболее благополучен. Многим разработчикам не нужны особые фичи UI, а кроссплатформенность нужна. Кроме того существование своеобразного стандарта на контролы подстегнет разработчиков к созданию аналогичных контролов на разных платформах, а там и сложные контролы могут появится.
По идее большая часть контролов во всех оконных тулкитах представляет из себя именно базовый набор, поверх которых идут различного рода layout-ы для удобства их расположения… Остальные вещи по сути уже не входят в базовый набор виджетов ОС, а реализуются на имеющихся средствах тулкита, что Xwt тоже позволяет сделать. В принципе, если какой-то виджет для ОС является уникальным, ничто не мешает сделать реализацию средствами Xwt, которая будет использоваться в других ОС.
Вообще-то в Java есть и то и другое. В начале был создан кросплатформный фреймворк AWT (Abstract Window Toolkit), построенный на родных компонентах системы, он был быстр, выглядел как родной, но был сложен и из-за кроплатформности содержал только те компоненты, которые были во всех ОС. А это значит он был довольно ограничен и неповоротлив. Тогда решили удариться в другу крайность и создали SWING. Он позволял делать безумную кастомизацию, но по всей видимости этим больше злоупотребляли, чем пользовались во благо. SWING может выглядеть как «родной», под виндой, но только если этого захочет разработчик. Под линуксом и маком с этим есть проблемы, правда не значительные.

Уровень кастомизации SWING приложений просто не имеет границ, однако, как было замечено, не популярность java на десктопах практически закопало развитие этого фреймворка. Возможно в этом есть резон так как полная прорисовка компонент занимало много ресурсов, и не всегда это было оправданно. По началу были реальные проблемы с производительность конкретно у этого фреймворка. Сейчас, когда прорисовка компонент происходит средствами графических ускорителей и нет дефицита памяти это уже не играет роли. Но уже было принято решение делать JavaFX, а SWING оставить в покое.

Учитывая большую популярность .NET на десктопах вполне возможно, что этот проект не повторит участи SWING.
Xamarin Studio — собсна тот солжнейший пример, который работает :)
Язык разметки планируется? Как будет вызываться OnDraw? В retained режиме или каждый раз для перерисовки содержимого?
Язык разметки планируется, и это может быть как Glade, так и XAML. Неясно, по какому пути пойдут разработчики. OnDraw вызываться не будет, потому что никакой отрисовки в библиотеке нет — только форвардинг на соответствующие интерфейсы существующих тулкитов. Для Canvas OnDraw вызывается каждый раз.
Есть ещё такой проект от независимого разработчика: github.com/picoe/Eto/

+поддерживается также WIndows Forms
-так как он пишет его один, то неизвестно как проект будет развиваться в дальнейшем.
Sign up to leave a comment.

Articles