Pull to refresh

Мои первые шаги в SWT: Простенький блокнот со вкладками

Reading time 5 min
Views 22K
На Хабрахабре очень мало статей о SWT, поэтому я постараюсь исправить данное маленькое упущение.

Из данной статьи Вы узнаете:
  • Какова мотивация использовать SWT в отличии от основного конкурента — Swing
  • Основные трудности с которыми я столкнулся при разработке простенького блокнота на связке Java + SWT и Немного кода
  • Каким образом упаковать и распространить свое приложение для нескольких платформ

Если Вас заинтересовало — прошу под кат.

Преамбула


Как известно, Java славится своей кросс-платформенностью (write-once — run anywhere), и к GUI приложениям это тоже относится. Хотя, пожалуй, Java и не самая распространненная платформа для написания GUI приложений. И на то есть ряд причин.

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

Некоторые со мной не согласятся и скажут, что это как раз стиль Java — написанное единожды должно исполняться и выглядеть одинаково на всех платформах. И Swing тому хорошее подтверждение. Конечно же Swing приложение можно кастомизировать с помощью различных тем(Look And Feel) но все равно оно будет чувствоваться и выглядеть не совсем так, как родное.

Хотя ребятам из JetBrains и удалось доказать (по крайней мере мне лично), что Swing приложения могут быть очень-даже дружелюбными, но факт остается фактом — оно начинает со временем тормозить не потому что написано плохо, а именно в силу того, что в качестве GUI фреймворка используется Swing, который с операционными системами дружит несколько хуже чем их нативные компоненты.

SWT как раз подошел с другой стороны к этой проблеме. По большому счету SWT — это тонкая прослойка между Java программистом и нативными API какой-то конкретной операционной ситемы, что несколько наршует идеологию Java. Но, как говорится, правила как раз и существуют для того, что бы их нарушать. Особенно, если это идет на благо. И это на мой взгляд является основной мотивацией, почему стоит обратить внимание на SWT.

Первые шаги


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

Задуммка была весьма проста:
Я хотел сделать подобие классического блокнота, того что мы наблюдаем под Windows. Только со вкладками.

Забегая вперед скажу, что я это не полностью реализовал свою идею — отстутствуют возможности посылать документ принтеру на печать, возможность менять шрифт, поиск по документу. Но, то что получилось, позволило почувствовать «вкус SWT», который окалазся довольно-таки приятным.

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

Точка входа в приложение, это(Bootstrap.java):

    final Display display = new Display();
	final Shell shell = new Shell(display);
	final DocumentAndTabManager documentAndTabManager = new DocumentAndTabManager(shell);
	final TextEditor textEditor = new TextEditor(shell, documentAndTabManager);
	textEditor.init();
	textEditor.run();


Что мы здесь сделали:
  • Создали дисплей(Display), сказали что бы оболочка(Shell) использовала наш дисплей. (На мой взгляд SWT имеет достаточно стройную идеологию — приложению не следует иметь более чем один объект-дисплей.)
  • Оболочка(Shell) — то, где будет проходить основное действие. Если провести аналогию со Swing — то можно сказать, что это в какой-то мере аналог JPanel.
  • Сделали инъекцию из оболочки нашему мэнеджеру документов и редактору текста, что бы они не забывались, зачем они нужны и кто у них хозяин.


Проинициализировали оболочку (TextEditor.java):


    shell.setLayout(new FillLayout());

	//И поставили поставили меню оболочке(окошку):

	shell.setMenuBar(createAndSetUpMenu());


В кратце процесс создания меню:

    //Говорим что у нас есть такое-то меню, чей родитель - оболочка:
	final Menu menu = new Menu(shell, SWT.BAR);

	// Создаем пункт в меню.
	final MenuItem helpItem = new MenuItem(menu, SWT.CASCADE);
	//Ставим текст: знак "&" говорит нам о том, что пункт меню будет доступен по комбинации клавиш Alt+H.
	helpItem.setText("&Help");

	//Далее делаем под-меню для нашего меню Item'a:
	final Menu helpMenu = new Menu(menu);
	helpItem.setMenu(helpMenu);
	final MenuItem about = new MenuItem(helpMenu, SWT.NONE);
	about.setText("About");
	about.addSelectionListener(new HelpMenuAboutSelectionListener(shell));//Вешаем слшуатель события на нажатие этого пункта меню.
	


