先週の記事に対するお詫び
前回の記事において、
Ubuntuのデスクトップ環境は、
しかし一度困難に陥ると、
このようなシェルスクリプトを第3者に渡す必要がある場合、
本連載の第422回ではwhiptailとシェルスクリプトとの組み合わせで、
Gtk+3を利用したGUIプログラム
多くのユーザーが使用している言語の代表例は、
なお、
Python 3の場合
Python 3を使った場合のプログラムは、
#!/usr/bin/env python3
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from gi.repository import GLib
import signal
class Sample(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self)
self.set_title('Gtk+3 sample')
self.set_border_width(20)
vbox = Gtk.Box()
vbox.set_orientation(Gtk.Orientation.VERTICAL)
vbox.set_spacing(10)
self.add(vbox)
topbox = Gtk.Box()
topbox.set_spacing(10)
vbox.pack_start(topbox, True, True, 0)
button = Gtk.Button()
button.set_label('swap')
button.connect('clicked', self.on_click_swap)
topbox.pack_start(button, True, True, 0)
button = Gtk.Button()
button.set_label('close')
button.set_use_underline(True)
button.connect('clicked', self.on_click_close)
topbox.pack_start(button, True, True, 0)
bottombox = Gtk.Box()
bottombox.set_spacing(10)
vbox.pack_start(bottombox, True, True, 0)
self.entry = Gtk.Entry()
self.entry.set_text('left')
bottombox.pack_start(self.entry, True, True, 0)
self.label = Gtk.Label()
self.label.set_text('right')
bottombox.pack_start(self.label, True, True, 0)
self.connect('delete-event', Gtk.main_quit)
GLib.unix_signal_add(GLib.PRIORITY_HIGH, signal.SIGINT, \
self.handle_unix_signal, None)
def handle_unix_signal(self, user_data):
self.on_click_close( None)
def on_click_swap(self, button):
label = self.label.get_text()
self.label.set_text(self.entry.get_text())
self.entry.set_text(label)
def on_click_close(self, button):
Gtk.main_quit()
win = Sample()
win.show_all()
Gtk.main()
コードの解説は後述します。python3.
$ gedit python3.py $ chmod a+x python3.py $ ./python3.py

