LoginSignup
0
0

More than 1 year has passed since last update.

Gtk3アプリComboBoxの表示の簡略化

Last updated at Posted at 2021-04-29

Gtk3アプリのComboBoxの表示の簡略化

スクリーンショット 2020-03-29 12.53.22.png
ComboBoxの表示の書き方の課題

CellRendererTextやSetCellDataFuncを毎回書くのが面倒
拡張クラスの中で実行させ、書く行数を減らす

gladeファイルにCombBoxを配置します。

using System;
using System.Collections.Generic;
using Gtk;
using UI = Gtk.Builder.ObjectAttribute;

namespace ComboBoxGtkApplication
{
    class MainWindow : Window
    {

        [UI] private ComboBox _comboBox1 = null;

        List<Song> songs;

        public MainWindow() : this(new Builder("MainWindow.glade"))
        {
        }
        private MainWindow(Builder builder) : base(builder.GetRawOwnedObject("MainWindow"))
        {
            builder.Autoconnect(this);
            _mkComboBox();
        }        
        void _mkComboBox()
        {
            songs = new List<Song>();

            songs.Add (new Song ("Dancing DJs vs. Roxette", "Fading Like a Flower"));
            songs.Add (new Song ("Xaiver", "Give me the night"));
            songs.Add (new Song ("Daft Punk", "Technologic"));

            _comboBox1._mkCellRendererText("Artist");

            Gtk.ListStore musicListStore = new Gtk.ListStore (typeof (Song));
            foreach (Song song in songs) {
                musicListStore.AppendValues (song);
            }

            _comboBox1._mkBinding();

            _comboBox1.Model = musicListStore;

        }
    }      
    public class Song
    {
        public Song (string artist, string title)
        {
            this.Artist = artist;
            this.Title = title;
        } 
        //リフレクションを有効にするためgetとsetを書く
        public string Artist { get; set; }
        public string Title { get; set; }
    }
}

解説

リフレクションを使うため、モデルにgeter seterを書く
ComboBoxクラスを拡張クラスにする
CellRendererTextExにCellRendererTextを親クラスにした派生クラス(継承)を作る
CellRendererTextExの中にbindingPropertyNameにモデルのプロパティを指定する

ComboBoxクラスを拡張クラス

CellRendererTextを継承クラスにする

using System;
using System.Reflection;
using Gdk;
using Gtk;

public static class objectExtensions {

    public static object _performSelector_Property(this object obj, string propertyName) {

        try
        {
            Type magicType = obj.GetType();
            PropertyInfo pi = magicType.GetProperty(propertyName,
                    BindingFlags.Public | BindingFlags.NonPublic |
                    BindingFlags.Instance | BindingFlags.Static);

            MethodInfo getMethod = pi.GetGetMethod();
            object result = getMethod.Invoke(obj, null);

            return result;
        }
        catch (Exception e)
        {
             Console.WriteLine(e.Message);
        }

        return null;
    }
}

namespace Gtk {

        public partial class CellRendererTextEx : Gtk.CellRendererText {
         public string BindingPropertyName = "";
        }

        public static partial class ComboxExtensions {

        static public void _comboInit(ComboBox Combox1)
        {
            Combox1.Clear();
        }

        static public Gtk.CellRendererText _mkCellRendererText(this ComboBox Combox1 ,string baindingName) {

            _comboInit(ComboBox);
            Gtk.CellRendererTextEx CellRendererTextEx1 = new Gtk.CellRendererTextEx();
            CellRendererTextEx1.BindingPropertyName = baindingName;
            Combox1.PackStart(CellRendererTextEx1, true);
            return CellRendererTextEx1;
        }

        static public void _mkBinding(this ComboBox Combox1) {
            if(Combox1.Cells.Length > 0) {
                Combox1.SetCellDataFunc(Combox1.Cells[0], new Gtk.CellLayoutDataFunc(_RenderComboDo));
            }
        }

        static private void _RenderComboDo(
            Gtk.ICellLayout cell_layout,
            Gtk.CellRenderer cell,
            Gtk.ITreeModel model,
            Gtk.TreeIter iter) {

            if(!(cell is Gtk.CellRendererTextEx)) {
                return;
            }
            if((cell as Gtk.CellRendererTextEx).BindingPropertyName == "" ||
                (cell as Gtk.CellRendererTextEx).BindingPropertyName == null) {
                Console.WriteLine("PropertyNameがない");
                return;
            }

            object classObj = (object)model.GetValue(iter, 0);

            object value = classObj._performSelector_Property((cell as Gtk.CellRendererTextEx).BindingPropertyName);

           if(value != null && cell is Gtk.CellRendererText && (value is String)) {
                (cell as Gtk.CellRendererText).Text = value as String;
            }else if (value != null && cell is Gtk.CellRendererText && (value is int)) {
                (cell as Gtk.CellRendererText).Text = ((int)value).ToString();
            }else if (value != null && cell is Gtk.CellRendererText && (value is long)) {
                (cell as Gtk.CellRendererText).Text = ((long)value).ToString();
            } else if(value != null && cell is Gtk.CellRendererPixbuf && (value is String)) {
                (cell as Gtk.CellRendererPixbuf).Pixbuf = new Pixbuf((value as String));
            } else if(value != null && cell is Gtk.CellRendererToggle && (value is String)) {
                (cell as Gtk.CellRendererToggle).Active = Convert.ToBoolean((value is String));
            } else if(value != null && cell is Gtk.CellRendererProgress && (value is String)) {
                (cell as Gtk.CellRendererProgress).Value = Convert.ToInt32((value is String));
            } else if(value != null && cell is Gtk.CellRendererPixbuf && (value is byte[])) {
                (cell as Gtk.CellRendererPixbuf).Pixbuf = new Pixbuf((byte[])value);
            } else if(value != null && cell is Gtk.CellRendererToggle && (value is Boolean)) {
                (cell as Gtk.CellRendererToggle).Active = (Boolean)value;
            } else if(value != null && cell is Gtk.CellRendererProgress && (value is int)) {
                (cell as Gtk.CellRendererProgress).Value = (int)value;
            }else if(value != null && cell is Gtk.CellRendererProgress && (value is int)) {
                (cell as Gtk.CellRendererProgress).Value = (int)value;
            }
        }
    }
}

Ubuntu Gtkアプリ イベントハンドラー編に続く

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0