while loop blocks reading callbacks from gui - user-interface

I'm trying to add a stop button to a GUI which can be used to abort the gui and execution of a background while loop. Consider the code:
function pushFun(button)
disp("Push!")
endfunction
h = figure(1);
set(h,'UserData',1);
button = uicontrol(h, 'Style', 'pushbutton', 'String', 'Stop',..
'Position', [0 0 60 25], 'callback', 'pushFun',..
"callback_type", 2);
which works perfectly fine. But the code:
function stopgui()
global guistop;
guistop = %t;
endfunction
h = figure(1);
set(h,'UserData',1);
global guistop
guistop = %f;
button = uicontrol(h, 'Style', 'pushbutton', 'String', 'Stop',..
'Position', [0 0 60 25], 'callback', 'stopgui',..
"callback_type", 2);
while ~guistop
// some code here
sleep(100)
end
does not respond to the pushbutton interactions. I would appreciate if you could help me know what is wrong and how I can solve it.
P.S. similar discussions: one, two.

You have to use callback type 10 (prioritary (or non-interruptible) Scilab instructions):
button = uicontrol(h, 'Style', 'pushbutton', 'String', 'Stop',..
'Position', [0 0 60 25], 'callback', 'stopgui',..
'callback_type', 10);

Related

Interacting with sg.image on a clic or a mouse fly over

I made a code using pysimplegui. it basically shows some images from a database based on a scanned number. it works but sometimes it could be useful to be able to increase the size of the image + it would make my user interface a bit more interactive
i want to have the possibility to either:
when i fly over the image with the mouse, i want the image to increase in size
have the possibility to clic on the image and have a pop-up of the image showing up (in a bigger size)
i am not sure on how to interact with a sg.image()
Below you will find a trunkated part of my code where i show my way of getting the image to show up.
layout = [
[
sg.Text("Numéro de boîte"),
sg.Input(size=(25, 1), key="-FILE-"),
sg.Button("Load Image"),
sg.Button("Update DATA"),
sg.Text("<- useless text ")
],
[sg.Text("Indicateur au max" , size = (120, 1),font = ("Arial", 18), justification = "center")],
[sg.Image(key="-ALV1-"),sg.Image(key="-ALV2-"), sg.Image(key="-ALV3-"), sg.Image(key="-ALV4-"), sg.Image(key="-ALV5-")],
[sg.Image(key="-ALV6-"),sg.Image(key="-ALV7-"), sg.Image(key="-ALV8-"), sg.Image(key="-ALV9-"), sg.Image(key="-ALV10-")],
[sg.Text("_" * 350, size = (120, 1), justification = "center")],
[sg.Text("Indicateur au milieu" , size = (120, 1),font = ("Arial", 18), justification = "center")],
[sg.Image(key="-ALV11-"),sg.Image(key="-ALV12-"), sg.Image(key="-ALV13-"), sg.Image(key="-ALV14-"), sg.Image(key="-ALV15-")],
[sg.Image(key="-ALV16-"),sg.Image(key="-ALV17-"), sg.Image(key="-ALV18-"), sg.Image(key="-ALV19-"), sg.Image(key="-ALV20-")],
[sg.Text("↓↓↓ ↓↓↓" , size = (120, 1),font = ("Arial", 18), justification = "center")],
]
ImageAlv1 = Image.open(PathAlv1)
ImageAlv1.thumbnail((250, 250))
bio1 = io.BytesIO()
ImageAlv1.save(bio1, format="PNG")
window["-ALV1-"].update(data=bio1.getvalue())
Using bind method for events, like
"<Enter>", the user moved the mouse pointer into a visible part of an element.
"<Double-1>", specifies two click events happening close together in time.
Using PIL.Image to resize image and io.BytesIO as buffer.
import base64
from io import BytesIO
from PIL import Image
import PySimpleGUI as sg
def resize(image, size=(256, 256)):
imgdata = base64.b64decode(image)
im = Image.open(BytesIO(imgdata))
width, height = size
w, h = im.size
scale = min(width/w, height/h)
new_size = (int(w*scale+0.5), int(h*scale+0.5))
new_im = im.resize(new_size, resample=Image.LANCZOS)
buffer = BytesIO()
new_im.save(buffer, format="PNG")
return buffer.getvalue()
sg.theme('DarkBlue3')
number = 4
column_layout, line = [], []
limit = len(sg.EMOJI_BASE64_HAPPY_LIST) - 1
for i, image in enumerate(sg.EMOJI_BASE64_HAPPY_LIST):
line.append(sg.Image(data=image, size=(64, 64), pad=(1, 1), background_color='#10C000', expand_y=True, key=f'IMAGE {i}'))
if i % number == number-1 or i == limit:
column_layout.append(line)
line = []
layout = [
[sg.Image(size=(256, 256), pad=(0, 0), expand_x=True, background_color='green', key='-IMAGE-'),
sg.Column(column_layout, expand_y=True, pad=(0, 0))],
]
window = sg.Window("Title", layout, margins=(0, 0), finalize=True)
for i in range(limit+1):
window[f'IMAGE {i}'].bind("<Enter>", "") # Binding for Mouse enter sg.Image
#window[f'IMAGE {i}'].bind("<Double-1>", "") # Binding for Mouse double click on sg.Image
element = window['-IMAGE-']
now = None
while True:
event, values = window.read()
if event == sg.WINDOW_CLOSED:
break
elif event.startswith("IMAGE"):
index = int(event.split()[-1])
if index != now:
element.update(data=resize(sg.EMOJI_BASE64_HAPPY_LIST[index]))
now = index
window.close()

