Окна «неправильной» формы, Java 6 & 7 ed

Симпотичная?

По следам бременских музыкантов


Как, наверное, многие помнят, в прошлом веке (еще во времена Windows 2000), было модно создавать всяческие splash-экраны и миниаппликации в окнах непрямоугольной формы (как и необычные элементы управления).
Писались эти понты на С\С++ с применением WinAPI с использованием т.н. регионов. Дело это было не таким простым, поскольку приходилось не только спотыкаться о косяки и Windows и языка, но и просчет полигонов для отрисовки тоже отпугивал. Поэтому, «нарисовав» одно-два округлых окошка, я отложил эту тему в долгий ящик.
И вот в этот понедельник промелькнула статья «Окна «неправильной» формы», снова обратившая моё внимание к этой теме. Ожидая узнать, что в .NET для этих целей реализованы функции-обёртки WinAPI, был разочарован, увидев описания внешних функций. И тут я, как программист в основном на Java, вспомнил, что, тогда ещё Sun, обещал ввести функции для отрисовки окна произвольной формы.



Чашечка кофе


Ну что ж, какие возможности предоставил нам Sun/Oracle?
  1. JNI/JNA:
    • зависит от платформы
    • писать дополнительный нативный код для каждой системы
  2. Эмуляция прозрачности путем прорисовки фона:
    • окно всё равно кликабельно
    • медленная прорисовка
    • заметны задержки при перемещении окна
    • не реагирует оперативно на изменение фона (особенно, беда с анимацией на фоне)
  3. Класс com.sun.awt.AWTUtilities:
    • доступен с версии 1.6_10 только в Sun VM
    • внутренний класс, поддержка которого не гарантируется
  4. Публичные методы классов java.awt.Window, java.awt.GraphicsEnvironment, java.awt.GraphicsConfiguration:
    • доступен с версии 1.7.0, ура!
    • что и досадно: как насчет OpenJDK?

На данный момент, наиболее приемлемым является предпоследний способ. Итак, задача у нас такая: Нарисовать полупрозрачное окно сложной непрямоугольной формы (на основе изображения), с фоновой картинкой, с возможностью перемещать окно, изменять размеры окна, размещать любые элементы управления (как стандартные, так и тоже произвольной формы)

Регионы, области, края


Покурив, покурив мануалы и туториалы, стало ясно, что за форму окна, как и любые геометрические фигуры, отвечают классы, реализующие интерфейс java.awt.Shape. Т.е., если нам удастся сгенерировать замкнутый Shape по нашей картинке, аналогично региону в Windows, задача будет решена.
Однако, по сложившейся кроссплатформенной традиции, нужно убедиться, что сама ОС умеет рисовать такие окна. Используя AWTUtilities, пишем, например, такой код:
if((com.sun.awt.AWTUtilities.isTranslucencySupported
		(com.sun.awt.AWTUtilities.Translucency.PERPIXEL_TRANSLUCENT))
	&& (com.sun.awt.AWTUtilities.isTranslucencyCapable
(GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration()))) {
	// необходимый код
}

PERPIXEL_TRANSLUCENT означает, что графическая система способна выводить не только целиком прозрачные окна, но и, грубо говоря, «иметь дырки» в окошках, а также, что текущее устройство вообще умеет работать с прозрачностью (увы, Windows 98 в пролёте) Можно, конечно, и не проверять, но тогда при попытке использовать эти функции вылетит соответствующее исключение.
Ещё, может статься, что в системе установлена старая Java и никаких AWTUtilities не будет вообще — тогда можно воспользоваться вспомогательным классом AWTUtilitiesWrapper из этой статьи, который работает с AWTUtilities через отражение. Я не стал его использовать, поскольку достаточна вероятность, что у всех обновлённая Java, а код становится более непонятным. Будем работать напрямую с AWTUtilities:
  1. Перед тем, как показывать окошко, уберём полосу заголовка (отключим стандартные декорации ОС):
    this.setUndecorated(true);
  2. Попросим возможность сделать окно полупрозрачным:
    com.sun.awt.AWTUtilities.setWindowOpaque(this, false);
  3. Установим степень прозрачности окна:
    com.sun.awt.AWTUtilities.setWindowOpacity(this, .75);

    Значение второго аргумента должно находиться в пределах 0 — 1 (в нашем
    случае 75%).
    Можно даже сделать окно абсолютно прозрачным, но оно будет реагировать на
    нажатия
  4. сконструировав нужный Shape, установим нужную нам форму для окна:
    com.sun.awt.AWTUtilities.setWindowShape(this, s);

    Теперь, магическим образом, всё, что находится за пределами нашей фигуры, не
    будет не только не рисоваться, но и не реагировать на нажатия (вспомним
    подход из книги "Swing Hacks")
  5. Раз мы лишились стандартной полоски заголовка, но хотим перемещать окно,
    добавим возможность перемещать окно щелчком в любой части окна (для этого я
    использовал класс MoveMouseListener из той же книги)
  6. Добавим кнопку «Закрыть» в окно, тоже нестандартную

