Ruby: how to renew the path of an image after image has been changed? - ruby

I am trying to build a GUI with ruby Shoes to select a background image for my desktop. As I am struggling with a particular part of my idea I am going to describe just the problem part, the rest works fine.
Here's the code of my ruby Shoes app:
Shoes.app :title => "Images!" do
stack do
#img1 = image "desktop_pic", :width => 200, :height => 100
button "Change image", :margin => 25 do
#img1.path = "/home/njutik/preview_desktop_pic"
end
end
end
Here's what the result looks like when I start my Shoes app:
result_at_beginning
In the background there is a different ruby script running which generates a new background-image and stores it as preview_desktop_pic.
So when I click the Change image-button, the path of #img1 gets adjusted and I see the new image:
result_after_clicking_change_button
That's fine so far. My problem is, that nothing happens when I click the Change image-button again. Of course in the meantime there is already a new image preview_desktop_pic so the code line
#img1.path = "/home/njutik/preview_destkop_pic"
which is executed each time I press the Change image-button should show me a new picture but nothing happens. Even when I delete the preview_desktop_pic from the folder and then press the Change image-button there is still no change at all and all I see is the same picture shown after clicking the Change image-button for the first time.
So my question is: what am I doing wrong and how can I make the Shoes app show the current preview_desktop_pic every time I press the Change image-button?
Any hints would be really great!
Update: After the comment of 7stud I tried to define a singleton method for the button. Like this:
#change_image = button "Change image"
def #change_image.click
#img1.path = "/home/njutik/preview_login_background"
end
#change_image.click
But that did not help - nothing changed.
Then I tried this:
def #img1.reload
#img1.path = "/home/njutik/preview_login_background"
end
button "Change image" do
#img1.reload
end
But this also did not help. I thought that by defining singleton methods I would delete the cache memory.
Any further hints would be really helpful.

I don't think you are doing anything wrong. I think that what you are seeing has to do with image caching, which Shoes uses for efficiency. If ten windows all use the same image, Shoes does not fetch the file from disk (or download the file from the web) for each window. Instead, Shoes caches the image used in the first window, and when the other windows use the same path for the Image, Shoes retrieves the image from the cache. As a result, if the path for your Image doesn't change, it looks like Shoes uses the cached image. It would be nice if an Image in Shoes had a reload() method, which would force Shoes to ignore the cache and go get the image again.
In your app, the first button click works because the Image's path changes from "/desktop_pic" to "/home/njutik/preview_desktop_pic". Subsequent clicks do not change the Image's path.

To change the image, the new image must have a different name than the previous one. I do not know why but it works for me then.

Related

I'm creating a little sound that plays when your mouse hovers over the button "White team" but nothing really happens. I'm using the MouseEnter event

