Pull to refresh

Comments 87

Пытался недавно что-то такое запилить на С++/Qt, но о композитинге вспомнил только после того как увидел результат. При отключенном композитинге (gnome 2, winxp, old mac) оно просто не работало(. Может кто знает кроссплатформенное решение этой проблемы для Qt?
Просто установка Qt::WA_TranslucentBackground и рисование на виджете APNG не помогает?
только на системах с композитингом.
Не давно игрался с попиксельной прозрачностью в java 7. Выяснил досадное ограничение — она не работает, если у окна есть заголовок. При этом на стандартном L&F она при этом работает. Пришлось оставить его :(.

Если обмануть систему и включить прозрачность при включенном заголовке, то он отображается один раз, а потом исчезает.
можно отключить стандартные декорации ОС, но при этом заголовок пусть отрисует сам L&F
Видимо далеко не каждый L&F это поддерживает. Надо будет попробовать с нестандартными L&F.
А вам нужно, чтобы работало при любом L&F? Кажется, прозрачность окна — это забота L&F. Ставьте любой из симпатичных, который поддерживает это. Кажется, старый добрый свинговский нормально смотрится.
А как насчёт сглаживания границ?
Хороший вопрос. Применительно к Java я пока не нашел инфы. Думаю, на первых порах можно изменить критерий принадлежности прозрачных пикселей будущему окну (в методе contour), и подать соотв. картинку.
интересно, с контролами такой же фокус прокатывает?
Данная возможность уже достаточно давно доступна, но, увы, на момент JDK 1.6 Update 25 работала только под Mac OS / Windows — под линухами косячила дико, сбивая отрисовку внутриоконных компонентов или вовсе всё вешало.

Сейчас вот хочу проверить как с этим в JDK 1.7

И, кстати, для той задачи, которую обрисовали Вы есть более простое решение без каких-либо просчётов границ картинки и, что важнее, сосглаженным краем:
public class TransparentImageDialog
{
  public static void main ( String[] args )
  {
    final ImageIcon ii = new ImageIcon ( "C:\\Users\\mgarin\\Desktop\\girl.png" );

    JFrame frame = new JFrame ();

    frame.getContentPane ().add ( new JComponent()
    {
      protected void paintComponent ( Graphics g )
      {
        Graphics2D g2d = ( Graphics2D ) g;
        g2d.setComposite ( AlphaComposite.getInstance ( AlphaComposite.SRC_OVER, 0.5f ) );
        g2d.drawImage ( ii.getImage (), 0, 0, null );
      }
    } );

    frame.setUndecorated ( true );
    frame.setSize ( ii.getIconWidth (), ii.getIconHeight () );
    AWTUtilities.setWindowOpaque ( frame, false );
    frame.setLocation ( 400, 300 );
    frame.setVisible ( true );
  }
}


Скрин:
hostingkartinok.com/image/01201108/0f42214ca83327d939a34088a66924c2.png
По факту — возможность задавать форму окна бесполезна, если Вы только не собираетесь сделать из окна что-то прямоугольное, иначе — не будет никакого алиасинга на границе. Да и геморроя с формами больше на порядок.

Проще задать полную прозрачность и далее, в нужных местах разместить компоненты/графику/что угодно.
События будут отлавливаться только для тех областей окна, на которых хоть что-то есть.
Т.е. по факту — ровно то же, что и задание формы окну, только более умное.
Спасибо. Не подумал бы, что композит через прозрачность так же делает не только прозрачность. Забавно = )
А на линухах (проверил на openSuSe11.4) почему-то до сих пор при движении картинки заметна перерисовка всего обрамляющего прямоугольника. К Макам доступа не имею, не могу сказать, как там оно.
Я на виртуалках проверял (XP/Vista/7/Mac OS X SL/Ubuntu/Debian/ArchLinux/CentOS) — на последних везде были одинаковые траблы с отрисовкой.

Перерисовка всего прямоугольника окна, о которых говорите Вы, ещё не так страшна. По крайней мере сама суть не теряется в убитом интерфейсе.

Сейчас вод доставил Ubuntu 11.04 — посмотрю как на ней будут дела с JDK 1.6 Update 26 и JDK7.
Надеюсь хотя бы на 7ке оно будет корректно работать :)
Скорее всего, дело в самих виртуалках, т.к. поддержка зависит еще и от устройства вывода.
Вряд ли, так как, скажем Ubuntu у нас в оффисе используется на доброй половине машин и там я также пробовал, так как были подозрения на косяки вывода — результат 1 в 1. Те же самые проблемы. Так что более похоже на проблемы в JDK более старых версий.
Позже проверю Ваш вариант на своей сюзе, но вот мой одинаково работал под сюзей, что на 6, что на 7, а на 7 проверял и способ для 6 тоже — всё одинаково.
Я сейчас как раз попробую на Ubuntu, надо только доставить всё необходимое для тестов.
Попробовал. Фейл: на моей сюзе так и не нашлось нужной конфигурации (GraphicsConfiguration), что бы Ваш вариант заработал. Точнее, нашлась какая-то, на которой окошко нарисовалось, но — с чёрным непрозрачным фоном :(
Или я что-то сделал не так?..
Нет, всё так. Именно это и происходит.
Собственно, была надежда что с 7ым JDK они таки это реализовали под Linux.
М, Вы же под 7ой пробовали или всё ещё под 6ой?
Увы, и там и там…
Граната у него не той системы! (ц)
У этого подхода есть один недостаток связанный с попиксельной отрисовкой — текст в JLabel с включеным сглаживанием на таком окне будет выглядеть чуть хуже чем в обычном JFrame.
Вопрос в том, зачем Вам понадобится JLabel или какой-либо другой сглаженный текст на таком окне без фона? Он ведь будет попросту нечитабелен в большинстве случаев…
На таком действительно не нужен. Думаю об этой проблеме надо знать если захочется сделать custom-окно с полями ввода и лейбами используя описанный подход. Например аккуратное окошко, со скругленными полями и мягкой тенью.
Хм, что-то меня всё же смущает, сейчас перепроверю свою теорию…
Честно говоря, не заметил никакой разницы между текстом на обычном окне и на таком.

Единственный нюанс — необходимо прописать включение антиалиасинга текста в UIManager константу или же в коде при отрисовке:
public class TransparentImageDialog
{
  public static void main ( String[] args )
  {
    final ImageIcon ii =
        new ImageIcon ( TransparentImageDialog.class.getResource ( "icons/girl.png" ) );

    JFrame frame = new JFrame ();

    frame.getContentPane ().add ( new JLabel( "Test text", JLabel.CENTER )
    {
      {
        setForeground ( Color.BLACK );

        MoveAdapter moveAdapter = new MoveAdapter ();
        addMouseListener ( moveAdapter );
        addMouseMotionListener ( moveAdapter );
      }

      protected void paintComponent ( Graphics g )
      {
        Graphics2D g2d = ( Graphics2D ) g;

        Composite comp = g2d.getComposite ();
        g2d.setComposite ( AlphaComposite.getInstance ( AlphaComposite.SRC_OVER, 0.5f ) );
        g2d.drawImage ( ii.getImage (), 0, 0, null );
        g2d.setComposite ( comp );

        g2d.setRenderingHint ( RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON );
        super.paintComponent ( g );
      }
    } );

    frame.setUndecorated ( true );
    frame.setSize ( ii.getIconWidth (), ii.getIconHeight () );
    AWTUtilities.setWindowOpaque ( frame, false );
    frame.setLocation ( 400, 300 );
    frame.setVisible ( true );
  }

  private static class MoveAdapter extends MouseAdapter
  {
    private boolean dragging = false;
    private int prevX = -1;
    private int prevY = -1;

    public void mousePressed ( MouseEvent e )
    {
      if ( SwingUtilities.isLeftMouseButton ( e ) )
      {
        dragging = true;
      }
      prevX = e.getXOnScreen ();
      prevY = e.getYOnScreen ();
    }

    public void mouseDragged ( MouseEvent e )
    {
      if ( prevX != -1 && prevY != -1 && dragging )
      {
        Window w = SwingUtilities.getWindowAncestor ( e.getComponent () );
        if ( w != null && w.isShowing () )
        {
          Rectangle rect = w.getBounds ();
          w.setBounds ( rect.x + ( e.getXOnScreen () - prevX ),
              rect.y + ( e.getYOnScreen () - prevY ), rect.width, rect.height );
        }
      }
      prevX = e.getXOnScreen ();
      prevY = e.getYOnScreen ();
    }

    public void mouseReleased ( MouseEvent e )
    {
      dragging = false;
    }
  }
}

Главное — собственно использовать антиалиасинг:
g2d.setRenderingHint ( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON );

Это общий вариант. Можно также и конкретно под текст:
g2d.setRenderingHint ( RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON );
Там также есть несколько вариантов антиалиасинга текста.

Вот кстати ещё один вариант как включить его для всего приложения:
UIManager.put ( SwingUtilities2.AA_TEXT_PROPERTY_KEY,
SwingUtilities2.AATextInfo.getAATextInfo ( true ) );
Немного данных, где эта проблема вылезла: Windows 7, JDK 1.6.0_22, включен Windows Look & Feel. И еще, это воспроизводилось только на Windows, на Mac OS X 10.6+ никакой разницы нет.
А если попробовать на Windows без включённого Windows Look & Feel?
Просто вот выдержка из WindowsLookAndFeel:
Object aaTextInfo = SwingUtilities2.AATextInfo.getAATextInfo(true);
table.put(SwingUtilities2.AA_TEXT_PROPERTY_KEY, aaTextInfo);
this.aaSettings = new FontDesktopProperty(SunToolkit.DESKTOPFONTHINTS);

Что содержится в SunToolkit.DESKTOPFONTHINTS одному богу известно :)
Без WindowsLookAndFeel разница незаметна. Похоже причина действительно в Look And Feel.
Собственно, LookAndFeel выбирает предпочтительный антиалиасинг (можете посмотреть список — RenderingHints.VALUE_TEXT_ANTIALIAS_*).
Некоторые из них, если попробовать установить вручную и посмотреть результат, весьма неопрятно сглаживают текст. Вероятно это у Вас и наблюдается.
Интересно посмотреть сколько кода займет вот такой пример на WPF,
чтобы Ваши слова не были «пустым звуком» :)
Честно говоря, пробовать лениво, но в голову приходят следующие варианты:
если вы хотите именно из битмапа — ставите у окна OpacityMask, WindowStyle = None и ничего особо писать даже не надо поидее
Если из вектора — в Expression Design рисуете то, что вам надо, жмете CopyXaml и вуаля
Просто если извлечь идейное содержимое из моего примера — это 2 важных строки:
frame.setUndecorated ( true );
AWTUtilities.setWindowOpaque ( frame, false );

