Gérer DatePicker avec Ruby / gtk3 + glade3

Préambule

Si gtk n'a pas de DatePicker et qu'il est difficile à utiliser ... Si vous vous demandez, @ kojix2 peut le faire avec gtk3 en combinaison avec PopOver! M'a conseillé.

Je veux couvrir une petite interface graphique frontale avec ruby, je veux écrire la partie GUI avec un outil de construction, mais maintenant que wxWidget ne peut plus être utilisé, je me plaignais que c'était un choix entre le créateur de QT et l'éditeur de scène JavaFX. J'ai eu une réponse comme celle-ci. Depuis que vous m'avez montré le code de gtk3, j'ai essayé de créer une zone de texte (Gtk :: Entry) qui peut sélectionner DatePicker, DateChooser ou date avec glade. Ou plutôt, un mémo à rédiger avant d'oublier.

Préparation

Les hypothèses d'exploitation sont ruby2.7, gtk3, glade 3.36.0. Je pense que ruby est facile à installer, mais il y avait un léger piège dans la clairière sous Windows, veuillez donc vous référer à ce qui suit.

macOS et UnixLikeOS

Pour Debian, apt + gem peut être utilisé, et pour macOS, homebrew peut être utilisé.

Windows

Si vous regardez le Site officiel pour utiliser glade sous Windows, vous pouvez voir que le binaire d'exécution est seulement ancien, comme pour gtk2. J'ai donc décidé d'utiliser msys2 avec scoop. (Pour l'introduction de scoop, vous pouvez vous référer à Another Qiita article)

Après avoir installé msys2, installez la bibliothèque gtk et glade3 avec pacman sur le bash de msys2. Veuillez noter que vous n'installez pas Glade directement avec scoop.

$ pacman -S mingw-w64-x86_64-gtk3 mingw-w64-x86_64-glade

$ /mingw64/bin/glade

Si vous pouvez commencer glade comme ci-dessus, vous êtes prêt (veuillez également préparer du rubis)

Faire une rivière avec clairière

Je vais faire une rivière selon le style de gtk (?). Si vous comparez le menu de l'écran de la clairière au Web, HTML / BODY est le niveau supérieur (≒ fenêtre), les boutons et les champs de texte avec les opérations de l'utilisateur sont Control (Button, Entry, etc.), les étiquettes d'affichage et les images sont Display, div S'agit-il d'un conteneur (GtkBox, etc.)?

Cette fois, lorsque le champ de texte (GtkEntry) est focalisé, je souhaite afficher le widget sur le calendrier, donc en plus de la fenêtre principale, créez un conteneur pour PopOver.

image.png

Puisque je dois le faire moi-même, j'ajouterai un bouton pour sélectionner hier à demain en plus du calendrier simple. Je suis en train de changer.

Donnez à chaque widget un nom par identifiant pour un appel ultérieur depuis ruby. Enregistrez également une méthode en tant que gestionnaire qui exécute un événement tel qu'un clic sur un bouton en le sélectionnant dans l'onglet de signal. Veuillez noter qu'une erreur se produira si aucune méthode n'est enregistrée comme gestionnaire lors de l'exécution de ruby.

Le fichier .glade qui est enregistré est XML.

La partie dégoûtante

Écrivez un gestionnaire dans l'événement de focus-in-event de signal de GtkEntry qui appelle DatePicker afin que PopOver s'affiche lorsque le focus arrive. Cependant, si vous fermez PopOver lorsque la mise au point est perdue, il est naturel que Calendar ne puisse pas être utilisé, alors soyez prudent.

Attribuer un gestionnaire au signal de sélection du jour-double-clic lorsque vous double-cliquez sur une date dans le calendrier

Créez un bouton "fermer" comme condition pour désactiver l'affichage PopOver et définissez visible = false dans le signal cliqué.

Anecdotes sur l'opération

Avec GtkWindow sélectionné dans le volet gauche, appuyez sur le bouton d'engrenage en bas pour un aperçu d'exécution.

Dans l'ancien Visual BASIC et Delphi, il était standard que les boutons puissent être disposés librement sous la fenêtre, mais dans gtk, il semble qu'il soit fondamentalement emballé dans un conteneur, etc. et ajouté et automatiquement mis en page. Pour un placement gratuit, utilisez un conteneur appelé GtkFixed. Vous pouvez déplacer le widget placé dans Fixe en maintenant la touche Maj enfoncée tout en faisant glisser.

Glade, qui est un constructeur d'interface graphique mais ne peut pas continuer à déplacer des widgets, fait des ajustements en déplaçant l'ordre des positions sur l'onglet d'emballage. Si vous souhaitez le déplacer vers une autre boîte, couper et coller ...

Écrire le code d'implémentation

Certains d'entre eux ont été essayés avec mvc, donc pour un code simple, reportez-vous à 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') #Calendrier dans 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')

    #Les boutons de PopOver définissent les gestionnaires de signaux de 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) } #le gestionnaire est String
  end

  def select_day(day)
    @seldate_controller.content.selected_date = Date.today + day
    click_dateclose
  end

  # [✕]Quittez l'application lorsque vous appuyez sur
  def on_main_destroy
    Gtk.main_quit
  end

  #Lorsque le focus se déplace sur la date d'entrée
  def focus_in_entrydate
    @date_picker.visible = true
  end

  #Lorsque vous double-cliquez sur une date du calendrier
  def dblclick_date
    @seldate_controller.content.selected_date = sprintf('%04d-%02d-%02d', @calendar.year, @calendar.month, @calendar.day)
    click_dateclose
  end

  # date_Appuyez sur le bouton d'annulation avec le sélecteur
  def click_dateclose
    @date_picker.visible = false
  end
end

class App < GyoumuApp
  def initialize
    super
    @win.show_all
    Gtk.main
  end
end
App.new

Résumé

Cliquez ici pour les dépôts divers (https://github.com/paichi81/glade_tut1)

La bibliothèque gtk3 est pratique car vous pouvez lire le fichier glade avec Gtk :: Builder.new et l'utiliser rapidement.

Il est pratique d'utiliser rapidement des pièces prêtes à l'emploi telles que DatePicker de WxWidget, mais lorsque vous souhaitez ajouter votre propre bouton comme cette fois, il n'est pas facile de se retourner. Il s'avère que gtk peut être résolu avec une approche de type Unix. C'est juste un tracas ...

En regardant les paramètres de glade, les parties qui peuvent être altérées avec gtk, auxquelles il est difficile de s'en tenir, sont assez détaillées. Pour le dire autrement, raw gtk doit être très conscient des widgets, donc il me manque quelque chose comme MVVM.

Recommended Posts

Gérer DatePicker avec Ruby / gtk3 + glade3
[Ruby] Gérez les variables d'instance avec des méthodes d'instance
Manipuler le dispositif avec des rails
Gérez JSON avec minimal-json
Premiers pas avec Ruby
Evolve Eve avec Ruby
J'ai essayé DI avec Ruby
Client GraphQL commençant par Ruby
Ruby: envoyer des e-mails avec Starttls
Formater Ruby avec VS Code
Comment vérifier les nombres entiers avec ruby
[Ruby] problème avec l'instruction if
Étudier à CodeWar (ruby) ⑤ Proc
Utilisez Ruby avec Google Colab
Premiers pas avec les modules Ruby
[ruby] Appel d'une méthode avec un argument
Gérer les dates avec Javascript (moment.js)