error bad argument #1 to draw (drawable expected, got table), trying to animate a sprite for the main character

new to Lua and love. I'm trying to animate a character for my platform game. I know my key binds and all work but I have never animated before, so I don't even know if I'm going in the right direction or not. I've tried looking up guides so I can compare my code to someone else's but it seems that most of them are outdated. Originally my player was just a white rectangle but now im trying to actually give it a sprite.
Here's my main.lua
local STI = require("sti")
local anim8 = require('anim8')
require("MC")
function love.load()
map1 = STI("map/map1.lua", {"box2d"})
Physics = love.physics.newWorld(0,0)
Physics:setCallbacks(beginContact, endContact)
map1:box2d_init(Physics)
map1.layers.Solid.visible = false
background = love.graphics.newImage("assets/Base pack/bg.png")
mc:load()
end
function love.update(dt)
Physics:update(dt)
mc:update(dt)
end
function love.draw()
love.graphics.push()
love.graphics.scale(5,3)
love.graphics.draw(background)
love.graphics.pop()
map1:draw(0, 0, 2, 2)
love.graphics.push()
love.graphics.scale(2,2)
mc:draw()
love.graphics.pop()
end
function love.keypressed(key)
mc:jump(key)
if keypressed == "escape" then
love.event.quit(0)
end
end
function beginContact(a, b, collision)
mc:beginContact(a, b, collision)
end
function endContact(a, b, collision)
mc:endContact(a, b, collision)
end
I don't believe that there is anything wrong with my main but i think it's necessary to recreate the problem (sorry if it makes this too long). Now my mc.lua is where I'm having the problem since im trying to animate the player themselves by giving them a jump idle and walk animation, I think i will give them a damaged and death animation later.
local anim8 = require('anim8')
mc = {}
spr_mc_walk = love.graphics.newImage("assets/mc sprites/1 Pink_Monster/Pink_Monster_Walk_6.png")
local w = anim8.newGrid(32, 32, spr_mc_walk:getWidth(), spr_mc_walk:getHeight())
walk = anim8.newAnimation(w('1-6', 1), 0.1)
spr_mc_idle = love.graphics.newImage("assets/mc sprites/1 Pink_Monster/Pink_Monster_Idle_4.png")
local i = anim8.newGrid(32, 32, spr_mc_idle:getWidth(), spr_mc_idle:getHeight())
idle = anim8.newAnimation(i('1-4', 1), 0.1)
spr_mc_jump = love.graphics.newImage("assets/mc sprites/1 Pink_Monster/Pink_Monster_Jump_8.png")
local j = anim8.newGrid(32, 32, spr_mc_jump:getWidth(), spr_mc_jump:getHeight())
jump = anim8.newAnimation(j('1-8', 1), 0.1)
obj_mc = walk
function mc:load()
self.x = 100
self.y = 0
self.width = 20
self.height = 60
self.xvel = 0
self.yvel = 0
self.maxspeed = 200
self.acceleration = 4000 -- max speed
self.friction = 3900 -- how long it takes them to reach max speed
self.gravity = 1000
self.jumpAmount = -500
self.grounded = false
self.physics = {}
self.physics.body = love.physics.newBody(Physics, self.x, self.y, "dynamic")
self.physics.body:setFixedRotation(true)
self.physics.shape = love.physics.newRectangleShape(self.width, self.height)
self.physics.fixture = love.physics.newFixture(self.physics.body, self.physics.shape)
end
function mc:draw()
love.graphics.draw(obj_mc, self.x, self.y)
end
This is most of my mc or player function, except for movement and such but this has all the code that I'm confused with. I'm pretty sure I wrote the code right I'm just confused on how to actually implement it now that I have it written down. I thought just doing the draw function would actually draw the idle version of the character but then there's where I get the error. If you need anymore code or anymore details just let me know.
The error that this is happening at is
Error
MC.lua:41: bad argument #1 to 'draw' (Drawable expected, got table)
Traceback
[C]: in function 'draw'
MC.lua:41: in function 'draw'
main.lua:30: in function 'draw'
[C]: in function 'xpcall'
I haven't done any of that for a while, but I believe obj_mc, in this case, is a table of the frames. You need to loop through them during update.
local anim8timer = 0
local anim8index = 1
local anim8rate = 0.2 -- pick an animation rate that looks good for your game
function mc:update( dt )
anim8timer = anim8timer +dt -- add delta time
if anim8timer >= anim8rate then
anim8timer = anim8timer -anim8rate -- reset timer
anim8index = anim8index +1 -- next frame
if anim8index > #obj_mc then anim8index = 1 end -- loop frames
end
end
function mc:draw()
love.graphics.draw( obj_mc[ anim8index ], self.x, self.y )
end
They may have a built-in function that accomplishes some of that, so look for anything that resembles this in the Love2D forum.