Далее всё что Вы поместите на окно будет «висеть в воздухе» и события мыши будут работать только над отрисованными областями. Даже не нужно себя напрягать никакими мыслями на тему «А какую форму мне задать, чтобы вот эта округлая панель влезла вот сюда...»
Та же штука и у меня, только в моем случае можно отрисовывать такое окно не только из битмапа, но еще и из вектора (что довольно актуально в сегодняшний день обилия мониторов и ТВ разных размеров, с разными разрешениями), да и еще с возможностью ресайза, анимациями и т.д.
При том все это будет отрисовываться с аппаратным ускорением.
Ок?
Я, конечно, не буду отрицать возможность использования в WPF векторной графики, но в данном случае это немного не к месту. Не представляю себе случай, когда мне может понадобиться векторная графика для оформления окна, честное слово (по крайней мере для большей части) :)

Остальные компоненты и так сами по себе «резиновые», если они так реализованы и могут спокойно изменять свой размер в соотношении с размером окна.

Возможность аппаратного ускорения (не уверен на 100%) вроде как присутствует на низком, когда доходит до самого рисования.
Ну вы попробуйте нарисовать, скажем, хотя бы тексбокс с закругленными углами и кастомным анимированным фокусом средствами своей платформы и сравните с тем, как это делается в WPF. Тогда наверняка прочувствуете преимущества векторной отрисовки.
Я уж даже не говорю об преимуществах лейаут контролов, которые предлагает WPF, над обычной попиксельной версткой.
Для некоторых компонентов векторная графика действительно более удобна, чем попиксельная вёрстка, тем более что можно разделить дизайн с кодом и не утруждать разработчиков лишними задачами. Впрочем у данного варианта также есть подводные камни.

