In TCL/TK Remove binding after widget destruction - binding

I have a canvas located in a Sub window of my main application:
.dsm.nb.mdlbuild.canvas
additionally I have the following (one of several) proc helping me letting the user move stuff around on the canvas:
proc grab { xx yy } {
global currentx currenty
set currentx $xx
set currenty $yy
}
I use this binding:
.dsm.nb.mdlbuild.canvas bind $tagtomove <Button-1> {grab %x %y }
PROBLEM:
When the user closes the window (.dsm) the canvas gets distroyed to, but the binding seems to 'survive'.
When the user then subsequentually clicks somwhere he gets the error:
wrong args: should be "grab xx yy"
This because xx and yy is empty i suppose because the canvas is gone together with the parrent window...
I have tried to set the binding to nothing after the .dsm window is destroyed:
.dsm.nb.mdlbuild.canvas bind $tagtomove <Button-1> { }
and to use the "break" command, but with no success.
.dsm.nb.mdlbuild.canvas bind $tagtomove <Button-1> break
How can i remove the binding uppon closing the window (.dsm) in which the canvas is located so that this error does dissapear?

The problem is most likely that you used the name of a standard Tk command for your proc. The grab command is called from different places in the Tk library, but not always matching the number of arguments of your proc. This would cause the error. You can check this by dumping the value of $errorInfo after you received the error message.
So, just rename your proc to something other than grab (or any other built-in command).

Related

my bindable function is spitting out the error "attempt to call a nil value"?

for a roblox lua game.
I'm trying to make a bindable function that after the player clicks on the text box, types something in, and then clicks enter/return it stores the word in the server and then prints it in the output. Now everything on the typing side works, It even prints out on a surfacegui. The problem is that if I try to run the code I get the error "attempt to call a nil value". Here's my Invoke code for typing in the box.
local screenTextBox = script.Parent -- Location of Textbox on the screen
local partTextLabel = game.Workspace.BlueTeamGameRoom.BlueGameBoard.Board.SurfaceGui.TextBox -- Location of text on block
while true do --code to update the screengui
wait(.5)--wait in order to keep roblox studio from crapping itself
screenTextBox.FocusLost:connect()--for clicking on the textbox
partTextLabel.Text = screenTextBox.Text -- Change text
end
screenTextBox.FocusLost:connect(function(enterPressed) --defining enterpressed(clicking enter) within the parameters of the player clicking the box
if enterPressed then
local DBallz = game.ReplicatedStorage.answerVerify:Invoke() --calling the bindable function
print(DBallz)--printing what the bindable function returns
end
end)
and here's my OnInvoke code to print the word in the box
game.ReplicatedStorage.answerVerify.OnInvoke = function()
local Text = game.StarterGui.ScreenGui.wordSend.TextBox.Text --defining the property of the text of the textbox
return Text --sending the text to the local script
end
I've tried using InvokeServer and OnServerInvoke but there was no difference. There I also tried using a different way of writing the keycode mapping but that didn't work either. and also the invoke code is in a localScript that is a child of the text box the user has to type in. and the on invoke code is in a regular server-side script that's a child of the workspace.
In your code I see this:
screenTextBox.FocusLost:connect()
You should provide a function here. So a soon as your textbox loses focus Roblox will call the event listener which happens to be nil.
Why do you do this in a loop btw? That doesn't make sense to me.

IsTradeAllowed not returning what I would expect

