I am using getGraphicsEventEnv to get events over an R plot. Previously, scroll up or down were encoded in the event handler but now, the test code posted on a related bug fix returns an empty whether it is scroll up or scroll down.
Is there a new way to get those events?
example code:
mousemove <- function (buttons, x, y){
cat("mousemove")
print(buttons)
NULL
}
mouseclick <- function (buttons, x, y){
cat("mouseclick")
print(buttons)
NULL
}
mouserelease <- function (buttons, x, y){
cat("mouserelase")
print(buttons)
NULL
}
keystroke <- function (key){
cat("keystroke")
print(key)
NULL
}
if (identical(version$os, "linux-gnu")){
x11(type = "Xlib")
} else {
x11()
}
par(mar = c(0, 0, 0, 0))
plot.new()
getGraphicsEvent(onMouseMove = mousemove, onMouseDown = mouseclick, onMouseUp = mouserelease, onKeybd = keystroke)
On scroll this selects both mouseclick and mouserelease on a loop but with no buttons given, impossible to use. Before, on X11, we had special "buttons" returned for "scroll up" and "scroll down". To me this is a regression, hopefully replaced by a feature somewhere but where is the feature?
Related
In R, is it possible to create a function that sets a default answer after some defined amount of time for menu (or to create something that works like that)?
My best not-working idea is to try using {future}.
Example
library(future)
plan(multisession(workers = 2))
zero_after_s <- function(s) Sys.sleep(s)
zero_after_t_menu <- function(
choices, graphics = FALSE, title = NULL, t = 0
) {
if (t == 0) {
menu(choices, graphics, title)
} else {
time_passed <- future(zero_after_s(t))
while (!resolved(time_passed)) {
return(menu(choices, graphics, title))
}
0
}
}
switch(
zero_after_t_menu(c("List letters", "List LETTERS"), t = 5) + 1,
cat("Nothing done (maybe t seconds passed without answers)\n"),
letters,
LETTERS
)
This cannon work because while will cycle and check its argument only when its body finishes the cycle, i.e., the user has answered to menu. I put this just as a tentative idea of a solution.
I try to call menu from the future (it seems more promising), but I cannot interact with it anymore (obviously), and anyway, it throws an error because menu cannot be used non-interactively :-)
zero_after_t_menu <- function(
choices, graphics = FALSE, title = NULL, t = 0
) {
if (t == 0) {
menu(choices, graphics, title)
} else {
res %<-% future(menu(choices, graphics, title), earlySignal = TRUE)
Sys.sleep(t)
if (resolved(res)) res else 0
}
}
Any ideas or suggestions?
Thank you,
Corrado.
PS: my actual use case is a loop across some (many) files to be (slowly) preprocessed. Under some conditions, I would like to have the opportunity to select what to do. Still, given that it is a very long execution, during nights or not-monitoring time, I would like a safe default selection (e.g., "skip that iteration for the future") to be made automatically to permit the loop to go on without my supervision.
I need help with GameMaker Studio 2 v2.3.2.556 project.
My clicking & dragging mechanism has two objects: an object called obj_iron that is being dragged, and an object called obj_cursor that is invisible and always follows the mouse. When I use the cursor to drag the iron, nothing happens. How do I make it so I can drag the iron using the cursor?
Code in obj_cursor in the Step Event
//Making the cursor move toward the mouse
global.picked_up_iron = 0
x = mouse_x
y = mouse_y
//Making the cursor small
image_xscale = 0.1
image_yscale = 0.1
//Checking if the cursor collided with obj_iron
if place_meeting(x,y,obj_iron)
{
//Checking if the mouse is held and the cursor is not collided with another obj_iron
if mouse_check_button(mb_left) and (global.picked_up_iron == 0 or global.picked_up_iron == other)
{
//Moving the dragged piece of obj_ironto the obj_cursor's location
var picked_up_iron = other
picked_up_iron.x = x - picked_up_iron.sprite_width / 2
picked_up_iron.y = y - picked_up_iron.sprite_height / 2
//Telling every the object what the dragged piece of obj_iron is
global.picked_up_iron = picked_up_iron
}
}
else if !mouse_check_button(mb_left)
{
//Resetting the value of the current piece of obj_iron
global.picked_up_iron = 0
}
If there are multiple of the same object in the same room, then place_meeting() does not know which kind of object is selected.
Maybe you can try out Instance_Place
var iron = instance_place(x, y, obj_iron);
This way, the iron returns the object the cursor is currently colliding with.
Basically, what I'm trying to do is have a sidebar, and have it show up when I move my mouse to the left edge of the screen, and have the sidebar disappear when I move my mouse TOO MUCH away from the sidebar.
So I made three widgets:
one that's one pixel wide on the side and that, when it detects the mouse entering, shows the sidebar
the actual sidebar
and a widget that's wider than the sidebar, is fully transparent, has input_passthrough set to true, and its only purpose is to look for the "mouse::leave" signal and when the mouse leaves, it would make itself and the sidebar disappear.
I got most of it to work but there's this particular error that I can't solve:
The wibox function takes as argument a table of fields. If you look through the code I provided, you can notice that the input_passthrough field of the sidebar_visible_limit hasn't been put in the body of the table, but supplied afterwards, right after the creation of the widget.
The problem with this is that it simply doesn't close the sidebar or itself when the mouse leaves. It doesn't detect the mouse leaving.
BUT if put the input_passthrough = true in the table provided to the wibox function, like this:
bar.sidebar_visible_limit = wibox({
x = 0,
y = 0,
ontop = false,
visible = false,
width = bar.sidebar.width + dpi(100),
height = bar.sidebar.height,
bg = '#000000',
opacity = 0.3, -- when it's all done this will be '0'
input_passthrough = true
})
then everything works fine, EXCEPT that now it doesn't allow input to pass through.
I would greatly appreciate an explanation as to why this happens.
This is the code:
awful = require("awful")
local wibox = require("wibox")
local naughty = require("naughty")
local gears = require("gears")
local beautiful = require("beautiful")
xresources = require("beautiful.xresources")
dpi = xresources.apply_dpi
bar = {}
-- make the sidebar
bar.sidebar = wibox({
x = 0,
y = 0,
ontop = false,
visible = false,
width = beautiful.sidebar_width or dpi(450),
bg = beautiful.sidebar_bg or "#2f2e3a",
type = "dock",
height = beautiful.sidebar_height or awful.screen.focused().geometry.height,
})
-- Hide sidebar when mouse leaves too much from the sidebar
-- It's incorporated along in the same table with the sidebar so the users
-- can implement these however they want, e.g. in the 'keys.lua' module
bar.sidebar_visible_limit = wibox({
x = 0,
y = 0,
ontop = false,
visible = false,
width = bar.sidebar.width + dpi(100),
height = bar.sidebar.height,
bg = '#000000',
opacity = 0.3, --when it's all done this will be '0'
})
bar.sidebar_visible_limit.input_passthrough = true
-- Show sidebar when mouse touches edge
local sidebar_displayer = wibox({
x = 0,
y = 0,
height = bar.sidebar.height,
ontop = true,
width = 1,
visible = true,
opacity = 0,
input_passthrough = true
})
function toggle_bar()
-- they have to be in this order, so the sidebar will show first,
-- and then the wibox that will close the sidebar when the mouse leaves
-- second. If you do it the other way around, then if you go with the
-- mouse on the sidebar-closing wibox , then if you try to go back
-- to the sidebar, it will close it because it's 'left' the widget.
-- That's why you have the sidebar-closing wibox on top and allow
-- input_passthrough for the sidebar-closing wibox
bar.sidebar.visible = not bar.sidebar.visible
bar.sidebar.ontop = not bar.sidebar.ontop
bar.sidebar_visible_limit.visible = not bar.sidebar_visible_limit.visible
bar.sidebar_visible_limit.ontop = not bar.sidebar_visible_limit.ontop
end
bar.sidebar_visible_limit:connect_signal( "mouse::leave", toggle_bar )
sidebar_displayer:connect_signal( "mouse::enter", toggle_bar )
You could use a mousegrabber to detect the position of the mouse:
bar.sidebar.ontop = true
function show_sidebar()
bar.sidebar.visible = true
mousegrabber.run(function(mouse)
if mouse.x > bar.sidebar.width + dpi(100) then
hide_sidebar()
return false
end
return true
end)
end
function hide_sidebar()
bar.sidebar.visible = false
end
Alternatively, you could use the same mousegrabber to decide when to show the sidebar too:
bar.sidebar.ontop = true
function show_sidebar()
bar.sidebar.visible = true
end
function hide_sidebar()
bar.sidebar.visible = false
end
mousegrabber.run(function(mouse)
if bar.sidebar.visible then
if mouse.x > bar.sidebar.width + dpi(100) then
hide_sidebar()
end
else
if mouse.x == 1 then
show_sidebar()
end
end
return true
end)
I think this is nicer than creating an invisible wibox over the whole screen.
I would greatly appreciate an explanation as to why this happens.
I think the X11 server reports mouse enter/exit relative to the input region of a window. With input_passthrough, the input region becomes empty. This means that the X11 server will now report the mouse pointer to be inside the window beneath your wibox and not inside of the wibox itself.
BUT if put the input_passthrough = true in the table provided to the wibox function then everything works fine, EXCEPT that now it doesn't allow input to pass through.
In other words: In this case the input_passthrough property is not set. Seems like you found one of the properties that cannot be set this way. ;-)
Since I guess you also want some ideas on how you can do what you are trying to do: If you are running a compositing manager (xcompmgr, compton, ...), you could make a wibox with a completely transparent background. That way, the X11 server will "think" that the window is there and report input events relative to it, but the wibox will not actually be visible on screen.
(And if you don't have a compositing manager: Make a widget that displays your wallpaper with the proper offset. A hint on how to do this can be found by reading /usr/share/awesome/lib/wibox/drawable.lua, the part that begins with if not capi.awesome.composite_manager_running then and that does something with the wallpaper. Feel free to ask for more details if necessary.)
I'm trying to learn how to signalConnect buttons to labels. For example, I've made a button labeled "+" and created a label initialized to "0". I would like the button to adjust the label by adding one every time the button is clicked. I have constructed the button and the window for it. My question is, how do I use the gSignalConnect() function to perform this?
Thanks,
Joe
-- Here is my code
win <- gtkWindow(show = FALSE)
win$Resize( width = 700, height = 500)
win$SetTitle(title = "Measurement GUI")
frame <- gtkFixedNew()
win$add(frame)
plus<-gtkButtonNewWithLabel("+")
plus$setSizeRequest(80,35)
frame$put(plus, 10, 50)
label <-gtkLabelNew("0")
frame$put(label, 100, 80)
win$ShowAll()
Try
callback <- function(btn, ...) {
old <- as.numeric(label$getText())
label$setText(old + 1)
}
gSignalConnect(plus, "clicked", callback)
To use gSignalConnect, you will need to know which signals (and their signatures) are available for your widget. ?gtkButton will give this information.
I have an application in Flex 4 with a map, a database of points and a search tool.
When the user types something and does the search it returns name, details and coordinates of the objects in my database.
I have a function that, when i click one of the results of my search, it zooms the selected point of the map.
The question is, i want a function that zooms all the result points at once. For example if i search "tall trees" and it returns 10 points, i want that the map zooms to a position where i can see the 10 points at once.
Below is the code im using to zoom one point at a time, i thought flex would have some kind of function "zoom to group of points", but i cant find anything like this.
private function ResultDG_Click(event:ListEvent):void
{
if (event.rowIndex < 0) return;
var obj:Object = ResultDG.selectedItem;
if (lastIdentifyResultGraphic != null)
{
graphicsLayer.remove(lastIdentifyResultGraphic);
}
if (obj != null)
{
lastIdentifyResultGraphic = obj.graphic as Graphic;
switch (lastIdentifyResultGraphic.geometry.type)
{
case Geometry.MAPPOINT:
lastIdentifyResultGraphic.symbol = objPointSymbol
_map.extent = new Extent((lastIdentifyResultGraphic.geometry as MapPoint).x-0.05,(lastIdentifyResultGraphic.geometry as MapPoint).y-0.05,(lastIdentifyResultGraphic.geometry as MapPoint).x+0.05,(lastIdentifyResultGraphic.geometry as MapPoint).y+0.05,new SpatialReference(29101)).expand(0.001);
break;
case Geometry.POLYLINE:
lastIdentifyResultGraphic.symbol = objPolyLineSymbol;
_map.extent = lastIdentifyResultGraphic.geometry.extent.expand(0.001);
break;
case Geometry.POLYGON:
lastIdentifyResultGraphic.symbol = objPolygonSymbol;
_map.extent = lastIdentifyResultGraphic.geometry.extent.expand(0.001);
break;
}
graphicsLayer.add(lastIdentifyResultGraphic);
}
}
See the GraphicUtil class from com.esri.ags.Utils package. You can use the method "getGraphicsExtent" to generate an extent from an array of Graphics. You then use the extent to set the zoom factor of your map :
var graphics:ArrayCollection = graphicsLayer.graphicProvider as ArrayCollection;
var graphicsArr:Array = graphics.toArray();
// Create an extent from the currently selected graphics
var uExtent:Extent;
uExtent = GraphicUtil.getGraphicsExtent(graphicsArr);
// Zoom to extent created
if (uExtent)
{
map.extent = uExtent;
}
In this case, it would zoom to the full content of your graphics layer. You can always create an array containing only the features you want to zoom to. If you find that the zoom is too close to your data, you can also use map.zoomOut() after setting the extent.
Note: Be careful if you'Ve got TextSymbols in your graphics, it will break the GraphicUtil. In this case you need to filter out the Graphics with TextSymbols
Derp : Did not see the thread was 5 months old... Hope my answer helps other people