Насчёт лэйаутов — они в Java есть ещё с самой древней версии, так что тут скорее WPF догоняет, чем перегоняет (как кстати с GC) ;)
Я вовсе не представляю себе как делать нормальные приложения без лэйаут-контролов.
Представьте себе, многие до сих пор рисуют гуй визуально, в пикселях, разумеется.
А сборщик мусора еще в лиспе был
Ну, учитывая что под это есть допотопные визуальные редакторы — представляю :)
До сих пор нередко встречаются «динозавры» со статичным интерфейсом.
Да я бы сказал, не для некоторых, я для всех. Какие тут подводные камни — поясните?

Лэйауты в Java лично мне показались куда менее удачными и понятными, чем лэйауты WPF. Тем более, разметку можно делать декларативно. Это просто удобнее в разы.
Лэйауты в Java действительно оставляют желать лучшего — но первый блин, как говорится, всегда комом.
Впрочем, привыкнув, можно интерфейс любой сложности сделать на 2х-3х типах лэйаутов.

Для привередливых есть MiG Layout
Кстати спасибо за линк, давно его искал :)
Всё никак не мог вспомнить где я видел достойный лэйаут для различных форм.
Подводные камни в точной (попиксельной) отрисовке компонентов.
Так как вектор в итоге так или иначе перегоняется в попиксельную отрисовку (как минимум для вывода на экран, но мне всё же кажется что раньше) — скейлинг делает своё грязное дело и иногда выходит не то, что ожидалось.