И запускаем наше приложение:

    shell.open();//Отображаем окно

	while (!shell.isDisposed()) {
	    final Display display = shell.getDisplay();
	        if (!display.readAndDispatch()) {
	            display.sleep();
	        }
	}

	shell.dispose();


Далее, во время выполнения нашего блокнота, сработает какой-то из слушателей (в ответ на какое-то наше действие), из которого мы сделаем то, что нам нужно, допустим запустим какое-то задание в синхронном или в асинхронном режиме:

    shell.getDisplay().asyncExec(new ReloadJob(documentAndTabManager, currentTab));


Упаковка


Очередная порция псевдо-трудностей с которой я столкнулся:
Для каждой операционной системы и архитектуры нужно сделать свой билд. Для этого нужны jar'ы для каждой конкретной платформы. Я привык пользоваться Maven'ом, но для этих целей он не очень хорошо подходит, ибо свежих версий SWT я увы не нашел в Maven-репозиториях, да и пришлось скачивать мануально пакеты для каждой из платформ операционных систем/архитектур. Кроме того там где нужно много кастомизации Maven не особо подходит, зато на помощь приходит старый-добрый Ant. В качестве менеджера зависимостей я взял Ivy.

Кусок ant-скрипта(build.xml), отвечающий за упаковку под конкретную операционную систему/архитектуру:

    <jar destfile="${package.dir}/${jar.prefix}_${target.platform}-${target.architecture}-${version}.jar"
	             basedir="${output.dir}">
	     <restrict>
	         <archives>
	                    <zips>
	                 <fileset refid="classpath.files"/>
	                 <fileset dir="${basedir}/lib/swt" includes="swt-${target.platform}-${target.architecture}.jar"/>
	             </zips>
	         </archives>
	    </restrict>
	    <manifest>
	         <attribute name="Main-Class" value="swt.texteditor.simple.Bootstrap"/>
	    </manifest>
	</jar>
       


Размер Jar'ов получился 2 — 2.5 МБ (в зависимости от ОС и архитектуры), что вообщем-то не так уж и много.

Вместо заключения


Пропустив через себя небольшой цикл разработки я могу заметить

Минусы SWT на мой взгляд:
* Мало документации/туториалов
* Гугл не так много знает о SWT, как о Swing
* Многие проблемы приходится решать дольше.

Плюсы SWT на мой взгляд:
* В общем и целом простой и понятный API
* Кросс-платформенное, нативно выглядящее приложение
* Из коробки быстрее работающее, чем такое же на Swing

Что я вынес для себя из этого маленького эксперимента?

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

P.S. Несколько скриншотов напоследок.

Из-под Linux'a:

Нативная прокрутка для Ubuntu (Unity)


Нативное меню для Ubuntu (Unity)


И из-под Windows:



Под Mac OS к сожалению скриншотов нет за неимением Mac OS X.
Любезно предоставленный скриншот пользователем seneast:
image

Исходные коды доступны здесь: code.google.com/p/swt-text-editor/source/browse
Скачать мою вариацией блокнота для своей ОС можно здесь: code.google.com/p/swt-text-editor/downloads/list
Из-под Windows запускается двойным кликом, из-под Mac OS X java -XstartOnFirstThread -jar simple_edit*., Linux командой java -jar simple_edit*. Запускается под Java 1.6 и выше.
Короткие инструкции, как начать баловаться с кодом из-под IDE(на английском) code.google.com/p/swt-text-editor/wiki/SourceCodeImport

Буду рад любым комментариям, нареканиям и советам.
Tags:
Hubs:
+42
Comments 40
Comments Comments 40

Articles