Streamlit dynamic text based on slider below - streamlit

Streamlit makes dynamic text, based on a slider value, super easy:
value = st.slider('Slide me', 0, 100, 50)
if value > 80:
st.warning('Value is too big!')
How do I issue this warning above the slider? This doesn't work:
if value > 80:
st.warning('Value is too big!')
value = st.slider('Slide me', 0, 100, 50)
The warning will never get displayed when sliding over 80 (actually I'd get an error that value is undefined so I have to set value = 0 at the top).

You can declare a container (or using st.empty) above the slider and then fill it in the conditional that runs after the slider:
container = st.container()
value = st.slider('Slide me', 0, 100, 50)
if value > 80:
container.warning('Value is too big!')
It could be possible that st.warning does not go "into" the container, then you'd have to define your own warning banner to put in there. Sorry, cannot test it currently.

Related

awesome-wm wibox not reacting to mouse signals when input_passthrough is true

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.)

GDI - Unexpected result for the OffsetRgn() function

I'm using Embarcadero RAD Studio C++ builder XE7.
For a drawing function using the Windows GDI, I need to add a clip region to the device context of a canvas.
By testing my code, I noticed that sometimes the clipping region was smaller than the expected size. I searched why and I found a strange behavior of the OffsetRgn() function which lets me a little puzzled.
To apply the clip region, I use a code similar to the following:
std::unique_ptr<TBitmap> pBitmap(new TBitmap());
pBitmap->PixelFormat = pf32bit;
pBitmap->AlphaFormat = afDefined;
pBitmap->SetSize(60, 7);
TCanvas* pCanvas = pBitmap->Canvas;
::SelectClipRgn(pCanvas->Handle, NULL);
const TRect sourceRect = pCanvas->ClipRect;
HRGN pClipRegion = ::CreateRectRgn(50, -2, 60, 8);
::SelectClipRgn(pCanvas->Handle, pClipRegion);
const TRect intermediateRect = pCanvas->ClipRect;
const int deltaX = pCanvas->ClipRect.Left - 50;
const int deltaY = pCanvas->ClipRect.Top - (-2);
::OffsetRgn(pClipRegion, -deltaX, -deltaY);
::SelectClipRgn(pCanvas->Handle, pClipRegion);
const TRect finalRect = pCanvas->ClipRect;
NOTE written like this and out of his context, the above code does not really make sense, and I know it's illogical. Please do not judge its quality, this is not the purpose of my question. I gathered several excerpts that I grouped into an executable code putting the problem forward.
The hardcoded values are an example of values I get in my application when the problem occurs. If I execute the above code, I measure:
left = 0, top = 0, right = 60, bottom = 7 in sourceRect value
left = 50, top = 0, right = 60, bottom = 7 in intermediateRect value
left = 50, top = 0, right = 60, bottom = 6 in finalRect
I however expected that the bottom value should also be equals to 7 in finalRect, which is the canvas limit, as I only moved the region and nothing else. So why it's value become suddenly smaller than expected?
So I finally found the substance of the case. Based on this post:
Why does calling GetRgnBox on the result of GetClipRgn return a very different rect than GetClipRect?
The clip region is applied in logical units relatively to the canvas origin, whereas the clipping rectangle I tried to apply was measured in pixels from a [0, 0] origin.
As I incorrectly thought in my code that the origin was always [0, 0] for the both systems, the resulting region could be incorrect in several special cases, causing this strange shifting I sometimes noticed between the clipping really applied and which I expected.
Measuring the canvas origin with the GetWindowOrgEx() function highlighted the issue.
However for the above shown case, issue came because the clip region was moved by an offset of -2, taking so the value of -4 on top and 6 on bottom, which is then clipped to fit the canvas bounds while the clip region is applied, resulting to a clipping with value of 0 on top and 6 on bottom.

how to stop Vpython from being unresponsive

Im fairly new to Vpython and Ive created a simulation for circular motion. I tried adding controls to the simulation and so far I am able to pause the simulation but when i do pause it, the entire control panel becomes unresponsive and i am unable to resume the simulation. Does anyone know why this may be or how i can fix this?
def playorpause(self, goorno):
self.pause = goorno
def actual_sim(self):
c = controls() # Create controls window
# Create a button in the controls window:
# b = Button(pos=(-50, 0), width=60, height=60, text="Pause", action=lambda: self.change)
# play = Button(pos=(50, 0), width=60, height=60, text="Play", command = self.play_sim)
b = button(pos=(-50, 0), width=60, height=60, text='Pause', action=lambda: self.playorpause(True))
play = button(pos=(50,0), width = 60, height = 60, text = "play", action =lambda: self.playorpause(False))
def loop():
#### simulation code
if self.pause == False:
loop()
I'm not sure, because I don't really understand your code, but a repetitive loop needs to include a rate statement. Otherwise the program will lock up, unable to output anything.

R gSignalConnect

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.

How to move raphael set?

I have a set of objects grouped with Raphael.set(). What I want to do is to move the whole set (change x and y coordinates) from one place to another.
How I can move the whole set as a single object?
What I found already is that when an .attr({X: newX, Y: newY}) is called every element from the set will be positioned on this coordinated which will result in piling all the elements in one place.
Edit: Refer to Rick Westera's answer as translate is now deprecated.
Use .translate(x, y), example:
var paper = Raphael('stage', 300, 300);
var set = paper.set();
set.push(paper.rect(0,0,30,50));
set.push(paper.circle(40,50,10));
set.push(paper.path("M 0 70 L 100 70"));
set.translate(100, 100);
http://jsfiddle.net/q4vUx/
Use transform('Tx,y') as translate is deprecated. For example:
var paper = Raphael('stage', 300, 300);
var set = paper.set();
set.push(paper.rect(0, 0, 100, 100));
set.push(paper.text(50, 50, "Foo"));
set.transform("T100,50");
Note that there are two types of translation:
'T100,50' will move the set 100px to the right and 50 down using the global axis.
't100,50' will do the same but using the set's local axis (ie. it depends on which way the set has been rotated).
This is what i'm using to reposition a set, in my case is a set of fonts returned by Paper.print() but i think it should work with any kind of set.
var glyphs = paper.print(0, 0, text, paper.getFont(font, 800), fontSize).hide();
glyphs.transform('...T' + [posx, posy] + 'R' + [angle, posx, posy]).show();
hope it helps.

Resources