Насчёт лэйаутов — могу ровно то же сказать о варианте реализованном в WPF.
Обычный холиварный вопрос взглядов.
Холивара не нужно — если что-то не устраивает, всегда можно написать собственный лэйаут, в т.ч. портировать из WPF. Благо это совсем не сложно.
Кстати насчёт написания подобных вещей — я уже где-то видел библиотеку для Java, реализующую подобную возможность. Впрочем, мне она не приглянулась :(
С вводом данного функционала в JDK7 — да, это полностью кроссплатформенный код.
Упс, немного поспешил :)
Кстати, насчёт WPF мне тоже интересно, полностью ли кросплатформенный будет код
Разумеется нет, WPF пока не портировался под что-то отличное от Windows.
Но есть Silverlight.
Да, только это уже немного в другую степь.
И если уж говорить о Silverlight — есть там подобные возможности для десктоп-приложений?
И насколько сам Silverlight переносим? Недавно где-то видел крики о проблемах на Linux…
Silverlight Out of browser, работает на Винде и на Маке. На линукс, честно говоря, как-то пофиг мне лично. Есть там Moonlight, вроде даже работает.
Вам может и пофиг, зато другим пользователям нет. Кроссплатформенность на данный момент достаточно значимый фактор.

Да и Silverlight — другая ниша с другими возможностями, а мы, всё же, обсуждаем здесь Desktop-возможности.

Кстати, скорость работы Silverlight приложений не может не вгонять в уныние даже на шустрых машинах. Древние как мир Java-апплеты и то пошустрее работают…
Кроссплатформенность на Linux мало кому нужна. Почти никто не хочет ей пользоваться, хоть она и есть.
В противном случае — где эти тысячи превосходных кросс-платформенных приложений для Linux? Почему никто не спешит переносить их туда (хотя, чего там переносить — они же кроссплатформенные).
Ну да ладно, это оффтопик, не будем разжигать, как говорится :)
В особенности это относится и к кроссплатформенности на Windows: З
Для многих до сих пор Операционная Система — это Windows.

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

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