Вот это формы!


Следующая задача: из любой картинки с прозрачным фоном, хорошо отделённого от переднего плана, составить её замкнутый контур. Для своих извращённых пыток я нагуглил вот такую прелестную барышню:
Барышня не моя, это только пример
Вначале я подумывал реализовать метод выпуклой оболочки (convex hull), но впоследствии отказался — наша барышня не только очень даже выпуклая, но местами и впуклая. На иное моих глупых мозгов в вечерний период не хватило, кроме как использовать решение «в лоб»: пробежаться по пикселам, удаляя прозрачные пиксели из начального прямоугольника . Получился такой код:
static Shape contour(final BufferedImage i) {
	final int w = i.getWidth();
	final int h = i.getHeight();
	final Area s = new Area(new Rectangle(w, h));
	final Rectangle r = new Rectangle(0, 0, 1, 1);
	for (r.y = 0; r.y < h; r.y++) {
		System.out.println(r.y + "/" + h);
		for (r.x = 0; r.x < w; r.x++) {
			if ((i.getRGB(r.x, r.y) & 0xFF000000) != 0xFF000000) {
				s.subtract(new Area( r ));
			}
		}
	}
	return s;
}

Прозрачными пикселями здесь считаются и полупрозрачные тоже (т.е. у которых alpha<255) — разумеется, если нужно, можно указать и некое пороговое значение, или даже назначить любой цвет скажем, белый: 0xFFFFFF). Но это неважно, важным оказалось другое — скорость, ведь никто не будет ждать 10 минут при загруженности проца 100%, пока наша Intro соизволит показаться. Да и генерировать форму каждый раз излишне, лучше сохранить где-либо, что бы потом быстро загрузить и показать.

R Tape loading error


Java имеет встроенные средства для сохранения и загрузки любых примитивов и объектов, которые реализуют интерфейс ava.io.Serializable, а также рекурсивно сериализуемы. Но вот беда: ни Shape, ни один из его реализующих классов не являются сериализуемыми! Довольно долго промучавшись, удалось получить интерфейс java.awt.geom.PathIterator, который позволяет пробежаться по контуру, что бы сохранить его, и класс java.awt.geom.GeneralPath, в который можно записать сохранённый ранее контур. И вот что получилось:
static void save(final Shape s, final DataOutput os) throws IOException {
	final PathIterator pi = s.getPathIterator(null);
	os.writeInt(pi.getWindingRule());
	System.out.println(pi.getWindingRule());
	while (!pi.isDone()) {
		final double[] coords = new double[6];
		final int type = pi.currentSegment(coords);
		os.writeInt(type);
		System.out.println(type);
		for (final double coord : coords) {
			os.writeDouble(coord);
			System.out.println(coord);
		}
		System.out.println("");
		pi.next();
	}
}

Использование интерфейса java.io.DataOutput позволяет сохранить данные куда угодно — я использовал редко встречающийся класс java.io.RandomAccessFile, его реализующий, но можно писать и в java.io.ObjectOutputStream. Можно(и даже лучше) сохранить файл рядом с class-файлами, чтобы потом его можно было бы достать даже из архива с апплетом.
static Shape load(final DataInput is) throws IOException {
	final GeneralPath gp = new GeneralPath(is.readInt());
	final double[] data = new double[6];
	CYC: while (true) {
		final int type = is.readInt();
		for (int i = 0; i < data.length; i++) {
			data[i] = is.readDouble();
		}
		switch (type) {
			case PathIterator.SEG_MOVETO:
				gp.moveTo(data[0], data[1]);
			break;
			case PathIterator.SEG_LINETO:
				gp.lineTo(data[0], data[1]);
			break;
			case PathIterator.SEG_QUADTO:
				gp.quadTo(data[0], data[1], data[2], data[3]);
			break;
			case PathIterator.SEG_CUBICTO:
				gp.curveTo(data[0], data[1], data[2], data[3], data[4], data[5]);
			break;
			case PathIterator.SEG_CLOSE:
			break CYC;
		}
	}
	return gp.createTransformedShape(null);
}