Excel 'shape' ends up a linked object from VBA

I'm bringing in a shape via code to be a logo at the bottom of a report, but it ends up being handled differently from the normal way Excel handles shapes. My shape disappears if the source (or indeed destination) file is moved - it's handled as though it's a link, so doesn't show, whereas, if I'm using normal "Insert tab ==>Picture" it just keeps the picture visible no matter what.
This is the code I'm using, can anyone see why it's doing it the way it is?
ActiveSheet.Pictures.Insert(MyFileAndPath).Select
Set MyLogo = Selection
'Format the size and position
With MyLogo
.ShapeRange.ScaleHeight 1#, True, msoScaleFromTopLeft
.ShapeRange.ScaleWidth 1#, True, msoScaleFromTopLeft
xWidth = .ShapeRange.Width
xHeight = .ShapeRange.Height
xRatio = xWidth / xHeight
.ShapeRange.LockAspectRatio = msoTrue
.ShapeRange.Width = 285
.ShapeRange.Height = 285 / xRatio
.ShapeRange.Left = shtCover.Range("LogoBotRight").Left + shtCover.Range("LogoBotRight").Width - MyLogo.ShapeRange.Width
.ShapeRange.Top = shtCover.Range("LogoBotRight").Top + shtCover.Range("LogoBotRight").Height - MyLogo.ShapeRange.Height
End With
Replace:
ActiveSheet.Pictures.Insert(MyFileAndPath).Select
Set MyLogo = Selection
with:
ActiveSheet.Shapes.AddPicture MyFileAndPath, msoFalse, msoTrue, 100, 100, 70, 70
Set MyLogo = ActiveSheet.Shapes(ActiveSheet.Shapes.Count)

Ruby/Tk Paned window 'orient' option will not work with horizontal value