Тот же Photoshop как-то не спешит :)

Но как минимум по тому что я вижу у нас и во многих фирмах, которые сотрудничают с нами — планомерно идёт переход на Linux. Конечно, всегда будут и машины с той же виндой и «ценители» маков, но факта это не меняет :)
Да и последние версии нашего ПО достаточно часто используют под Linux'ами (и не только серверную часть, но и «толстые клиенты» и другие десктопные приложения).

Хотя бы поэтому я бы не стал так быстро отмахиваться от Linux.
Окошко неправильной формы в окошке броузера прямоугольной формы? Звучит.
Похоже или нет — сильно сомневаюсь что Вы будете использовать Silverlight под десктопное приложение, так же как и Java-апплет для создания сайта…

А вообще судя по разным ресурсам — возможно установить из браузера установить к себе локально приложение и получать на него обновления. Что-то аля Adobe air.
Т.е. в общем — примерно то же. Не уверен только насчёт обновлений…
В данный момент из мультимедиа технологий в сфере моего внимания находится JavaFX 2, который еще бета. Правда, сразу споткнулся о то, что туториалы, видимо, для 1.0 не работают в 2.0 ))
Мне лично JavaFX пришёлся не по вкусу. Может они конечно его ещё изменят и улучшат, но сомневаюсь что я переберусь на него, даже для какого-либо отдельного проекта. Имхо на поиграться разок и бросить.

Да и приложений на нём — одни демки и «Hello World!».
Создаётся ещё большее ощущение бесполезности…
Почему Вы сомневаетесь в перспективах?
Я вот, наоборот, вижу большой потенциал для реализации графических эффектов подобно Flash — как для десктопа, так и в броузерных Java-аппликациях
В этом плане это конечно хорошо, только меня расстраивает, что в Java FX есть и обновлённый медиа-плеер и какой-никакой веб-браузер, некие подвиги в сторону анимации и прочие «рюшки», а дескоп Java всё ещё «сидит на древних руинах».

А это как раз те вещи, которые банально закрывают проход в огромный спектр всевозможных десктоп приложений на Java.

Да и с самим Swing'ом в последние годы никаких глобальных изменений не происходило, хотя там есть куда двигаться. В общем создаётся ощущение, что они просто решили отделаться от Swing.

А на JavaFX я не стал бы писать десктопное приложение, также как и на Silverlight, Adobe Air и прочих подобных штуках. По крайней мере крупное точно.

Кстати где-то я видел примеры по использования JavaFX в Swing, интересно с текущей (2ой) и последующими версиями такой трюк прокатит, и насколько он неудобен в использовании?..
Просто они сделали эти рюшки в качестве отдельного проекта, вроде как с Java3D. Их можно понять — не захотели обвешивать SE
Ну Java3D то можно использовать вкупе с тем же Swing, а JavaFX…
Хм, тогда надо будет получше поискать на эту тему, так как никаких толковых рабочих примеров я так и не нашёл.
Но если это действительно так, то моё мнение резко изменится :)
Зачем это нужно, если все это уже есть в Silverlight? Ждать, пока JavaFX допилят до сопоставимого уровня — нет никакого смысла.
Silverlight готовится откинуть копыта. Сам мелкософт заявил, что он теперь плюет на свой сребросвет и ставки делают на HTML5
Это ещё один повод «в копилку»
Господи, я уж думал на Хабре все успели прочитать опровержения на этот бред. Ан нет.
Сударь, ни коим образом МС не забивает на Silverlight, а готовит к релизу пятую версию. Просто следует четко понимать, что для основных задач веба будет использоваться HTML5, а ниша Сильверлайта — корпоративные приложения, клиенты облачных сервисов под Windows и MacOs, приложения под Windows Phone, системы видеотрансляций через веб и т.д. Разговоры об отказе МС от Silverlight — дезинформация, пущенная в ряде статеек в момент появления слухов о Windows 8.
Сударь, вы будто пол года в интернете отсутствовали, ей-богу
Ну, скажем так, если то что уже разрабатывается — написано на Java и особенности языка давно известны, нет смысла переходить на Silverlight, у которого тем более, опять же, проблемы с кроссплатформенностью ;)
И особенно учитывая, что под Java написана ещё одна аналогичная технология. В этом плане я согласен с Lure_of_Chaos — у технологии есть все шансы.

