Ruby/Desktop(Qt4)
Пример «простого текстового редактора», написанного на Ruby + Qt4.
правитьСейчас мы напишем простой текстовый редактор (просмотрщик для начала).
Нам понадобится ruby1.8 и rbuic4 в системе GNU/Linux. Причём при установке последнего должны будут установиться необходимые библиотеки по работе с Qt4 в Ruby. Интерфейс будет делаться в Qt Designer (designer-qt4)
В Qt Designer создаём новую форму, основанную на «Main Window». На форму помещаем 2 кнопки типа «Push Button» и поле для редактирования текста «Text Edit».
Для первой кнопки установим текст «Открыть файл»: через свойство «text» в окне Property Editor или по двойному щелчку на кнопке. Также установим для неё ObjectName — «b_open»: опять же через Property Editor или выбрав в контекстном меню пункт «Change objectName».
Для главной формы objectName я установил как «notepad», а для Text Edit — «editor_window».
Второй кнопке установим название «Закрыть» и objectName = «b_close». Кнопка что должна делать? Правильно, закрывать окно. В Qt-Disigner в окне Signal/Slot Editor добавим новый слот: Sender -> b_close; Signal -> clicked(); Receive -> notepad; Slot -> close();
И сохраняем проект как «editor.ui».
Теперь выполним команду:
$ rbuic4 editor.ui -x > editor.rb
для того, чтобы получить класс Ruby - Ui_Notepad.
Опция -x добавляет инструкции в файл для запуска приложения. Можно сейчас запустить форму, чтобы убедиться что всё работает:
$ ruby -Ku editor.rb
опции -Ku предназначены для корректной обработки UTF-8.
Но тут есть одна тонкость: если мы будем вносить какие-то изменения в интерфейс, то будет переписываться файл «editor.rb». Поэтому мы создадим отдельный скрипт, который будет вызывать форму, назовём его «start.rb». Пересоздадим форму: rbuic4 editor.ui > editor.rb, и напишем start.rb следующим образом:
require 'Qt4'
require 'editor.rb'
class StartQT4 < Qt::MainWindow
def initialize parent=nil
super
@ui = Ui_Notepad.new
@ui.setupUi self
end
end
if $0 == __FILE__
app = Qt::Application.new(ARGV)
myapp = StartQT4.new
myapp.show
app.exec
end
Сейчас кнопка «Закрыть» работает. Пора настроить кнопку «Открыть». Внесём изменения в «start.rb»:
require 'Qt4'
require 'editor.rb'
class StartQT4 < Qt::MainWindow
#перечисляем используемые слоты
slots 'file_dialog()'
def initialize parent=nil
super
@ui = Ui_Notepad.new
@ui.setupUi self
#тут мы обрабатываем сигнал
Qt::Object.connect(@ui.b_open, SIGNAL('clicked()'), self, SLOT('file_dialog()'))
end
#метод, который выполняется при нажатии на кнопку.
def file_dialog
@ui.editor_window.setText 'WikiBooks: Ruby'
end
end
if $0 == __FILE__
app = Qt::Application.new(ARGV)
myapp = StartQT4.new
myapp.show
app.exec
end
Если запустить приложение, то при нажатии на кнопку («clicked()») вызывается слот «file_dialog()» и, в свою очередь, вызывается метод «file_dialog», который вставляет текст «WikiBooks: Ruby» в EditText.
Сейчас мы используем Qt::FileDialog для выбора файла. Следующий код:
require 'Qt4'
require 'editor.rb'
class StartQT4 < Qt::MainWindow
slots 'file_dialog()'
def initialize parent=nil
super
@ui = Ui_Notepad.new
@ui.setupUi self
Qt::Object.connect(@ui.b_open, SIGNAL('clicked()'), self, SLOT('file_dialog()'))
end
def file_dialog
f = Qt::FileDialog
text = File.new(f.getOpenFileName).read
@ui.editor_window.setText text
end
end
if $0 == __FILE__
app = Qt::Application.new(ARGV)
myapp = StartQT4.new
myapp.show
app.exec
end
f.getOpenFileName покажет диалог выбора файла, который закрывается после выбора файла (и возвращается путь к файлу), прерывая выполнение кода. Это работает, но если мы нажмём «Отмена» при работе окна f.getOpenFileName, мы не получим пути к файлу, но получим следующую ошибку: start.rb:17:in `initialize': can't convert nil into String (TypeError)
То есть, если файл не выбран — возвращается nil. Следующий код включает проверку возвращаемого значения:
require 'Qt4'
require 'editor.rb'
class StartQT4 < Qt::MainWindow
slots 'file_dialog()'
def initialize parent=nil
super
@ui = Ui_Notepad.new
@ui.setupUi self
Qt::Object.connect(@ui.b_open, SIGNAL('clicked()'), self, SLOT('file_dialog()'))
end
def file_dialog
f = Qt::FileDialog
if @filename = f.getOpenFileName
text = File.new(@filename).read
@ui.editor_window.setText text
end
end
end
if $0 == __FILE__
app = Qt::Application.new(ARGV)
myapp = StartQT4.new
myapp.show
app.exec
end
Сейчас мы можем выбрать файл, но не можем сохранить его. Добавим кнопку «Сохранить» в и установим её свойство objectName в «b_save», и пересоздадим GUI из нового ui-файла:
rbuic4 editor.ui > editor.rb
Сейчас приложение выглядит следующим образом:
Мы добавим слот для сохранения файла и создадим ему коннект с сигналом «clicked()» на pushButton-кнопку «Сохранить»:
require 'Qt4'
require 'editor.rb'
class StartQT4 < Qt::MainWindow
slots 'file_dialog()', 'file_save()'
def initialize parent=nil
super
@ui = Ui_Notepad.new
@ui.setupUi self
Qt::Object.connect(@ui.b_open, SIGNAL('clicked()'), self, SLOT('file_dialog()'))
Qt::Object.connect(@ui.b_save, SIGNAL('clicked()'), self, SLOT('file_save()'))
end
def file_dialog
f = Qt::FileDialog
if @filename = f.getOpenFileName
text = File.new(@filename).read
@ui.editor_window.setText text
end
end
def file_save
if @filename
f = File.new @filename, 'w'
f.puts @ui.editor_window.toPlainText
f.close
end
end
end
if $0 == __FILE__
app = Qt::Application.new(ARGV)
myapp = StartQT4.new
myapp.show
app.exec
end
Итак, мы получили приложение, которое открывает текстовые файлы и сохраняет изменения в этом файле.