Rubyの場合
Rubyを使った場合のプログラムは、
#!/usr/bin/env ruby
require 'gtk3'
class Sample < Gtk::Window
def initialize()
super
self.title = 'Gtk+3 sample'
self.border_width = 20
vbox = Gtk::Box.new(Gtk::Orientation::VERTICAL, 10)
self.add(vbox)
topbox = Gtk::Box.new(Gtk::Orientation::HORIZONTAL, 10)
vbox.pack_start(topbox, :expand => true, :fill => true, :padding => 0)
button = Gtk::Button.new(:label => 'swap')
button.signal_connect('clicked') { |obj|
label = @label.text
@label.set_text(@entry.text)
@entry.set_text(label)
}
topbox.pack_start(button, :expand => true, :fill => true, :padding => 0)
button = Gtk::Button.new(:label => 'close')
button.signal_connect('clicked') { |obj|
Gtk::main_quit()
}
topbox.pack_start(button, :expand => true, :fill => true, :padding => 0)
bottombox = Gtk::Box.new(Gtk::Orientation::HORIZONTAL, 10)
vbox.pack_start(bottombox, :expand => true, :fill => true, :padding => 0)
@entry = Gtk::Entry.new()
@entry.set_text('left')
bottombox.pack_start(@entry, :expand => true, :fill => true, :padding => 0)
@label = Gtk::Label.new('result')
@label.set_text('right')
bottombox.pack_start(@label, :expand => true, :fill => true, :padding => 0)
Signal.trap('INT') { |signo|
Gtk.main_quit()
}
self.signal_connect('delete_event') {
Gtk.main_quit()
}
end
end
win = Sample.new()
win.show_all()
Gtk::main()
このプログラムを実行するために、
$ sudo apt-get install ruby-gtk3 $ gedit ruby.rb $ chmod a+x ruby.rb $ ./ruby.rb
ECMAScriptの場合
ECMAScriptは、
ECMAScriptを使った場合のプログラムは、
#!/usr/bin/gjs
const Gtk = imports.gi.Gtk;
const Lang = imports.lang;
const Sample = new Lang.Class ({
Name: 'Gtk+3-Sample',
Extends: Gtk.Window,
_init: function() {
let params = {
title: 'Gtk+3 sample',
border_width: 20,
};
this.parent(params);
params = {
orientation: Gtk.Orientation.VERTICAL,
};
let vbox = new Gtk.Box(params);
this.add(vbox);
params = {
orientation: Gtk.Orientation.HORIZONTAL,
spacing: 10,
};
let topbox = new Gtk.Box(params);
vbox.pack_start(topbox, true, true, 0);
params = {
label: 'swap',
};
this.button = new Gtk.Button(params);
this.button.connect("clicked", Lang.bind(this, this.on_click_swap));
topbox.pack_start(this.button, true, true, 0);
params = {
label: 'close',
};
let button = new Gtk.Button(params);
button.connect('clicked', Lang.bind(this, this.on_click_close));
topbox.pack_start(button, true, true, 0);
params = {
orientation: Gtk.Orientation.HORIZONTAL,
spacing: 10,
};
let bottombox = new Gtk.Box(params);
vbox.pack_start(bottombox, true, true, 0);
this.entry = new Gtk.Entry();
this.entry.text = 'left';
bottombox.pack_start(this.entry, true, true, 0);
params = {
label: 'right',
};
this.label = new Gtk.Label(params);
bottombox.pack_start(this.label, true, true, 0);
},
on_click_swap: function() {
let label = this.label.label;
this.label.label = this.entry.text;
this.entry.text = label;
},
on_click_close: function() {
Gtk.main_quit();
},
});
Gtk.init(null);
var win = new Sample();
win.show_all();
Gtk.main();
このプログラムを実行するために、
$ sudo apt-get install gjs $ gedit ecmascript.js $ chmod a+x ecmascript.js $ ./ecmascript.js
なお、
また、
共通処理について
Python 3/
- windowの機能を実装したオブジェクトを作成し、
Gtk. main()を呼ぶ。 - そのオブジェクトは初期化の過程で、
レイアウトを決定されてウィジェットやイベントハンドラを付与される。
この2つの共通点について説明します。
ウィジェットの配置
まずは2番目についてです。今回のサンプルプログラムで使うBoxは、
- vboxとして垂直ボックスを生成し、
ウィンドウ内に配置。 - topboxとして水平ボックスを生成し、
vboxに配置。 - buttonとしてボタンを生成し、
topboxに配置。 - buttonとしてもうひとつボタンを生成し、
topboxに配置。 - bottomboxとして水平ボックスを生成し、
vboxに配置。 - entryとしてテキストエントリーを生成し、
bottomboxに配置。 - labelとしてテキストラベルを生成し、
bottomboxに配置。
2つのボタンには、
Gtk.main()でのループ処理
共通点の1番目で言及しているGtk.
今回のサンプルで実装したイベントハンドラは、
ループに突入するとプログラムは終了しなくなりますが、
Qt5を利用したGUIプログラム
前章で確認した共通の処理は、
そこで、
#!/usr/bin/env python3
from PyQt5.QtWidgets import QApplication, QWidget, QHBoxLayout, QVBoxLayout
from PyQt5.QtWidgets import QToolButton, QGroupBox, QLineEdit, QLabel
from gi.repository import GLib
import signal
class Sample(QWidget):
def __init__(self, parent=None):
super(Sample, self).__init__(parent)
self.setWindowTitle("PyQt5 sample")
layout = QVBoxLayout()
self.setLayout(layout)
top_grp = QGroupBox(self)
top_layout = QHBoxLayout()
top_grp.setLayout(top_layout)
layout.addWidget(top_grp)
buttom_grp = QGroupBox(self)
buttom_layout = QHBoxLayout()
buttom_grp.setLayout(buttom_layout)
layout.addWidget(buttom_grp)
button = QToolButton(top_grp)
button.setText('swap')
top_layout.addWidget(button)
button.clicked.connect(self.on_click_swap)
close = QToolButton(top_grp)
close.setText('close')
top_layout.addWidget(close)
close.clicked.connect(app.quit)
self.entry = QLineEdit(buttom_grp)
self.entry.setText('left')
buttom_layout.addWidget(self.entry)
self.label = QLabel(buttom_grp)
self.label.setText('right')
buttom_layout.addWidget(self.label)
GLib.unix_signal_add(GLib.PRIORITY_HIGH, signal.SIGINT, \
self.handle_unix_signal, None)
def handle_unix_signal(self, user_data):
app.quit()
def on_click_swap(self):
label = self.label.text()
self.label.setText(self.entry.text())
self.entry.setText(label)
app = QApplication(list())
sample = Sample()
sample.show()
app.exec()
このプログラムを実行するために、
$ sudo apt-get install python3-pyqt5 $ gedit qt5.py $ chmod a+x qt5.py $ ./qt5.py
利用した実装環は完全に異なりますが、
今回のプログラムについて
今回掲載したプログラムのライセンスはすべてパブリックドメインです。
また、