If gtk doesn't have a DatePicker and it's hard to use ... If you're wondering, @ kojix2 can do it with gtk3 in combination with PopOver! Advised me.
I want to cover the GUI of the front end with ruby, and I want to write the GUI part with the builder tool, but now that wxWidget can no longer be used, I was complaining that I had to choose between QT creator and JavaFX Scene Editor. I got a reply like this. Since you showed me the code of gtk3, I tried to make a text box (Gtk :: Entry) that can select a date such as DatePicker or DateChooser with glade. Or rather, a memo to write before forgetting.
The operating premise is ruby2.7, gtk3, glade 3.36.0. I think that ruby can be introduced easily, but there was a slight trap in glade on Windows, so please refer to the following.
For Debian, apt + gem can be used, and for macOS, homebrew can be used.
Windows
When I try to use glade on Windows, when I look at the official site, I find that the executable binaries are only old ones such as for gtk2. So I decided to use msys2 with scoop. (For the introduction of scoop, you can refer to Another Qiita article)
After installing msys2, install gtk library and glade3 with pacman on bash of msys2. Please note that you do not install glade directly with scoop.
$ pacman -S mingw-w64-x86_64-gtk3 mingw-w64-x86_64-glade
$ /mingw64/bin/glade
If you can start glade as above, you are ready (please prepare ruby as well)
I will make a river according to the style of gtk (?). If you compare the menu on the glade screen to the web, HTML / BODY is the top level (≒ window), buttons and text fields with user operations are Control (Button, Entry, etc.), display labels and images are Display, div. Is it a container (GtkBox, etc.)?
This time, when the text field (GtkEntry) is focused, I want to display the widget on the calendar, so in addition to the main window, create a container to popover.
Since I have to make it myself, I will add a button to select yesterday to tomorrow in addition to the calendar. I am changing.
I will give each widget a name by ID so that I can call it from ruby later. Also, register a method that executes an event such as a button click by selecting it from the Signal tab as a handler. Please note that an error will occur if there is no method registered as a handler when executing ruby.
The .glade file that is saved is XML.
Write a handler in the signal focus-in-event event of GtkEntry that calls DatePicker so that PopOver is displayed when the focus comes. However, on the contrary, if you close PopOver when the focus is lost, it is natural that Calendar cannot be operated, so be careful.
Assign a handler to the day-select-double-click signal when double-clicking a date in Calender
Create a "Close" button as a condition to turn off the PopOver display, and set visible = false in the clicked signal.
With GtkWindow selected in the left pane, press the gear button at the bottom to preview at runtime.
In the old Visual BASIC and Delphi, it was standard that buttons could be arranged freely under the window, but in gtk, it seems that it is basically packed in a container etc., added, and automatically laid out. For free placement, use a container called GtkFixed. Widgets placed inside Fixed can be moved by holding down the Shift key while dragging.
Glade, who is a GUI builder but can't keep moving widgets, makes adjustments by moving the order of positions on the packing tab. If you want to move it to another Box, Cut and Paste ...
There is a part I tried with mvc, so for a simple code, refer to Original tweet ...
app.rb
# frozen_string_literal: true
%w[pp gtk3 date observer].each { |lib| require lib }
class ObjectController
include Observable
attr_reader :content
def content=(object)
@content = object
@content.add_observer(self)
@content
end
def update
changed
notify_observers
self
end
end
class View
attr_reader :widget
def controller=(c)
@controller = c
@controller.add_observer(self)
c
end
end
class State
include Observable
def initialize
@select_date = Date.today
end
attr_reader :selected_date
def selected_date=(date)
@selected_date = date
changed
notify_observers
date
end
end
class SelectedDateView < View
def initialize(parent_builder)
@widget = parent_builder.get_object('entrydate')
@widget.signal_connect('changed') do
@controller.content.selected_date = value
true
end
end
def value
@widget.text
end
def value=(f)
@widget.text = f.to_s
end
def update
self.value = @controller.content.selected_date
self
end
end
class GyoumuApp
def initialize
@select_date = Date.today
@builder = Gtk::Builder.new(file: 'glade1.glade')
@seldate_controller = ObjectController.new
@seldate_controller.content = State.new
@seldate_view = SelectedDateView.new(@builder)
@seldate_view.controller = @seldate_controller
@win = @builder.get_object('main')
@date_picker = @builder.get_object('date_picker') # PopOver
@calendar = @builder.get_object('calendar') #Calendar in PopOver
@buf_code = @builder.get_object('entrybuffer1')
@buf_code.text = 'K6205'
@btn_yday = @builder.get_object('select_yesterday')
@btn_tday = @builder.get_object('select_today')
@btn_tmrw = @builder.get_object('select_tomorrow')
#Button in PopOver sets signal handler from ruby
@btn_yday.signal_connect('clicked') do
select_day(-1)
end
@btn_tday.signal_connect('clicked') do
select_day(0)
end
@btn_tmrw.signal_connect('clicked') do
select_day(1)
end
@builder.connect_signals { |handler| method(handler) } #handler is String
end
def select_day(day)
@seldate_controller.content.selected_date = Date.today + day
click_dateclose
end
# [✕]Exit the app when is pressed
def on_main_destroy
Gtk.main_quit
end
#When the focus shifts to the entry date
def focus_in_entrydate
@date_picker.visible = true
end
#When you double-click a date on the calendar
def dblclick_date
@seldate_controller.content.selected_date = sprintf('%04d-%02d-%02d', @calendar.year, @calendar.month, @calendar.day)
click_dateclose
end
# date_Press the cancel button with picker
def click_dateclose
@date_picker.visible = false
end
end
class App < GyoumuApp
def initialize
super
@win.show_all
Gtk.main
end
end
App.new
Click here for miscellaneous repositories (https://github.com/paichi81/glade_tut1)
The gtk3 library is useful because you can read the glade file with Gtk :: Builder.new and use it quickly.
It is convenient to use ready-made parts such as WxWidget's DatePicker quickly, but when you want to add your own button like this time, you can not turn around. It turns out that gtk can be solved with a unix-like approach. It's just a hassle ...
Looking at the glade settings, the parts that can be tampered with with gtk, which is difficult to stick to, are quite detailed. To put it the other way around, raw gtk has to be very conscious of widgets, so I miss something like MVVM.
Recommended Posts