Да и если на данный момент не устраивает JavaFX — чем стандартные Java-апплеты хуже?

Они вмещают в себя все возможности полноценных Java-приложений и легко интегрируются в любом месте сайта. Да и перенести обычное Java-приложение в апплет не составляет больших проблем. Систему они также не сильнее чем Silverlight.
У Сильверлайта векторная отрисовка, аппаратное ускорение и XNA-вставки с поддержкой шейдеров и т.д. У Жабы этого либо нет, либо тащится далеко позади. И все разговоры о кроссплатформенности уже не нужны.
В базовой комплектации действительно нет и весьма спорно, насколько бы это было бы нужно и востребованно.
Кстати интересно было бы посмотреть на статистику использования векторной отрисовки по различным крупным и серьёзным desktop-проектам (всякие гаражные Paint'ы и HelloWorld'ы на WPF не интересуют, ну серьёзно).

А все разговоры о «не нужной кроссплатформенности» точно так же «уже» не нужны :)
Всегда удобно сказать «у нас этого нет но и не нужно!». И отбиваться от разумных доводов всё той же фразой. Но факта это не меняет.
Смотреть надо не по крупным десктоп-проектам. Они тащат за собой кучу легаси кода и полностью переписывать Фотошоп, например, мало кто решится. На это нужны веские причины. Смотреть надо по энтерпрайзу, где такие вещи внедряются местами быстрее на новых проектах.
Вот мы сейчас, например, делаем на Silverlight систему визуализации технологического процесса на одном из крупнейших в стране заводов.
Что касается десктопа — там я помню переход Автокада на WPF в 11й версии, еще что-то было. Не суть важно.
А кроссплатформенность действительно нужна чаще всего только в рамках одной экосистемы. Все остальное — чаще всего мелкие проекты, борящиеся со следствием корявой ит-инфраструктуры, либо опять же, десктопная мелочь и всерьез это рассматривать просто нет никакого смысла.
Кроссплатформенность весьма востребованная вещь, что бы Вы не говорили. Просто проблема (точнее не проблема, а менее крупный спектр кросс-платформенных приложений) кроется как раз в том, что крупные проекты, как Вы и сказали, без веских причин никто переписывать не будет. Да вобщем то и различные мелкие софтины написанные только под Windows или Mac также переписывают без особого энтузиазма.

Если смотреть на более современные выходящие в последние годы приложения — достаточно большой их контингент выходит кроссплатформенным (не важно даже, будь то на основе Java или Air или какой другой технологии, раз уж речь идёт о востребованности).

Аналогично множество проектов «переезжает в онлайн» в связи с тем что поддерживать «зоопарк» браузеров всё же проще, чем поддерживать аналогичный «зоопарк» операционных систем. Конечно, там есть и другие факторы, влияющие на подобное решение.

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

Смотря что Вы подразумеваете под экосистемой.
А насчёт кривой ИТ-инфраструктуры — я бы не стал всё сводить к этому. Вы считаете, что фирмы должны пользоваться одной ОС и точка, и что любой «зоопарк» систем в фирме это следствие кривости рук (не суть важно кого)? Всё же есть абсолютно разные области, и потребности одной фирмы могут быть весьма разнообразны, из-за чего в итоге подобный «зоопарк» просто необходим. Да и есть множество других факторов влияющих на ситуацию.
отлично нагуглил барышню для задачи!
Sign up to leave a comment.

Articles