Gtk 颜色选择器 - 从屏幕选择颜色 - 不起作用 - Gtk 版本 3.24.33

问题描述 投票:0回答:1

我正在 Linux Mint 21 上使用应用程序绘图 - 版本 1.02 进行绘图,并注意到颜色选择工具
(请参阅 https://github.com/maoschanz/drawing/issues/630)无法工作。
I无法从屏幕上选择任何颜色...
这是一个 Gtk 小部件 - Gtk.ColorChooserWidget!

我使用 GJS 检查了它,并检查了颜色选择按钮上是否有任何待处理的处理程序!

Gtk.ColorChooserWidget 测试:

#!/usr/bin/gjs
"use strict";
imports.gi.versions.Gtk="3.0";
const { Gtk, GObject }= imports.gi;
Gtk.init(null);
const window = new Gtk.Window(), colorChooser= new Gtk.ColorChooserWidget ();

window.set_title("ColorChooserWidget test");
window.connect('destroy', () => { Gtk.main_quit(); });
window.set_size_request(640, 480);
window.add (colorChooser);
window.show_all();

log ("Gtk Version: "+Gtk.get_major_version()+"."+Gtk.get_minor_version()+"."+Gtk.get_micro_version());

//-- Gtk.ColorChooserWidget has only button_colorSelect !!
var button_select, button_cancel, button_colorSelect;
function find_buttons (gtk_children)                                                //-- finds the Color Chooser Dialog buttons Color-Select|Cancel|Select
   {
   const l=gtk_children.length;
   var i, gtk_child, button_child;
   for (i=0;i<l;i++)
      {
      gtk_child=gtk_children[i];
      if (gtk_child.get_children) find_buttons (gtk_child.get_children());
      if (gtk_child.constructor === Gtk.Button)
         {
         button_child=gtk_child.get_children()[0];
         if (button_child.constructor === Gtk.Image) button_colorSelect=gtk_child;  //-- button with image -> colorSelect button
         else                                                                       //-- button with label -> Select or Cancel
            {
            if (button_child.get_text() == "Select") button_select=gtk_child;
            else button_cancel=gtk_child;
            }
         }
      } 
   }
find_buttons (colorChooser.get_children());

var signal_ID=GObject.signal_lookup ("button_press_event", Gtk.Button.$gtype);
log ("class Gtk.Button - 'button-press-event' signal ID :"+signal_ID);

//-- GObject.signal_has_handler_pending ([GObject object OBJ], [signal ID NUM(int)], [detail GQuark-NUM(int)], [include blocked handlers BOOL]), for non detailed signal 0 can be used as GQuark
log ("button_colorSelect has handler pending on 'button-press-event' :" +GObject.signal_has_handler_pending (button_colorSelect, signal_ID, 0, true));

//-- test, if the button colorSelect is correctly identified - click on it
button_colorSelect.connect ("button-press-event", function () { log ("button colorSelect"); });

Gtk.main();

输出:

Gjs-Message: 23:13:23.831: JS LOG: Gtk Version: 3.24.33
Gjs-Message: 23:13:23.833: JS LOG: class Gtk.Button - 'button-press-event' signal ID :66
Gjs-Message: 23:13:23.833: JS LOG: button_colorSelect has handler pending on 'button-press-event' :false

“颜色选择”按钮没有任何待处理的处理程序!!,因此它没有任何功能! 这只在 Linux Mint 上吗???
还是一般在其他平台上,你必须自己编写功能?

gtk gjs
1个回答
0
投票

我已经附加了此功能,供 GJS 用户使用,如果您想使用
CLASS接口_ColorChooser

#!/usr/bin/gjs
"use strict";
imports.gi.versions.Gtk="3.0";
const { Gtk, Gdk, GdkPixbuf, GObject } = imports.gi;
Gtk.init(null);

const window = new Gtk.Window(), box=new Gtk.Box ({ orientation:1 }), button_startDialog=new Gtk.Button ({label: "get color dialog"}),
      labelA= new Gtk.Label ({ label: "Gtk.ColorChooserDialog", margin_top: 10, margin_bottom: 10 }), labelB= new Gtk.Label ({ label: "Gtk.ColorButton", margin_top: 10, margin_bottom: 10  }), 
      labelC= new Gtk.Label ({ label: "Gtk.ColorChooserWidget", margin_top: 10, margin_bottom: 10 });
      
var colorChooserA, colorChooserB, colorChooserC;


window.set_title("interface_ColorChooser");
window.connect('destroy', () => { Gtk.main_quit(); });
window.set_size_request(640, 480);
window.add (box);

/* ========================================================================================================================================
   CLASS interface_ColorChooser (implementation)
   ========================================================================================================================================
   implementation ... an instance of the three Color Chooser implementations Gtk.ColorButton, Gtk.ColorChooserWidget, Gtk.ColorChooserDialog */
{
var interface_ColorChooser=function (implementation)
   {
   this.implementation=implementation;     //-- three kinds of interface implementations -> Gtk.ColorButton, Gtk.ColorChooserWidget, Gtk.ColorChooserDialog
   this.button_select=null;                //-- Color Chooser Dialog button Select
   this.button_cancel=null;                //-- Color Chooser Dialog button Cancel
   this.button_colorSelect=null;           //-- Color Chooser Widget button Color-Select 
   this.button_colorSelect_handlerID=null; //-- ID for the handler connected to the button_colorSelect at "button-press-event" 
   this.average_33=true;                   //-- average color of a 3*3 pixel field under pointer

   //-- cursor for color selection - check hotspot values for new cursors!
   this.cursor=Gdk.Cursor.new_from_pixbuf (display, Gtk.IconTheme.get_default().load_icon ("color-select", 3, Gtk.IconLookupFlags.FORCE_SVG), 6, 16);
   this.colorButton_CCW=null;              //-- For implementation Gtk.ColorButton, the property holds a reference to the connected Gtk.ColorChooserWidget
   this.colorButton_handlerID=null;        //--                                     ID of the handler connected to the ColorButton at "butten-press-event" signal
   }

//-- destroys the interface and the implementation without memory leaks
interface_ColorChooser.prototype.destroy=function (dont_destroy_implementation)
   {
   this.button_select=null; this.button_cancel=null;
   if (this.button_colorSelect_handlerID) this.button_colorSelect.disconnect (this.button_colorSelect_handlerID);
   this.button_colorSelect=null; this.cursor=null;

   this.colorButton_CCW=null;
   if (this.colorButton_handlerID) this.implementation.disconnect (this.colorButton_handlerID);
   if (!dont_destroy_implementation) this.implementation.destroy(); this.implementation=null;
   }

/* connects to the Color Chooser implementation
   means -> finds the buttons Color-Select|Cancel|Select, if they exist and then add handler for color selecting to Color-Select button
   exception: Gtk.ColorButton -> if button_colorSelect isnt found yet,
              adds a handler "find_colorButton_dialog" at signal "button-press-event" on ColorButton instance, if not set yet */
interface_ColorChooser.prototype.connect=function ()
   {
   if (!this.button_colorSelect)
      {
      if (this.implementation.constructor === Gtk.ColorButton)
         {
         //-- add handler "find_colorButton_dialog" to Gtk.ColorButton instance at signal "button-press-event"
         if (!this.colorButton_handlerID)
            this.colorButton_handlerID=this.implementation.connect("button-press-event", find_colorButton_dialog.bind(this));
         else return;
         }
      else this.find_buttons (this.implementation.get_children());
      }
   
   //-- add signal handler for color selecting to Color-Select button
   if (this.button_colorSelect && this.button_colorSelect_handlerID==null)
      this.button_colorSelect_handlerID=this.button_colorSelect.connect ("button-press-event", pointer_grab.bind(this));  
   }

//-- finds the Color Chooser Dialog buttons Color-Select|Cancel|Select, if they exist
interface_ColorChooser.prototype.find_buttons=function (gtk_children)
   {
   const l=gtk_children.length;
   var i, gtk_child, button_child;
   for (i=0;i<l;i++)
      {
      gtk_child=gtk_children[i];
      if (gtk_child.get_children) this.find_buttons (gtk_child.get_children());
      if (gtk_child.constructor === Gtk.Button)
         {
         button_child=gtk_child.get_children()[0];
         if (button_child.constructor === Gtk.Image) this.button_colorSelect=gtk_child;  //-- button with image -> colorSelect button
         else                                                                            //-- button with label -> Select or Cancel
            {
            if (button_child.get_text() == "Select") this.button_select=gtk_child;
            else this.button_cancel=gtk_child;
            }
         }
      } 
   }

let root_window=Gdk.get_default_root_window(), //-- root Window
    display=Gdk.Display.get_default(),         //-- default Display
    seat=display.list_seats()[0],              //-- collection of input devices that belong to a user
    colorSelecting=false, colorPicked=false, colorChooser_inAction=null,
    keyStack=null, handler_register=new Object (), button_down_lastTimeStamp=null,


//-- template function for bind - will be bound to interface_ColorChooser instance
//-- called from "find_colorButton_dialog" setTimeout
find_colorButton_dialog_timeout=function ()
   {
   let i, windows=Gtk.Window.list_toplevels(), identification;
   for (i=0; i<windows.length;i++)
      {
      if (windows[i]!==window)
         {
         try { identification=windows[i].get_children()[0].get_children()[0]; }
         catch (error) { continue; }
         if (identification.constructor === Gtk.ColorChooserWidget)
            {
            this.colorButton_CCW=identification;
            this.find_buttons (windows[i].get_children()); //-- start search in window, to find also dialog buttons Cancel, Select, CCW has only Color-Select button!
            this.connect();
            break;
            }
         }
      }
   },

//-- template function for bind - will be bound to interface_ColorChooser instance
//-- signal handler for "button-press-event" on Gtk.ColorButton instance
find_colorButton_dialog=function (button, event)
   {
   if (this.colorButton_CCW) return;                          //-- already found
   setTimeout(find_colorButton_dialog_timeout.bind(this), 300);  //-- can only be found, if ColorButton press action has opened the dialog, wait 300ms after button press
   },
   
//-- template function for bind - will be bound to interface_ColorChooser instance
//-- signal handler for "button-press-event" on Color Chooser Widget button Color-Select
pointer_grab=function (button, event)
   {
   seat.grab (window.get_window(), Gdk.SeatCapabilities.POINTER | Gdk.SeatCapabilities.KEYBOARD, false, this.cursor, null, null); //
   colorChooser_inAction=this; colorSelecting=true; colorPicked=false; keyStack=[]; button_down_lastTimeStamp=-1;
   },

//-- signal handler for window "button-press-event"
onColorSelecting=function (window, event)
   {
   if (colorSelecting && !colorPicked)
      {
      const root_coords=seat.get_pointer().get_position ();
      let pixbuf, pixels, u, i, l, d, red_sum=0, green_sum=0, blue_sum=0,
          red, green, blue, alpha;
      
      if (event.get_time()-button_down_lastTimeStamp<=2) return;           //-- if SHIFT is hold down, then one mouse down causes two button press events, one immediateley after the other
      else button_down_lastTimeStamp=event.get_time();                     //--             dont know why, but can eliminate that with time check.
      
      if (colorChooser_inAction.average_33)                                                  //-- 3*3 field: build average values
         {
         pixbuf=Gdk.pixbuf_get_from_window (root_window, root_coords[1]-1, root_coords[2]-1, 3, 3);
         pixels=pixbuf.get_pixels();
         
         if (pixbuf.get_has_alpha()) { d=4; alpha=pixels[19]/255; }  //-- d .. count of values for one pixel, alpha from the middle point
         else { d=3; alpha=1 };
         for (u=0, i=0; u<3; u++)     //-- 3 lines
            {
            for (l=i+3*d; i<l; i+=d)  //-- 3 columns
               {
               red_sum+=pixels[i]; green_sum+=pixels[i+1]; blue_sum+=pixels[i+2];
               }

            if (d==3) i+=d; //-- internal inside pixbuf no alpha nulls are added per line to the pixel data,
            }               //-- some kind of padding? 3 pixel 9 color values plus 3 nulls are 12 values per line

         red=red_sum/2295; green=green_sum/2295; blue=blue_sum/2295; //-- 9*255=2295
         }
      else                                                                                  //-- 1*1 field
         {
         pixbuf=Gdk.pixbuf_get_from_window (root_window, root_coords[1], root_coords[2], 1, 1);
         pixels=pixbuf.get_pixels();
         if (pixbuf.get_has_alpha()) alpha=pixels[3]/255;
         else alpha=1;
         red=pixels[0]/255; green=pixels[1]/255; blue=pixels[2]/255;
         }
      
      colorChooser_inAction.implementation.set_rgba (new Gdk.RGBA ({ red: red, green: green, blue: blue, alpha: alpha }));
      if (colorChooser_inAction.colorButton_CCW) colorChooser_inAction.colorButton_CCW.set_rgba (new Gdk.RGBA ({ red: red, green: green, blue: blue, alpha: alpha }));
      if (!keyStack.includes(50)) colorPicked=true;                                         //-- pressed SHIFT will keep colorSelecting
      }
   },

//-- signal handler for window "button-release-event"   
pointer_ungrab=function (window, event)
   {
   if (colorSelecting && colorPicked)
      {
      seat.ungrab ();
      colorSelecting=false; colorPicked=false; colorChooser_inAction=null;
      }
   },

//-- signal handler for window "key-press-event"
onkeypress=function (window, event)
   { 
   if (colorSelecting)
      {
      const keyCode=event.get_keycode();
      if (keyCode[0])
         {
         if (keyCode[1] == 37) { colorPicked=true; pointer_ungrab (); }                     //-- pressed STRG will cancel colorSelecting
         if (keyStack.length==0 || keyCode[1]!=keyStack[keyStack.length-1]) keyStack.push(keyCode[1]);
         }
      }
   },

//-- signal handler for window "key-release-event"
onkeyrelease=function (window, event)
   {
   if (colorSelecting)
      {
      const keyCode=event.get_keycode();
      var i;
      
      if (keyCode[0])
         {
         for (i=0; i<keyStack.length; i++) { if (keyStack[i] == keyCode[1]) { keyStack.splice(i,1); break; } }
         }
      }
   };

handler_register.window=[];
handler_register.window.push (window.connect ("key-press-event",      onkeypress));
handler_register.window.push (window.connect ("key-release-event",    onkeyrelease));
handler_register.window.push (window.connect ("button-press-event",   onColorSelecting));
handler_register.window.push (window.connect ("button-release-event", pointer_ungrab));
}
/* ========================================================================================================================================
   CLASS interface_ColorChooser (implementation)
   ======================================================================================================================================== */

box.add(labelA);
box.add(button_startDialog);

//-- Gtk Color Chooser Dialog
button_startDialog.connect ("button-press-event", function (button, event)
   {
   if (!colorChooserA)
      {
      colorChooserA=new interface_ColorChooser (new Gtk.ColorChooserDialog());
      colorChooserA.connect();
      colorChooserA.implementation.show();
      colorChooserA.implementation.connect ("destroy", function () { colorChooserA.destroy(true); colorChooserA=null; });
      }
   });
   
box.add(new Gtk.Separator ({ orientation:0, margin_top: 10, margin_bottom: 10 }));

//-- Gtk Color Button
box.add(labelB);
colorChooserB=new interface_ColorChooser (new Gtk.ColorButton());
colorChooserB.connect();
box.add (colorChooserB.implementation);
box.add(new Gtk.Separator ({ orientation:0, margin_top: 10, margin_bottom: 10 }));

//-- Gtk Color Chooser Widget
box.add(labelC);
colorChooserC=new interface_ColorChooser (new Gtk.ColorChooserWidget ());
colorChooserC.connect();
box.add(colorChooserC.implementation);

window.show_all();
Gtk.main();
© www.soinside.com 2019 - 2024. All rights reserved.