Пример «простого текстового редактора», написанного на 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

Итак, мы получили приложение, которое открывает текстовые файлы и сохраняет изменения в этом файле.