我正在 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 上吗???
还是一般在其他平台上,你必须自己编写功能?
我已经附加了此功能,供 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();