I couldn't find any useful resources for this subject. I hope I can find some guidance here.
I made a dialog window class using Glade, Gtk (3.10) and Python 3. It has about 30 options that can be changed. In the init function I set up the whole dialog window and set the options to the current value. I also define a bool-variable that stores if any of the widgets was changed:
self.settings_changed = False
So for each widget I set up a function that catches the "change-signal" and does the following:
def on_checkbutton_line_width_changed(self, widget):
#Set setting_changed to True so that the dialog knows something changed
self.settings_changed = True
#Store the changed value in a temporary variable
self.temp_checkbutton_value = widget.get_active()
Now when I click "Cancel" on the dialog I just don't apply any of the temporary values. But when I click "Apply" I want all changed variables to be applied. But here is my problem: Of those 30 changed variables only a few exist and all the others would lead to a lot of AttributeErrors, because the temporary variable doesn't exist.
I tried avoiding the errors by using a lot of try-except functions:
try:
self.dataclass.set_checkbutton(self.temp_checkbutton_value)
except:
pass
Is there a easier (and shorter) way to solve this? I imagine that there should be a way to build a queue of changes that are executed after each other after clicking on "Apply", but my potato-like python skills have so far not helped me in solving this.
Here's an example that might help:
class MyWidget:
def __init__(self):
self.changes = []
def cancel_changes(self):
self.changes.clear()
def change_name(self, new_name):
self.changes.append(('change_name', new_name))
def change_color(self, new_color):
self.changes.append(('change_color', new_color))
def apply_changes(self):
for change in self.changes:
print("{} - {}".format(change[0], change[1])
alternatively you could do something like:
self.changes.append(lambda: self.dataclass.set_checkoutbutton(value))
and then apply changes would be:
for change in self.changes:
change()
Related
I'm writing a program to generate a VFP form class with lots (90+ each) of labels and radio buttons on it. That's the easy part. (and yes, I know that's a lot of radio buttons, but that's what the users want).
We have several VCXs in our application which do something similar, but not with anywhere near as many individual controls. So, rather than spend a huge fraction of my life dragging and dropping fields around, and realizing that I happen to have a handy list of all the fields, their options and default values, I used the 'View Class Code' option from the Class Browser to get a sample of what the code looks like as a base. Then I wrote code to generate a PRG with all the pieces I need.
My actual problem is that the code output by 'View Class Code' seems to include invalid syntax:
DEFINE CLASS form40 AS frmae
Height = 427
Width = 710
ScrollBars = 2
DoCreate = .T.
Visible = .T.
Name = "form40"
ADD OBJECT form40.cntouter.cntform40 AS cntctrls WITH ;
Top = 175, ;
Left = 2, ;
Visible = .T., ;
Name = "Cntform40"
ENDDEFINE
The class frmae is a class (from a VCX) which includes a container called 'cntouter'. Class cntctrls is the container that contains all the labels/radio buttons.
The problem is that apparently you can't, in the DEFINE CLASS command, ADD OBJECT to a member. The dotted syntax causes a syntax error. Yet, this technique is used in the 'View Class Code' output.
I suspect I could get around this by generating an Init method which calls ADDOBJECT() to add my control container to cntouter, but I'd rather have it in the class definition.
The "View Class Code" option doesn't produce runnable code; it never has.
My suggestion for doing what you need is to create an option button class with the appearance that you want. Then, use your existing list to populate a cursor and write code that spins through that and adds option buttons to a container class.
The key thing you need to know here is that you can run code in the IDE that affects a form or class that's open in the Form Designer or Class Designer. That's what Builders do. So rather than generate a code-based class, use code to create a visual class.
If you want to do this in code, then first you shouldn't depend view code as Tamar already pointed out. You can do any form and its controls in code (with the exception of one or two activex controls maybe) but you need to understand how to code container type controls. First, to add a class from a class library you need to sepcify its source. ie:
add object myContainer as MyBeautifulContainer from myClasslib.vcx
wouldn't work. Instead you would need to define a class in your code like this:
define class form40 as form
* ...
add object myContainer as MyContainer with ...
* ...
enddefine
define class myContainer as MyBeautifulContainer from myClasslib.vcx
* additiobnal code if any
enddefine
Second, you would need to create your inner controls first and then add as needed to create the outermost object.
AT designtime, you could go to command window, pop up a code window:
modify command [enter]
and then using ASELOBJ() function you can get a reference to any object on the form you are designing. Onece you have the desired reference(s), you can add and arrange objects within that code window programmatically, select the code and execute selection (erase the controls, correct your code and retry if you can't do it right for the first time). That is temporary "do and throw away" style builder.
I'm trying to make two buttons in Tkinter using python version 3.3, one to create a button and one to delete said button. It has been working so far except for the fact that if I create more than one button I can only delete one the the created buttons. My question is: is there anything I can do to be able to delete a button every time the delete button is called upon?
This is my code so far:
from tkinter import *
def createbutton():
global secondbut
secondbut=Button(root,text="button")
secondbut.pack()
def eliminatebutton():
secondbut.destroy()
if __name__=='__main__':
root=Tk()
global create
global delete
create= Button(root,text="create",command=createbutton)
delete=Button(root,text="delete",command=eliminatebutton)
create.pack()
delete.pack()
root.mainloop()
The problem is that you're storing your Button in a variable (secondbut), then overwriting that variable if you create a new button.
Instead of directly storing it in a variable, store it in some container, such as a list.
This code will do what you want:
from tkinter import *
def createbutton():
global secondbut
secondbut.append(Button(root,text="button"))
secondbut[-1].pack()
def eliminatebutton():
secondbut[-1].destroy()
secondbut.pop()
if __name__=='__main__':
root=Tk()
global create
global delete
global secondbut
secondbut = []
create= Button(root,text="create",command=createbutton)
delete=Button(root,text="delete",command=eliminatebutton)
create.pack()
delete.pack()
root.mainloop()
Note that it removes buttons in the opposite order it adds them.
I'm using QtRuby with Qt 4.8.6 and trying to create a tree view where each item has a custom icon between the tree controls and the name. The end result should be like this:
I am getting space allocated for where the icon should go, but I'm not seeing any icons. What do I have to do to get them to show up?
Here's my code (simplified slightly to remove the no-data edge cases):
class MyModel < Qt::AbstractItemModel
# ...
def data(index, role)
case role
when Qt::DisplayRole
case index.column
when 0; Qt::Variant.new(index.internalPointer.displayName)
when 1; Qt::Variant.new(index.internalPointer.displayType)
end
when Qt::DecorationRole
if index.column==0 then
# Just testing to show a static icon for all items
Qt::Pixmap.new(':/resources/images/Objects-Scene-Normal.png')
end
end
end
end
#mytreeview.model = MyModel.new
If you want to inspect the Qt Designer .ui file (in case the tree view needs to have a property set that I have not) it can be seen here.
I think the image cannot be found with the path specified. Verify it with QFileInfo::exists().
Apparently the QPixmap needs to be wrapped in a QVariant to work properly. This is done in QtRuby by using Qt::Variant.fromValue():
when Qt::DecorationRole
if index.column==0 then
Qt::Variant.fromValue( Qt::Pixmap.new(':/path/to/resource') )
Credit to andre and peppe on #qt irc.freenode.net for helping with this.
use QTreeWidget insted of QTreeView.
then create a new form class (YourTreeWidgetItem) for your new items, every thing you like, then do this:
YourTreeWidgetItem* wItem = new YourTreeWidgetItem;
treeWidget->setItemWidget(wItem);
but it is c++ Qt code
So I'm working on a text editor to better learn wxPython (and to make a text editor that I really like :P). I have been having trouble finding much info on the wx.aui.AuiNotebook class. One thing I would like to know is how to interact with its pages. For example, I would really like to know how to change the title of a page (so that I can update the page title when a user saves or to mark it when there is unsaved changes). Any assistance on this matter would be most appreciated!
The method is called SetPageText, so you would do something like:
current_page = notebook.GetCurrentPage()
current_page_index = notebook.GetPageIndex(current_page)
current_label = notebook.GetPageText(current_page_index)
if not current_label.endswith(' (*)':
notebook.SetPageText(current_page_index, current_label + ' (*)')
Apparently, in wxPython version 2.8 does not include wx.aui.AuiNotebook.GetCurrentPage(). What I apparently didn't realize is that a "page" in the wx.aui.AuiNotebook is equivalent to the panel that is being added to it. Thus the following code will work,
self.panelBox = []
newPanel = wx.Panel(self, wx.ID_ANY)
#YADA YADA STUFF!
self.nb.AddPage(newPanel, "Untitled Document "+str(self.untitledDocCount))
currPageIndex = self.nb.GetPageIndex(newPanel)
currLabel = self.nb.GetPageText(currPageIndex)
if not currLabel.endswith(' (*)'):
self.nb.SetPageText(currPageIndex, currLabel+' (*)')
self.panelBox.append(newPanel)
It's up to the programmer to ensure that the pages (panels) are accessible. I do this by storing the panel references in a "panel box" and then switching between them accordingly in conditions such as a "change tab" event. I don't know if this is the best way to do this, but it appears to work so far.
The is any way to remove the events in Shoes? I searched around many websites and references but I can't found any way to remove a event... I minding that I will need to create my own event manager... its really nescessary? or there is a way to desattach event listeners?
I have found that Shoes only allows a single listener method on a given event, so you can remove a previous listener by calling the event and not passing a block to it.
For example, this Shoes app will clear the click event after it is clicked one time. If you remove the call to click inside the block, then it will fire repeatedly.
Shoes.app
#p = para "Empty"
#click_count = 0
click do |b,x,y|
#click_count += 1
#p.replace "Clicked #{#click_count} time(s)."
click # remove the click handler
end
end
Which keybindings do you want to remove? All events on the Shoes app or just the default bindings?
If you want to override bindings reserved for shoes like "alt-/", "alt-.", "alt-?", paste the following code into the file which contains your application code
class Shoes::App
def Shoes.show_log # gets called on alt-/
end
def Shoes.show_manual # gets called on alt-?
end
def Shoes.show_selector # gets called on alt-.
end
end
The above code monkey-patches the shoes code and in-turn does nothing when the corresponding keys are pressed.
You can use the same technique for rest of the default bindings. grep the shoes source for the key bindings, find the corresponding method and define an empty method within your app to override the built-in method.
Have you tried method.unbind(obj)?
Can you clarify what you mean by "remove a event"? Are you wanting to ignore a specific event or are you wanting to "turn off" an event listener?
If the former, I'd suggest writing a listener that just ignore the event.
If the later, why not make the body of the listener conditional on some externally accessible value, giving yourself an on/off switch.
If you are wanting something else, edit the question to clarify and I'll stop back later and edit my answer.
In response to your comment, I'd re-suggest the second of the above alternatives. If you wanted to get really fancy you could write something like this:
$keypress_listeners = {}
keypress do |key|
$keypress_listeners.values.each { |l| l.call(key)
end
$keypress_listeners[:hero_controller] = lambda { |key| ... }
:
:
$keypress_listeners.delete[:hero_controller]
and likewise for any other events, but that is probably overkill. On the other hand, it would give you total control of the event processing.