Let's say I have a button. In it's constructor I use variables to feed the values(before running I set some default values to these variables), so later they can be changed and within the program the look of the GUI can be modified. What I need is to update the widgets whenever I change these values.
For example I have some options to change a certain color, I press the button it calls a certain command defined in the constructor, changes the color variable and after that, it needs to be updated. Here it says the update() redraws widgets as needed. How do I tell it I need the widgets to be redrawn ?
http://effbot.org/tkinterbook/widget.htm
I might be mistaken on what the redrawing actually means. In any case I need it to update with the new values. I have a quite dumb solution for this, that is destroying everything and rebuilding it. I feel like there is a smarter way of doing things.
All widgets have a configure method which can be called to change any of its attributes. All you have to do is keep a reference to the widget(s), and call the method:
def update_the_widgets():
the_label.configure(background="red")
a_button = tk.Button(..., command=update_the_widgets)
the_label = tk.Label(..., background="green")
This is much easier if you use an object oriented style of coding. Otherwise these references need to be global variables.
When your GUI is properly coded you should almost never need to call update.
Related
I have put nodes in a group. And I have put a func on the scene script to make changes to the nodes in group. In that func,I made the nodes to queue free and stuffs like that. But when I change scene and come back to the previous scene,the queued free is back again,it is not queued free anymore. How do I make it not change even after changing scene?
Why information is lost
When you change the current scene with change_scene or change_scene_to the current scene is unloaded, and the new one is loaded and instanced.
Perhaps it helps to conceptualize that the instance of the scene is not the same as the scene in storage. So what happens is like opening a file in an editor, modifying and not saving it.
Alright, that is one solution if you really want to go that route: you can save a scene.
First create a PackedScene, for example:
var packed_scene := PackedScene.new()
Then tell it to pack the root node of the scene, for example:
packed_scene.pack(self)
Note: any Nodes that don't have their owner property set to the Node you passed here will be ignored. And no, add_child does not set the owner property.
If you have been paying attention, you know you can give a PackedScene to change_scene_to... But how do you keep it around when the scene changes?
There are a few ways. And the thing is: if we can keep information around, we might not need to save the scene.
Keep things around in autoloads
The scripts and scene you add to your autoloads (singleton) in project settings stay there (unless you explicitly remove them) even when you change scene.
Thus, a very simple way to keep information around is to have a script with some variables that you can write and read from anywhere in your project. And you can do that with an autoload.
Keep things around in resources
Godot caches resources. When you load the same resource in multiple places, you actually get the same object.
Well, you know you can create a custom Resource class. To do that, on the context menu of the FileSystem panel select "New Script", and in the script make a class that extends Resource, and give it a class_name.
Then you can create resources of that Resource from the context menu of the FielSystem panel by selecting "New Resource" and picking your Resource class when asked.
Everywhere you load one of those, you are going to get the same object. Yes, even if it is in another scene. So you can add variables to your Resource class, write them in one scene and read them in another.
I explain a more concrete example elsewhere.
Keep things around in storage
You can write to a file and read from a file. For example you can do this:
# save
var file = File.new()
file.open("user://a.sav", File.WRITE)
file.store_pascal_string(var2str(data))
file.close()
# load
file.open("user://a.sav", File.READ)
data = str2var(file.get_pascal_string())
file.close()
Or, if what you want to store is a Resource (be it a PackedScene, or some other Resource class including a custom one), you can use ResourceSaver and ResourceLoader:
# save
ResourceSaver.save("user://a.tres", resource)
# load
resource = ResourceSaver.load("user://a.tres")
Of course, you can also load resources with load, or preload. You may also be interested in Background Loading.
By the way, if you are going to save player progress, having all the player progress data in a single object makes sense. And if you are going to have all the data you are keeping all the player progress data in a single place, it makes sense it would be somewhere it is accesible all the time and stays around even when you change scenes, thus: put the player progress data in an autoload. Bonus: you can put the functions to save and load to a file there too.
Don't change scenes
Since changing scenes brings problems - consider another solution: don't.
You can load an scene:
var packed_scene := load("res://scene.tscn") as PackedScene
Then make an instance of it:
var scene := packed_scene.instance()
Then add it to your current scene tree:
add_child(scene)
Yes, it is a Node! It also means you can…
scene.queue_free()
Or you can simply remove it with remove_child which does not free it, so you can add it back later.
So you would be in control of what gets loaded or unloaded and when. Which is useful to keep stuff around (e.g. the UI, the player character, etc...). A drawback of doing it the way I describe here is get_tree().current_scene would not be useful to you anymore. See also Change scenes manually.
I was looking at the function CMFCRibbonCategory::RemovePanel and I saw something that I don't understand. The 2nd optional parameter is bDelete which according to the docs:
[in] bDelete
TRUE to delete the panel object from memory; FALSE to remove the panel object without deleting it.
I don't see a way of referencing the same panel elsewhere and this isn't like hiding the panel as there is no way to bring it back, so why wouldn't I want to do this?
Unless this is in case I were to keep a live pointer to it using CMFCRibbonCategory::GetPanel? Sounds kinda like a bad idea.
I agree. There is no real use for Setting bDelete to false at all.
m_arPanes is no where accessed in a way that some one can add a Panel with a plain pointer.
It seams to be a relict when they transported the BGC ribbons implementation into the MFC. The BCG version also have this bDelete flag and it isn't useful there too, but there are more complex functions that handle such panels.
But I don't see this functions and internal customizable panels in categories in the MFC.
So from the design point it would have been better to create a special protected function like InternalRemovePanel. That just remove th Panel and keps the pointer...
I have a question regarding coded ui UIMap.
Every time I record an action on the same application, coded ui generates a new object for the same window in the application.
It looks like:
UIAdminWindow
UIAdminWindow1
UIAdminWindow2
and so on...
every window class holds different buttons, even though it's the same window.
Thus it's very hard to keep code maintenance.
What i would like is that every time i perform actions and records on a window, even if not at the same time, the already generated class for this window, will be updated with the new controls.
any suggestions to why it happens?
Thanks a lot!
You can clean up your UIMaps by doing two things:
Use the UIMap Toolbox (from codeplex) to move controls within the UIMap so they are all under one control tree.
When you have duplicate UI controls, go to the properties for the action that references the duplicate control and change the UI Control property to point to the original control in the UIMap.
The duplicate trees should now be unreferenced and you can delete it from your map, keeping things clean.
And yes, it's a pain to do, but it's worth it for maintainability.
In UIMap.uitest you can change the action name and the control name for better maintenance.
For example: you can set UIAdminWindow as FirstAcessWindow or other name that will express comfortably the control or the action.
What I can guess is that there is some randomly generated content or element identification data such as class or title that may be causing it. This may be caused by different username for example. Also you can update the element from UI map element tree.
I have a core data document based cocoa app that is working well except for one slightly odd problem.
For some reason, if I make a change to any of my fields the menu/window don't seem to recognize it - ie. the red close button doesn't get the black 'dirty' indicator and the File/Save menu item isn't enabled. However, if I attempt to close the application (via command-Q), I do get the popup asking me if I want to save my changes.
It seems that the document's dirty flag is being set, but the window/menu items aren't reacting to it. I am curious as to where I might look to see why this might be the case. I suspect that it may have something to do with my window not knowing about my ManagedObjectContext...
The only slightly atypical behaviour is that my document's makeWindowControllers method has been overridden and I am adding my window controllers using a call to my document's [self addWindowController:xxx] method. My window controllers subclass from NSWindowController so I had to add my own instance variable to each window controller to hold the ManagedObjectContext, but I suspect that this isn't getting passed to the window/menu. Not sure what the normal pattern is here...
Anyway, any thoughts would be much appreciated. Thanks
From the description it sounds like your UI elements are not actually bound to the document itself. If so, then the UI elements are not observing the document and are not reacting to changes in the document. Check the bindings.
Thanks in part to TechZen, and also re-reading my own question (in particular, where I said "I suspect that it may have something to do with my window not knowing about my ManagedObjectContext") I started to look at the bindings for my WindowController subclass.
As it turned out, I hadn't bound the window outlet for the File's Owner to my actual NSWindow. As soon as I did that, the black dirty dot and the window's menus started behaving correctly.
I have a Glade GUI description file with a GtkTreeView in a GtkHBox in a window; and there's a handler for the row_activated signal. Now, Glade has automatically set the "events" property (inherited from GtkWidget) of that treeview to some value (GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK). And there are two strange things with this:
removing the pre-set value (so that the property is empty) doesn't seem to break the application (at least not with the old GTK 2.10 I have atm).
in fact, an annoying bug I has seen before (where the treeview items would not correctly react to expand or collapse clicks) is now gone!
I have yet to test this with a newer GTK version, but the question is already there: exactly what is the purpose for this events property? And why does Glade automatically and unnecessarily set it to some value? Does this have some side effects I'm not aware of?
It's a bug in glade, it always sets the event property of widgets it create. It has no notion of the default value of a property so it always sets it.
Doesn't this mask indicate the events you're willing to receive? In this case, you'll probably want to receive notification that the user has clicked or double-clicked an item in the GtkTreeView, and you'll want to register callbacks to handle these events.
me.yahoo.com/a/kUQ7zeQ: but even if I set the property to an empty string as mentioned, the row_activated handler is still called when I double-click on a row (or press Enter or Space). So the treeview still gets events...