Please see the script below:
void OnStart()
{
Alert(IsTradeAllowed()); //alert 1
Alert(IsTradeAllowed(NULL, TimeGMT())); //alert 2
Alert(IsTradeAllowed(Symbol(), TimeGMT())); //alert 3
Alert(IsTradeAllowed("GBPUSD", TimeGMT())); //alert 4
}
This returns:
true //for alert 1
true //for alert 2
false //for alert 3
false //for alert 4
As alert 2 returns: true, then I would expect alert 3 and alert 4 to return true.
I have tried running the code at multiple times of the day on weekdays. The code returns the same result at weekends. I have also tried putting the code in a script and an EA. Every time I get the same result. Is there an explanation for this? I have tried what is suggested here: https://www.mql5.com/en/docs/runtime/tradepermission
Symbol() returns: "GBPUSD". Each alert should return true in my mind, however this does not appear to be the case here. Incidentally I have notices that Symbol() returns the symbol at the top of the demo account watchlist if the script is run inside MetaEditor, however it returns the symbol displayed on the chart if run inside the demo account.
The broker is Oanda.
Update 04/03/21 at 19:55
I have now discovered that if I right click on the Market Watch and select: show all, then more symbols appear. I can then see that some symbols are greyed out and some symbols are not. The symbols that are not greyed out e.g. USDGBP-g return what I would expect when running the program above i.e. alert 1-alert 4 =true. The symbols that are greyed out e.g. USDGBP returns true; true; false; false in the program above. I now have two questions:
Why does: IsTradeAllowed(NULL, TimeGMT()); //alert 2 return true for symbols that are greyed out?
What does -g mean in GBPUSD-g?
IsTradeAllowed checks if the Expert Advisor is allowed to trade and trading context is not busy.
The version of the function without any arguments will check if the EA has been applied with the correct permissions ("Allow live trading" ticked and "AutoTrading" enabled).
The second form of the function:
bool IsTradeAllowed(const string symbol, datetime tested_time);
checks if the EA would be allowed to trade according to the specifications for the chart selected (to view this, from the Market Watch window right click a symbol, from the menu that pops up select "Specification").
For example
IsTradeAllowed(Symbol(), D'2021.03.06 12:00');
would check if the current symbol can be traded this coming Saturday (which should be false).
If you are getting undesirable results you should check that your broker has set the "Specifications" correctly.
EDIT
I've tested the command in OANDA which is the broker you are using and the command functions as expected.
NULL is not valid for a Symbol and its use makes the command function in its first form (ie timedate is ignored).
I would suggest rather than use Alerts to examine output, try the following.
string cmnt;
cmnt=StringConcatenate("Alert 1: ",IsTradeAllowed());
cmnt=StringConcatenate(cmnt+"\r\n","Alert 2: ",IsTradeAllowed(NULL, TimeGMT()));
cmnt=StringConcatenate(cmnt+"\r\n","Alert 3: ",IsTradeAllowed(Symbol(), TimeGMT()));
cmnt=StringConcatenate(cmnt+"\r\n","Alert 4: ",IsTradeAllowed("GBPUSD", TimeGMT()));
Comment(cmnt);
I tried your script in my ICMarkets version of MetaTrader4. With disabled auto trading i get result:
When I set auto trading to enable using Ctrl+E shortcut, in all cases script return true.
I recommend you to try this script on another account or different broker. If this will help, you should communicate with your broker about this issue. The last option is a reinstall MetaTrader to make sure, that all config files are correct.

readByteSync - is this behavior correct?

stdin.readByteSync has recently been added to Dart.
Using stdin.readByteSync for data entry, I am attempting to allow a default value and if an entry is made by the operator, to clear the default value. If no entry is made and just enter is pressed, then the default is used.
What appears to be happening however is that no terminal output is sent to the terminal until a newline character is entered. Therefore when I do a print() or a stdout.write(), it is delayed until newline is entered.
Therefore, when operator enters first character to override default, the default is not cleared. IE. The default is "abc", data entered is "xx", however "xxc" is showing on screen after entry of "xx". The "problem" appears to be that no "writes" to the terminal are sent until newline is entered.
While I can find an alternative way of doing this, I would like to know if this is the way readByteSync should or must work. If so, I’ll find an alternative way of doing what I want.
// Example program //
import 'dart:io';
void main () {
int iInput;
List<int> lCharCodes = [];
print(""); print("");
String sDefault = "abc";
stdout.write ("Enter data : $sDefault\b\b\b");
while (iInput != 10) { // wait for newline
iInput = stdin.readByteSync();
if (iInput == 8 && lCharCodes.length > 0) { // bs
lCharCodes.removeLast();
} else if (iInput > 31) { // ascii printable char
lCharCodes.add(iInput);
if (lCharCodes.length == 1)
stdout.write (" \b\b\b\b chars cleared"); // clear line
print ("\nlCharCodes length = ${lCharCodes.length}");
}
}
print ("\nData entered = ${new String.fromCharCodes(lCharCodes).trim()}");
}
Results on Command screen are :
c:\Users\Brian\dart-dev1\test\bin>dart testsync001.dart
Enter data : xxc
chars cleared
lCharCodes length = 1
lCharCodes length = 2
Data entered = xx
c:\Users\Brian\dart-dev1\test\bin>
I recently added stdin.readByteSync and readLineSync, to easier create small scrips reading the stdin. However, two things are still missing, for this to be feature-complete.
1) Line mode vs Raw mode. This is basically what you are asking for, a way to get a char as soon as it's printed.
2) Echo on/off. This mode is useful for e.g. typing in passwords, so you can disable the default echo of the characters.
I hope to be able to implement and land these features rather soon.
You can star this bug to track the development of it!
This is common behavior for consoles. Try to flush the output with stdout.flush().
Edit: my mistake. I looked at a very old revision (dartlang-test). The current API does not provide any means to flush stdout. Feel free to file a bug.