Trying to add a Paned window in Ruby/Tk and I'm getting the following error:
C:/Users/user/Ruby193/lib/ruby/1.9.1/tk.rb:3016:in `_invoke': Attempt to change read-only option (RuntimeError)
whenever I add the orient option to my code like this:
p = Tk::Tile::Paned.new(parent) { orient 'horizontal' }
It seems that 'orient' is read-only (and defaults to 'vertical') for some reason? I noticed a ruby/tk tutorial on the web with a Paned window example and it avoided using the orient option, perhaps because they ran into the same error?
If you paste the following tutorial code into a .rb file and run it (no orient option) it works. Add the orient option similar to the above and it fails.
require 'tk'
require 'tkextlib/tile'
$resultsVar = TkVariable.new
root = TkRoot.new
root.title = "Window"
p = Tk::Tile::Paned.new(root)do
height 110
place('height' => 100, 'width' => 200, 'x' => 10, 'y' => 10)
#orient 'horizontal' # <== uncomment this line to see error
end
f1 = TkFrame.new(p) {
relief 'groove'
borderwidth 3
background "red"
padx 30
pady 30
pack('side' => 'left', 'pady' => 100)
}
f2 = TkFrame.new (p){
relief 'groove'
borderwidth 3
background "yellow"
padx 30
pady 30
pack('side' => 'right', 'pady' => 100)
}
p.add f1 #, nil <== had to remove nil option here because this also caused an error
p.add f2 #, nil
Tk.mainloop
Has anyone else been able to get the 'orient' option to work? I need it to be horizontal, not the default vertical value. I tried looking at tk.rb and following the error trace and it seems to indicate a 'method_missing' issue.
I think the problem is that the property 'orient' can be set but can't be changed. You can create a PanedWindow 'horizontal' if you pass the option at creation time. Like
p = Tk::Tile::Paned.new(root, 'orient' => 'horizontal' )
Forget the 'method_missing' call. Is a trick for dinamically creating the properties of the widgets.

Matlab GUI: How to Save the Results of Functions (states of application)

I would like to create an animation which enables the user to go backward and forward through the steps of simulation.
An animation has to simulate the iterative process of channel decoding (a receiver receives a block of bits, performs an operation and then checks if the block corresponds to parity rules. If the block doesn't correspond the operation is performed again and the process finally ends when the code corresponds to a given rules).
I have written the functions which perform the decoding process and return a m x n x i matrix where m x n is the block of data and i is the iteration index. So if it takes 3 iterations to decode the data the function returns a m x n x 3 matrix with each step is stired.
In the GUI (.fig file) I put a "decode" button which runs the method for decoding and there are buttons "back" and "forward" which have to enable the user to switch between the data of recorded steps.
I have stored the "decodedData" matrix and currentStep value as a global variable so by clicking "forward" and "next" buttons the indices have to change and point to appropriate step states.
When I tried to debug the application the method returned the decoded data but when I tried to click "back" and "next" the decoded data appeared not to be declared.
Does anyone know how is it possible to access (or store) the results of the functions in order to enable the described logic which I want to implement in Matlab GUI?
Ultimately, this is a scoping of variables problem.
Global variables is rarely the right answer.
This video discusses the handles structure in GUIDE:
http://blogs.mathworks.com/videos/2008/04/17/advanced-matlab-handles-and-other-inputs-to-guide-callbacks/
This video discusses sharing of variables between GUIs and could apply to a single GUI problem also.
http://blogs.mathworks.com/videos/2005/10/03/guide-video-part-two/
The trick is to use nested functions so that they share the same workspace. Since I already started with an example in your last question, now I'm simply adding GUI controls to enable going forward/backward interactively, in addition to play/stop the animation:
function testAnimationGUI()
%# coordinates
t = (0:.01:2*pi)'; %# 'fix SO syntax highlight
D = [cos(t) -sin(t)];
%# setup a figure and axis
hFig = figure('Backingstore','off', 'DoubleBuffer','on');
hAx = axes('Parent',hFig, 'XLim',[-1 1], 'YLim',[-1 1], ...
'Drawmode','fast', 'NextPlot','add');
axis(hAx, 'off','square')
%# draw circular path
line(D(:,1), D(:,2), 'Color',[.3 .3 .3], 'LineWidth',1);
%# initialize point
hLine = line('XData',D(1,1), 'YData',D(1,2), 'EraseMode','xor', ...
'Color','r', 'marker','.', 'MarkerSize',50);
%# init text
hTxt = text(0, 0, num2str(t(1)), 'FontSize',12, 'EraseMode','xor');
i=0;
animation = false;
hBeginButton = uicontrol('Parent',hFig, 'Position',[1 1 30 20], ...
'String','<<', 'Callback',#beginButton_callback);
hPrevButton = uicontrol('Parent',hFig, 'Position',[30 1 30 20], ...
'String','<', 'Callback',#previousButton_callback);
hNextButton = uicontrol('Parent',hFig, 'Position',[60 1 30 20], ...
'String','>', 'Callback',#nextButton_callback);
hEndButton = uicontrol('Parent',hFig, 'Position',[90 1 30 20], ...
'String','>>', 'Callback',#endButton_callback);
hSlider = uicontrol('Parent',hFig, 'Style','slider', 'Value',1, 'Min',1,...
'Max',numel(t), 'SliderStep', [10 100]./numel(t), ...
'Position',[150 1 300 20], 'Callback',#slider_callback);
hPlayButton = uicontrol('Parent',hFig, 'Position',[500 1 30 20], ...
'String','|>', 'Callback',#playButton_callback);
hStopButton = uicontrol('Parent',hFig, 'Position',[530 1 30 20], ...
'String','#', 'Callback',#stopButton_callback);
%#----------- NESTED CALLBACK FUNCTIONS -----------------
function beginButton_callback(hObj,eventdata)
updateCircle(1)
end
function endButton_callback(hObj,eventdata)
updateCircle(numel(t))
end
function nextButton_callback(hObj,eventdata)
i = i+1;
if ( i > numel(t) ), i = 1; end
updateCircle(i)
end
function previousButton_callback(hObj,eventdata)
i = i-1;
if ( i < 1 ), i = numel(t); end
updateCircle(i)
end
function slider_callback(hObj, eventdata)
i = round( get(gcbo,'Value') );
updateCircle(i)
end
function playButton_callback(hObj, eventdata)
animation = true;
while animation
i = i+1;
if ( i > numel(t) ), i = 1; end
updateCircle(i)
end
end
function stopButton_callback(hObj, eventdata)
animation = false;
end
function updateCircle(idx)
set(hSlider, 'Value', rem(idx-1,numel(t))+1) %# update slider to match
set(hLine,'XData',D(idx,1), 'YData',D(idx,2)) %# update X/Y data
set(hTxt,'String',num2str(t(idx))) %# update angle text
drawnow %# force refresh
if ~ishandle(hAx), return; end %# check valid handle
end
%#-------------------------------------------------------
end
You might find the slider functionality a bit buggy, but you get the idea :)

Resources