用Ruby创建GUI应用程序只是为了浏览Yard


介绍

在这里,我回顾一下只看我1-2年前为GUI练习制作的院子的软件,想起了我是如何用Ruby制作GUI软件的,并将其总结在自己的模板中。本文总结了有关ruby/gtk3的中间内容。如果您是初学者,请在此处查看。

[Ruby]使用Glade在10分钟内创建的Ruby / GTK3 GUI应用程序

该软件仅显示本地安装的ruby,因此并不总是实用的。

Github:https://github.com/kojix2/yardview

image.png

有点透明。我搞砸了Glade设置,而不是代码。

image.png

您可以与Gem一起尝试。 (视环境而定可能不起作用)

1
gem install yardview_gtk3

开始

1
yardview

原始故事

Lazarus Lazaridis的文章。我正在制作Todo应用。

  • https://iridakos.com/programming/2018/01/25/creating-a-gtk-todo-application-with-ruby
  • https://github.com/iridakos/gtk-todo-tutorial

对于能够阅读该原始材料的英语内容的人来说已经足够了,但是本文还包含比原始材料更多的内容,例如如何使信号处理更轻松。

ruby

添加可执行文件的选项--exe -b

1
bundle gem yardview --exe

照常编辑gemspec文件

ruby规格

1
2
3
4
5
  spec.add_dependency 'yard'
  spec.add_dependency 'gtk3'
  spec.add_dependency 'webkit2-gtk'
  spec.add_development_dependency 'bundler'
  spec.add_development_dependency 'rake'

用户熟悉Ruby→不包含Gemfile.lock
用户与Ruby没有关系→Gemfile.lock保留

目录结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
.
├── Gemfile
├── LICENSE.txt
├── README.md
├── Rakefile
├── exe
│   └── yardview
├── lib
│   ├── yardview
│   │   ├── application.rb
│   │   ├── application_window.rb
│   │   └── version.rb
│   └── yardview.rb
├── resources
│   ├── LICENSE
│   ├── gresources.xml
│   ├── ruby.png
│   ├── yardview.ui
│   └── yardview_screenshot.png
└── yardview.gemspec

这很麻烦,所以我直接在exe/yardview上编写各种东西。

点是您一路运行glib-compile-resources的位置。我们使用Gnome的资源框架GResource。如果此命令未通过路径,则将无法执行该路径,因此您可能需要采取一些措施。那么Windows ...另外,我觉得有一个问题,就是每次编译资源并最后丢弃它是否真的好。

庭院景观

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#!/usr/bin/env ruby

require 'optparse'
require 'yardview'
require 'fileutils'

port_num ||= 8808

opt = OptionParser.new
opt.program_name = 'Yardview'
opt.version = Yardview::VERSION
opt.on('-p', '--port VAL', Integer) { |v| port_num = v }
opt.parse!(ARGV)

resource_xml = File.expand_path('../resources/gresources.xml', __dir__)
resource_bin = File.expand_path('../gresource.bin', __dir__)

system('glib-compile-resources',
       '--target', resource_bin,
       '--sourcedir', File.dirname(resource_xml),
       resource_xml)

at_exit do
  FileUtils.rm_f(resource_bin)
end

app = Yardview.application

resource = Gio::Resource.load(resource_bin)
Gio::Resources.register(resource)

app.signal_connect :activate do |application|
  window = Yardview::ApplicationWindow.new application, port: port_num
  window.present
end

app.run

这次我们将显示一个网页,因此添加webkit2-gtk

lib / yardview.rb

1
2
3
4
5
6
7
require 'yardview/version'
require 'yardview/application'
require 'yardview/application_window'
require 'webkit2-gtk'

module Yardview
end

在Glade一侧指定信号处理程序的名称。

image.png

写入要使用的文件。

gresource.xml

1
2
3
4
5
6
7
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
  <gresource prefix="/com/github/kojix2/yardview">
    <file preprocess="xml-stripblanks">yardview.ui</file>
    <file>ruby.png</file>
  </gresource>
</gresources>

这是一个大酱,但是我将Application的一个实例包装在一个类变量中,以便可以对其进行引用。

lib /码视图/ application.rb

1
2
3
4
5
6
7
8
9
require 'gtk3'

module Yardview
  class << self
    def application
      @@application ||= Gtk::Application.new('com.github.kojix2.yardview', :flags_none)
    end
  end
end

type_registerset_templatebind_template_child set_connect_func是重要的魔术。
据说type_register用于与Glib和GObject集成。 (老实说,我不太了解)
set_template指定ui文件。请注意,您是从GResource指定它,而不是从文件路径指定它。
set_template_child提供了可以访问窗口小部件的方法。在底部看起来像变量的box实际上是访问小部件的方法调用。
set_connect_func自动将信号连接到Ruby方法。 (这是原始故事中未完成的部分)

lib /码视图/ application_window.rb

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
require 'gtk3'

module Yardview
  class ApplicationWindow < Gtk::ApplicationWindow
    type_register

    def self.init
      set_template resource: '/com/github/kojix2/yardview/yardview.ui'
      bind_template_child 'box'
      set_connect_func do |handler_name|
        lambda do
          Yardview.application.active_window.__send__(handler_name)
        end
      end
    end

    attr_accessor :port

    def initialize(application, port: port_num)
      super application: application
      set_title 'YardView'
      set_icon GdkPixbuf::Pixbuf.new resource: '/com/github/kojix2/yardview/ruby.png'

      @port = port
      start_yard_server
      create_gui
    end

    def create_gui
      signal_connect('destroy') do
        Process.kill(:INT, @yard)
        @yard = nil
      end
      at_exit { Process.kill(:INT, @yard) unless @yard.nil? }
      @view = WebKit2Gtk::WebView.new
      @view.load_uri("http://localhost:#{port}")
      box.add @view, expand: true, fill: true
      @view.show
    end

    def port_open?(port)
      !system("lsof -i:#{port}", out: '/dev/null')
    end

    def on_home_clicked
      @view.load_uri("http://localhost:#{port}")
    end

    def on_back_clicked
      @view.go_back
    end

    def on_top_clicked
      @view.run_javascript('window.scrollTo(0,0);')
    end

    def on_refresh_clicked
      @view.reload
    end

    def start_yard_server
      if port_open? port
        @yard = spawn("yard server -g -p #{port} --reload")
        sleep 1
      else
        raise "port #{port} is in use!"
      end
    end
  end
end

当使用Ruby创建GUI应用程序时,异步处理会成为一个问题,但是对于仅通过执行命令即可进行管理的事情,建议使用spawn。无论平台如何,它都相对工作。

如上所述,在很多地方,写它的人不太了解,但是如果您写这样的东西,它会起作用。

这是一个模板,使您可以主动使用Gnome的功能。不,我不需要GResource,不需要集成GObject和Ruby对象,而且我认为每次进行信号处理都比较容易。

这就是本文的全部内容。