I have been trying to create a sound every time your mouse leaves and enters this button. The code doesn't really work. I have tried this on a local script and a normal script:
script.Parent.MouseEnter:Connect(function()
local sound = script.Parent.Parent.hit
sound:Play()
end)
script.Parent.MouseEnter:Connect(function()
local soundTwo = script.Parent.Parent.hitS
soundTwo:Play()
end)
```[enter image description here][1]
[1]: https://i.stack.imgur.com/5niz4.png -- The explorer of the game (I used script and local script btw and none of them changed anything, but i do think local script would work better for a gui)
You can try adding the following lines at the top of your code.
if not sound.IsLoaded then sound.Loaded:Wait() end
if not soundTwo.IsLoaded then soundTwo.Loaded:Wait() end
Also, both of your functions are for MouseEnter. Try changing one to MouseLeave.

How can I automate a slider using watir-webdriver and ruby?

I am trying to automate a Jquery UI slider using watir-webdriver and ruby but am having no luck. I want to be able to manipulate the slider to either increase or decrease the value. I have searched everywhere and asked a few of my colleagues but no one has an answer. I am attaching a piece of HTML code for the slider. Any help would be much appreciated.
URL link: http://www.whatcar.com/new-car-deals/ (price range slider)
I haven't done any coding for the slider as I have no idea how to go about it. If I could be set on the right path that would be fantastic. Also it seems the HTML code doesn't seem to be showing on the question I am asking.
it's a Jquery widget that appears (looking at the scripts) to respond to key presses once one of the handles has been clicked on. the handles are link objects, inside a pair of divs, the outer one has the ID value 'slider-range'
You should be able to address them via browser.div(:id => 'slider-range').link(:index => n) where n = 0 for the lefthand one and n=1 for the right hand one.
Try this manually first
Click on the left handle for the slider
Then press arrow keys on the keyboard.. it will move 1K(pounds) up or down with each right or left arrow keypress.
Once you have moved it right, click the Home key and it should reset to its min value
repeat above for the right handle but reset it to far right using the End key.
In theory you could fire a click event at the right slider to get focus, then fire off some keypress events to first set it far right (end) followed by enough left arrows to move it down to the top value you want.
Repeat for the left handle, setting it to the left end with the home key, and moving it with right arrow keypresses
I don't have the time right now to experiment further and develop an exact script, but I think you could probably create two little functions even that took an upper and lower range value and did the required number of keypresses to move the lower up from 5K to the right amount, and the upper down from 100k
Note that this thing is very very event driven, it responds (at least when watching the dev tools while playing with it) to being moused over, mousedown, mouseup, etc.. if using click does not work to 'get the attention' of the control so it will respond to keypresses, try using the onmousedown event instead.
Using the code from your answer, to move the left slider to 12K I'd try
browser.div(:id => 'slider-range').link(:index => 0).click #make sure it has focus
browser.div(:id => 'slider-range').link(:index => 0).send_keys :home #set to 5K
7.times do
browser.div(:id => 'slider-range').link(:index => 0).send_keys :arrow_right
end
Thank you very much Chuck. I got it working. Here is the script I used:
#browser.link(:xpath, "/html/body/div/div[3]/div[4]/div/div/div/a").send_keys :arrow_right
Still needs a bit of tweaking, but I should be ok now.
This worked great. We just added these sliders to our website and my first thought was "how are we going to automate that!?"
I wanted to add an example will full code that is available publicly for people to experiment with. The following interacts with an example on jqueryui.com.
require "watir-webdriver"
#browser = Watir::Browser.new :chrome
#browser.goto "http://jqueryui.com/slider/#default"
#browser.frame(:class => "demo-frame").span(:class =>"ui-slider-handle").click
#browser.frame(:class => "demo-frame").span(:class =>"ui-slider-handle").send_keys :home
puts "clicked home"
7.times do
#browser.frame(:class => "demo-frame").span(:class =>"ui-slider-handle").send_keys :arrow_right
end
To achieve this using Rspec and Watir-Webdriver with Page-Object gem I used:
div(:slider, id: "slider-range") #in page file
#then in spec file
browser.slider_element.input.send_keys :home
This answer comes from http://watir.com/guides/special-keys/

GTK - Don't highlight buttons on select / hover

I'm trying to write a kiosk GUI in ruby/gtk on ubuntu. I'm pretty fluent in ruby, but new to writing GUIs and not great with linux.
I'm using a touch screen, and am using our own images for buttons, e.g.
button_image = Gtk::Image.new(Gdk::Pixbuff.new "images/button_image.png")
#button = Gtk::Button.new
#button.add(button_image)
#button.set_relief(Gtk::RELIEF_NONE)
My issue is that when the buttons are pressed or remain selected (or hovered over, although this is less relevant with a touch screen), gtk shows fat, square borders around them. Obviously it's applying gtk's prelight / selected / active lighting to the buttons. I've tried changing the button properties in various ways, and also tryied hacking apart my theme, and while I can modify how the highlighting looks, I can't seem to completely get rid of it. Changing the color of the highlight via my theme is easy, but if I remove my setting there's still a default I can't get rid of.
Does anyone know if there's a way to stop it, or possibly make it transparent? Thanks in advance!
Sounds like you want to use exactly your image for the whole button, instead of putting an image inside the normal GtkButton - but still use all the normal behavior of the button.
The easiest way to do this is to just override the drawing. If you are on gtk2, connect to the "expose-event" signal, do your drawing there, and return true so that the default handler doesn't get run. If you are on gtk3, connect to the "draw" signal and do the same.
I tried meddling with the drawing as Federico suggested, but found that the most direct way to address this was instead to use an event box rather than a button. Event boxes accept clicks just like buttons, but don't respond to selecting, hovering, etc. In ruby, the code looks like this:
image = Gtk::Image.new("myfile.png")
event_box = Gtk::EventBox.new.add(image)
event_box.visible_window = false
event_box.signal_connect("button_press_event") do
puts "Clicked."
end
Most of this is exactly like a button; the *visible_window* method, obviously, keeps the event box from being visible under the button image.

How to design a linear GUI program

I'm making a simple Qt application. It has 4 screens/pages:
Start import
Select folder to import images to
Accept or reject each image in folder, and when no images left:
"No images left" and an OK button.
I can't figure out the best way to implement this. I started off with a QWidget, but this quickly got unmanageable.
Is a QWizard too constrained?
EDIT: Part of the problem with QWizard is it seems to always have "Back" and "Next" buttons. I don't want those as options in this program, so this leads me to believe that a wizard isn't exactly what I'm after.
I'm going to disagree slightly on using a QWizard here. It would be fairly easy to do, but in this case I think it might be easier to just use a QStackedWidget and swap the widget shown based on what you want the user to be able to do. This is likely what is done inside QWizard anyway, without some of the complication for running the buttons and moving back and forth. You also might want to take a look at the state machine stuff they're looking at adding soon, since you're application could so easily be split into states.
I think a QWizardPage is your best bet.
You can disable the 'back' on a QWizardPage by using setCommitPage(True) on it.
You'll also have to override nextId for the 'variable' amount of QWizardPages you want in between step 2 and 4.
here (basic) and here are examples of QWizards.
You can make QWizardPages for your screens and add them to a QWizard. With registerField() you can register fields to communicate between pages.
EDIT:
I didn't test this, but i guess you can control the button layout of QWizard with
setButtonLayout
Create a dialog with a "Start Import" button on top. When the user clicks this:
Populate a QFormLayout :
The layout should have a checkbox and the label is the name of the picture to import. I'm not sure of your requirements, but you could also display a thumbnail of the image.
The user just checks the images he wants.
Then at the bottom have a "Save..." button. When the user clicks this, a Save As dialog appears. You save all the checked images, discard the others.
If there are no images, change the "Save..." button text to "OK", and display a QLabel with the "No images left" string. You can switch between the QLabel and QFormLayout using a QStackedWidget.
Checkout this article on QFormLayout: http://doc.trolltech.com/qq/qq25-formlayout.html
Option: Get rid of the "Start Import" button. Have the app automatically populate the QFormLayout on startup (possibly in constructor if its fast enough).

How do I change the icon of my Shoes App?

I was wondering if it was possible to change the my Shoes app's icon? I imagine its style-oriented, but I haven't been able to find anything on it.
Is this possible?
You can do it in Green Shoes, but you have to go under the hood a bit. Here's some very simple code I wrote for SciRuby:
class Shoes
class App
def icon filename=nil
filename.nil? ? win.icon : win.icon = filename
end
class << self
def default_icon= filename
Gtk::Window.set_default_icon(filename)
end
end
end
end
The second method is optional; you can use it to set the icon for your whole app, I think. The first method sets the icon for the current window, and you would use it like so:
DIR = Pathname.new(__FILE__).realpath.dirname.to_s
ICON_PATH = File.join(DIR, '..', 'static', 'my-icon.png')
# ...
Shoes.app :title => "My App" do
icon ICON_PATH
end
And for the default:
Shoes::App.default_icon = ICON_PATH
I use a 128x128 png file. I tried a 500x500 one and it didn't work properly. In the code above, ICON_PATH, from the root of your project directory, should be ./static/my-icon.png.
You may also need to require "gtk2" somewhere for the default_icon= method.
I don't believe this is possible from within Shoes. This is based on extensive searching, both online and in the source code.
However, there are a couple things external to Shoes that work. One is to simply change the file #{DIR}/static/shoes-icon.png, which is where the runtime pulls its icon from. The other is to change the hardcoded value in the file libshoes.so (or your OS's equivalent); you could use a hex editor, or any other editor that wouldn't mess the file up. Note that for the hardcoded editing to work without crashing, you have to replace the hardcoded string with something of the same length.
Use IcoFx. _why himself suggested this utility on the mailing list. You will find the instruction in the tutorial section of the icoFX website.
So far, I am not sure that this is actually possible. in OS X, I was able to modify the package contents to change what the plist is pointing to in terms of icons. However, when the application runs, it uses the Shoes' runtime icon.
I have no clue how you'd do this on Windows.

Resources