Issue with using int.parse() in Dart

I'm currently teaching myself the Dart language, and my first app doesn't seem to be working right. Here's the code that's causing trouble:
usrLoc = int.parse(query("#txtLoc").text);
When I try to run the app, it opens fine, but when I click the button that triggers this (and three other similar parses), the debugger stops and tells me "Source not found" for int._native_parse(), int._parse(), and int.parse().
Any help would be greatly appreciated.
The text property for the specified element #txtLoc returns an empty string.
The parse method requires that:
The source must be a non-empty sequence of base- radix digits, optionally prefixed with a minus or plus sign ('-' or '+').
You can specify an onError named argument in your call to parse, which takes a callback that handles the invalid input. E.g., if you want the parse call to return the value 42 for all invalid input, you can do this:
usrLoc = int.parse(query("#txtLoc").text, onError: (val) => 42);
If you really expect the element to have some text, you can store the result of query("#txtLoc").text into a separate variable and verify the value. It would also be interesting to check what the real element type is or which tag is marked with id #txtLoc.
If you want to get the content of an input element, you should use the value property instead of text:
query("#txtLoc").value

apply new layer to a slice of a volume webgl

i have two volumes (.nrrd) of different qualities. the user can browse through the layers. if a key is pressed
i want to load the slice of the volume with better quality.
my volume is similar to this one: lesson 10 xtk
i've found:
volume.children[2].children[0].children[0].texture.file = "http://path/to/file.ext";
but if i apply some kind of file (.jpg, .dcm) nothing happens.
is this the right approach to change the slice to go inside the children and change the texture?
or shall i load the selected slice seperate as an object and apply it to the "lower-quality-volume" somehow?
edit:
this is what i tried so far (i get errors with dcms but not with jpgs):
if (event.keyCode == 83) { // "s"-button
volume.children[2].children[0].children[0].texture.file = "http://localhost:3000/112.jpg";
volume.children[2].children[0].children[0].modified();
r.render();
}
edit2: this is whats in my r.onShowtime = function() {}
volume.children[2].children[0].texture.file = 'http://localhost:3000/112.jpg';
volume.children[2].children[0].visible = true; // to activate the first layer
volume.children[2].children[0].modified();
console.log(volume.children[2].children[0].visible +" "+ volume.children[2].children[0].texture.file);
it outputs "true hostname/112.jpg"
when i inspect the .jpg in firebug the header is ok but the answer is "null"
when i inspect console.log(volume.children[2].children[0]); with firebug
.texture.file is set to hostname/112.jpg
when i go to "network" the .jpg has been transfered successfully
please notice that 112.jpg and level.jpg are the same. the first one is getting loaded in r.onShowtime and the other one is loaded at a keypressed event.
EDIT 3: volume.children[2].children[0] is of the type "X.slice", isn't it?
here is my approach: jsFiddle
and this is my actual issue and still not working: jsFiddle
Mhh..
I think a call to object.modified() is missing in the file setter (and in others setters from inject classes). Let's see when Haehn will come if he wants to change something internaly, but for the moment could you try to call it by yourself ?
You can try to add after the modification of texture :
volume.children[2].children[0].children[0].modified();
And if it doesn't work, in addition :
renderer.render();
Edit :
It's strange, I did a similar code and it did something. Can you please try something like that with opening your javascript console (Firefox, Chrome,... has one) and tell me the error you get ?
renderer.onShowtime = {
for (var i=0 ; i< volume.children[2].children.length ; i++) {
volume.children[2].children[i].texture.file="myimage.jpeg";
volume.children[2].children[i].modified();
}
}
It is important you call it in the onShowtime, because before the volume is not loaded, and so slicesX, slicesY... don't exist.
Edit2 :
Hey,
Thanks to the informations you added I think I've got the point ! In the render() method of our renderer3D there is a test on texture._dirty flag, that you cannot change from outside the framework. In addition the 1st rendering with a texture make that flag false, and loading a new texture doesn't seem to set that flag back to true in the current XTK. So, I think, we have to add it in the loader.load(texture, object) method. I'll make an issue on Github and see what Haehn thinks of it !

Resources