Разумеется, для корректного восстановления необходим правильный файл — для простоты я не провожу никаких проверок, и никакие исключения не обрабатываются (а вообще нужно бы!). Формат файла такой:
  1. Направление обхода контура: по часовой стрелке или против (целое)
  2. Сколько угодно блоков:
    1. Тип кривой (целое)
    2. Опорные точки кривой (массив из 6 дробных)

Дополнительно вполне стандартным образом рисуем фоновую картинку — перегрузкой метода paint(Graphics g), а точнее — paintComponent(Graphics g)

Всё или ничего


Ну если уж мы сами рисуем окно, то для законченности нужно еще нарисовать и собственные элементы управления. Пока ограничусь только кнопкой «Закрыть».
  • Нативные элементы управления SWT:
    • вид зависит от платформы
  • Расширение элементов управления Swing:
    • для каждого элемента писать свой класс
    • затруднительная смена внешнего вида (тем)
  • Написание собственного Look-and-Feel:
    • хлопотно
    • конечно, есть же Synth...
  • Декорирование элементов управления Swing c помощью javax.swing.plaf.LayerUI
    • доступен только с версии 1.7.0 :(

Для демонстрации я пошёл вторым путём:
  • Генерируем картинку и контур точно так же, как и для окна
  • Расширяем класс JButton
    • Делаем прозрачным:
      this.setOpaque(false);
    • Запрещаем прорисовку фона:
      this.setContentAreaFilled(false);
    • Также не будем рисовать ни рамку, ни линию фокуса:
      this.setFocusPainted(false);
      this.setBorderPainted(false);
    • Устанавливаем явные размеры, чтобы никакие менеджеры компоновки
      (LayoutManager) не попортили картинку:
      this.setSize(this.result.size);
      this.setMinimumSize(this.result.size);
      this.setMaximumSize(this.result.size);
  • Замещаем метод paintComponent(Graphics g) для прорисовки картинки
  • Замещаем метод contains(int x, int y) делегируя такому же метода для нашего контура


Finita la comedia


Всё! Делаем завершающие штрихи: Стандартным образом добавляем кнопку в окно и навешиваем на неё обработчик. Запускаем и любуемся:
Симпотичная?
Как и многие свои проекты, храню на xp-dev.com: страница проекта, svn-репозиторий
Там лежат два проекта для Eclipse Helios: Shaped для Java6 и Shaped7 для Java7. Чтобы уменьшить разницу версий, специфичные запросы вынес в методы класса, а вспомогательные функции — в отдельный класс утилит.



Чтиво по теме:


Share post

Comments 87

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

      Если обмануть систему и включить прозрачность при включенном заголовке, то он отображается один раз, а потом исчезает.
        0
        можно отключить стандартные декорации ОС, но при этом заголовок пусть отрисует сам L&F
          0
          Видимо далеко не каждый L&F это поддерживает. Надо будет попробовать с нестандартными L&F.
            0
            А вам нужно, чтобы работало при любом L&F? Кажется, прозрачность окна — это забота L&F. Ставьте любой из симпатичных, который поддерживает это. Кажется, старый добрый свинговский нормально смотрится.
        +2
        А как насчёт сглаживания границ?
          0
          Хороший вопрос. Применительно к Java я пока не нашел инфы. Думаю, на первых порах можно изменить критерий принадлежности прозрачных пикселей будущему окну (в методе contour), и подать соотв. картинку.
            0
            Собственно, описал как сделать отдельным комментарием.
              0
              интересно, с контролами такой же фокус прокатывает?
          +4
          Данная возможность уже достаточно давно доступна, но, увы, на момент 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
            +1
            По факту — возможность задавать форму окна бесполезна, если Вы только не собираетесь сделать из окна что-то прямоугольное, иначе — не будет никакого алиасинга на границе. Да и геморроя с формами больше на порядок.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                                                                      Смотря что Вы подразумеваете под экосистемой.
                                                                      А насчёт кривой ИТ-инфраструктуры — я бы не стал всё сводить к этому. Вы считаете, что фирмы должны пользоваться одной ОС и точка, и что любой «зоопарк» систем в фирме это следствие кривости рук (не суть важно кого)? Всё же есть абсолютно разные области, и потребности одной фирмы могут быть весьма разнообразны, из-за чего в итоге подобный «зоопарк» просто необходим. Да и есть множество других факторов влияющих на ситуацию.
                                      +1
                                      отлично нагуглил барышню для задачи!
                                        0
                                        Старушка Бетти :)
                                        +1
                                        Вот примерно то же самое на SWT: Create non-rectangular shell from an image with transparency.

                                        Only users with full accounts can post comments. Log in, please.