Using XRC to create custom Dialog boxes - dialog

I have been having trouble defining my own Dialogs which are described using XRC.
I have read http://nebelhom.blogspot.co.nz/2012/04/xrc-and-wxdialogs.html and other similar sources which tells me to do this:
class ConfigDialog(wx.Dialog):
def __init__(self, parent):
self.res = xrc.XmlResource("config_dialog.xrc")
pre = wx.PreDialog()
self.res.LoadOnDialog(pre, parent, "ConfigDlg")
self.PostCreate(pre)
#Bind controls to events
However, I am still very confused as to how you actually bind the controls to different methods defined in ConfigDialog class.
I tried
self.btn_1 = xrc.XRCCTRL(self.frame, 'btn_1')
and
self.btn_1 = xrc.XRCCTRL(self, 'btn_1')
(because i read here that)
The PostCreate method is
used to transfer the guts of pre into self, so it acts like it was a
real instance of ConfigDialog.
but neither of them worked.
Would you be able to point me in the right direction?

I solved the problem using 2 step creation as documented here.
Here's a small example
# Import both wx main module and the xrc module
import wx
import wx.xrc as xrc
class MyDialog(wx.Dialog):
"""
This is our dialog. XRC will create it's widgets and all we need to do is
handle the events.
"""
def __init__(self, parent, res):
pre = wx.PreDialog()
self.PostCreate(pre)
res.LoadOnDialog(self, None, "MyDialog")
#Binding events
self.Bind(wx.EVT_BUTTON, self.on_ok, xrc.XRCCTRL(self, "okButton"))
self.Bind(wx.EVT_BUTTON, self.on_cancel, xrc.XRCCTRL(self, "cancelButton"))
def on_ok(self, event):
"""Show a message box informing us we pressed the OK button"""
msgDlg = wx.MessageDialog(self, "OK pressed", style=wx.OK)
msgDlg.ShowModal()
msgDlg.Destroy()
self.Destroy()
def on_cancel(self, event):
"""Show a message box informing us we pressed the Cancel button"""
msgDlg = wx.MessageDialog(self, "Cancel pressed", style=wx.OK)
msgDlg.ShowModal()
msgDlg.Destroy()
self.Destroy()
# Create the simplest wxApp object
app = wx.PySimpleApp()
# Load the XRC resources
res = xrc.XmlResource("example.xrc")
# Show and run the dialog
dlg = MyDialog(None, res)
dlg.ShowModal()
and the XRC file:
<?xml version="1.0" encoding="cp1255"?>
<resource>
<object class="wxDialog" name="MyDialog">
<title></title>
<object class="wxBoxSizer">
<orient>wxVERTICAL</orient>
<object class="sizeritem">
<object class="wxStaticText">
<label>Just a little bit of text to make
the dialog a little bit less empty
than it has to be for a simple
example.</label>
<font>
<size>12</size>
<family>default</family>
<style>normal</style>
<weight>normal</weight>
<underlined>0</underlined>
</font>
</object>
<flag>wxALL</flag>
<border>5</border>
</object>
<object class="spacer">
<size>0,20</size>
</object>
<object class="sizeritem">
<object class="wxBoxSizer">
<orient>wxHORIZONTAL</orient>
<object class="spacer">
<option>1</option>
</object>
<object class="sizeritem">
<object class="wxButton" name="okButton">
<label>OK</label>
</object>
<flag>wxALL</flag>
<border>5</border>
</object>
<object class="sizeritem">
<object class="wxButton" name="cancelButton">
<label>Cancel</label>
</object>
<flag>wxALL</flag>
<border>5</border>
</object>
</object>
<flag>wxEXPAND</flag>
</object>
</object>
</object>
</resource>
finally, a small tip: To end the dialog, use EndModal(id) as such
self.EndModal(wx.ID_OK)

Related

Integrate a multioption dropdown list in calculator Django

I will try to explain this issue the better I can.
So I built a calculator using django. The user can put the desired input, and then he sees all the results in a table, only by pressing the button: 'select'. 
If the user only wants this result, the user see the result output in the table. 
However, if the user selects one of the options presented in the dropdowns, then the result should be different. Meaning that the dropdown list, has specific calculus. 
This is the part that I don't understand,I know that I have to use JS to this, but I don't know in which module this should be added. 
Here is my code:
models.py
class CalcAnalyzer(models.Model):
sequence = models.TextField()
gc_calc = models.CharField(max_length=2000000)
person_of = models.ForeignKey(User,null=True,on_delete=models.CASCADE)
def save(self, *args, **kwargs):# new
if self.sequence != None:
self.gc_calc = gc_calc(self.sequence)
super(CalcAnalyzer,self).save(*args, **kwargs)
def __str__(self):
return self.sequence
class addcalc_1(models.Model):
name_sequence = models.ForeignKey(OligoAnalyzer, on_delete=models.SET_NULL, null=True)
Option1_5 = models.FloatField(default=0)
def save(self, *args, **kwargs):
self.Option1_5 = Option1_5(self.sequence)
class addcalc_3(models.Model):
name_sequence = models.ForeignKey(OligoAnalyzer, on_delete=models.SET_NULL, null=True)
optional_3
def save(self, *args, **kwargs):
self.optional_3 = optional_3(self.sequence)
views.py
def calc_sequence(request):
sequence_items=Calanalisis.objects.filter(person_of=request.user)
form=AddSequenceForm(request.POST)
if request.method=='POST':
form=AddSequenceForm(request.POST)
if form.is_valid():
profile=form.save(commit=False)
profile.person_of = request.user
profile.save()
return redirect('calc_sequence')
else:
form=AddSequenceForm()
myFilter=SequenceFilter(request.GET,queryset=sequence_items)
sequence_items=myFilter.qs
context = {'form':form,'sequence_items':sequence_items,'myFilter':myFilter}
return render(request, 'Add_Calc.html', context)
How can I insert this in the view.py? If the user selects the 5 or 3 box, the result should appear in the table bellow, if not, the result will stay the same.
Sofia, hi!
To subscribe on the dropdown's events you need a piece of javascript.
HTML and static files
So, you need to attach your new script.js file to your project. You can check what you need to serve static files (it's not a "one-click" solution, especially if you want to deploy your code for external users) docs
When your static file is ready you can include it in the front-end.
Let's imagine that you have index.html where your controls live.
Add the link to the file in your html (before closing </body> tag):
<script type="text/javascript" src="/static/script.js"></script>
static.js
This example shows you how to make an event listener and listen to the dropdown changes.
Use values from the selected options of your dropdowns to make a URL for the request. Ex. /calc/api/?param=1, so you will be able to catch param=1 in your view and react properly.
dropdown example:
<select id="param" name="here_name">
<option value="">Select …</option>
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</select>
API
Create an additional view to handle the requests that will be sent on events. Make it accessible with urls.py.
Use the proper URL to the endpoint in the javascript. Here you can find how to make requests from the JS to your Django back-end.
The param that was chosen will be in the request.GET of your view (if you've chosen GET method to send the data). So make a proper answer and send it back to the JS. You can use JSON format for this.
Parse the answer in the JS and change your page with updated information.

app structuring / re importing modules with tkinter python3

I am restructuring this question: I felt the original questions were long winded and not particularly helpful to anyone else.
I have a main app (run as__main__) that runs directly.
I have a module (simple_module.py) that I only wish to use as an import.
I realise that I can run it standalone if required (via if__name__) and have including that in the modules code, for demonstration only.
When user presses main.py's 'start' button, it should open a new toplevel window with all the classes and widgets from the simple_module which are all in a single class called Page. (all whilst the main app window remains open.)
I want the module to be re-imported (or equivalent) every time the button is pressed. When the modules 'close' button or X is pressed I want it to close that window. main.py's window remains open throughout this and the button press needs to re-open that module window, infinitely, like a loop.
I have added if name == 'main' just to highlight that I understand what this does (it is normally within all my main.py apps) and why I still cannot get the result I want. As far as I can see, it does not change anything, I am now only importing the class but 'new' is still not recognised. Which is the same issue as in the prior example.
I have main.py
import tkinter as tk
# audio module works as expected
import audio_module as am
# I want this window to open and close on command
import simple_module as sm
class GUI(tk.Frame):
def __init__(self, *args, **kwargs):
tk.Frame.__init__(self, *args, **kwargs)
#self.new = tk.Toplevel(self) # auto loads a second, unwanted window
self.session_counter = 0
self.start_btn = tk.Button(root, text="start", command=self.start)
self.start_btn.grid(row=4,column=0,sticky="nsew",pady=30, padx=30, ipady=18)
def start(self):
am.spell() # these audio imports work like a charm, every btn press - single functions call OK
self.session_counter += 1
print(self.session_counter)
#import simple_module - if used here, my usual 'illegal' import style (works great, once only,
# unless in same script as __main__ in which case all re-imports work fine)
# Import attempts
#import simple_module as sm
#page = Page(new) # Page not defined
#sm.Page() #missing parent arg (new)
# error: 'new' not defined
#sm.Page(new)
if __name__ == '__main__':
print('running as __main__')
root = tk.Tk()
#sm.Page = tk.Toplevel(new) # a desperate attempt NO
#page = sm.Page(tk.TopLevel) NO
# qualify and USE module here! sm is not required if you use 'from simple_module import Page' !!
page = sm.Page(root)
#page.pack(fill='both', expand=True)
page.grid(row=0,column=0,sticky='nsew')
main = GUI(root)
root.mainloop()
Finally, we have simple_module.py:
import tkinter as tk
import audio_module as am
# this module works exactly as expected IF run directly...
class Page(tk.Frame):
def __init__(self, parent, *args, **kwargs):
tk.Frame.__init__(self, parent, *args, **kwargs)
# super().__init__(*args, **kwargs)
self.back_btn = tk.Button(parent, text="close", command=self.back)
self.back_btn.grid(row=4,column=0,sticky="nsew",pady=30, padx=30, ipady=18)
def back(self):
am.click()
# close this page BUT have it ready to re-open IF user re-presses button.
new.destroy()
if __name__ == "__main__":
print('running as __main__ directly')
new = tk.Tk()
#new = tk.Toplevel() # this loads an unwanted additional blank window. IF run directly.
page = Page(new)
# the missing line to self contain module!
#page.pack(fill='both', expand=True)
page.grid(row=0,column=0,sticky='nsew')
new.mainloop()
else:
print('running as import with __name__ ==',__name__)
Thanks for your patience and responses. I have re-studied the if main guide you provided a link to, it re-affirms what I already believe I knew about it. A useful example in there for when I want to open a single frame only and switch between them, but in this case I want the main window to remain open whilst calling the modules window.
The problem you're facing is that your Page class isn't written to be reusable. It's relying on global variables and knowledge about the code that is calling it. To be reusable, the Page class needs to be self-contained.
In short, that means that every widget created by Page must be inside the Page class and not in the root window. Also, the code that creates an instance of Page needs to be responsible for calling pack, place, or grid on the instance.
So, the first step is to modify Page so that it can be reusable. The key to that is to require that the caller pass in the parent widget. You're doing that, but you aren't using the passed-in value.
Page should look like the following code. Notice that it explicitly declares parent as the first positional argument, and it passes that on to tk.Frame.__init__:
class Page(tk.Frame):
def __init__(self, parent, *args, **kwargs):
tk.Frame.__init__(self, parent, *args, **kwargs)
self.back_btn = tk.Button(parent, text="close", command=self.back)
...
Notice how the back button is a child of parent rather than the child of some global variable. This is the important step that you are missing, and this is what allows Page to be self-contained and not tightly coupled to the code that creates it.
Once Page is properly self-contained, it is the responsibility of the code that creates an instance of Page to call pack, place, or grid on the instance.
For example, simple_module.py might have this block at the end:
if __name__ == "__main__":
new = tk.Tk()
page = Page(new)
page.pack(fill="both", expand=True)
new.mainloop()
In main.py, since you are importing simple_module as a whole, you need to fully qualify the use of Page:
import simple_module as sm
...
root = tk.Tk()
page = sm.Page(root)
page.pack(fill="both", expand=True)
root.mainloop()
Alternately, you could just import Page and omit the sm.:
from simple_module import Page
...
page = Page(root)
...
Notice how one file can use root and one can use new, but your code will work in either case because it doesn't rely on a global variable. Inside of page it will always be parent no matter what the caller called it.
As an aside, you don't have to import simple_module inside start -- you only need to import it once at the start of the program.

returning another node based on a condition in groovy

My XML is like:
<app>
<module>
<web>
<web-uri>abc.war</web-uri>
<context-root>abc</context-root>
</web>
</module>
<module>
<web>
<web-uri>abc.pl</web-uri>
<context-root>adf</context-root>
</web>
</module>
</app>
I need the context-root values only if web-uri value ends with war. As a List.
I wrote something like:
def ctxRootList = nodeList.'**'.findAll{
ctxRoot ->
ctxRoot.module.web."web-uri".text().endsWith(".war")
}*.text()
There are 2 problems here:
I do not know how to get the other sibling rather the web-uri value
The result now seems to be returned as a concatenated string of all those values. So, how to make it return as a list of values
Here you go:
def txt = '''
<app>
<module>
<web>
<web-uri>abc.war</web-uri>
<context-root>abc</context-root>
</web>
</module>
<module>
<web>
<web-uri>abc.pl</web-uri>
<context-root>adf</context-root>
</web>
</module>
</app>'''
def xml = new XmlSlurper().parseText(txt)
xml.module.web.findAll { it.'web-uri'.text().endsWith('war') }*.'context-root'*.text()
The trick is to search for web elements - parent of both web-uri and context-root. If such element is found you can easily refer to it's children.

XMLHolder in groovy unable to Retrieve value

I have the following xml:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<SOAP-ENV:Body>
<Login_v1Response>
<result xsi:nil="true"/>
<opSessionID>FjqkjEjipbhkdiin</opSessionID>
</Login_v1Response>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
I have the following code in groovy which returns me null:
def groovyUtils=new com.eviware.soapui.support.GroovyUtils(context)
def holder = groovyUtils.getXmlHolder("Step1-Login#response")
log.info holder.getNodeValue("//SOAP-ENV:Envelope/SOAP-ENV:Body/Login_v1Response/opSessionID")
Please help out.
Thanks.
You are using namespaces in your script, without defining what those namespaces are. For just reading values it is generally easier to use wildcards and not worry about them.
def groovyUtils=new com.eviware.soapui.support.GroovyUtils(context)
def holder = groovyUtils.getXmlHolder("Step1-Login#Response")
log.info holder.getNodeValue("//*:opSessionID")
Or even something simpler like:
log.info context.expand('${Step1-Login#Response#//*:opSessionID}')

How to draw points and lines on widgets using PyQt

I'm making an application, which should draw several points on widget and connect some of them with lines. I've made a form using QT Designer and I want to draw the points on frame for example. I've read that to draw on a widget its paintEvent() method should be reimplemented and I have a problem with it. My MainForm class has following code:
.........
def paintEvent(self, QPaintEvent):
paint = QtGui.QPainter()
paint.begin(self)
paint.setPen(QtCore.Qt.red)
size = self.size()
for i in range(100):
x = random.randint(1, size.width()-1)
y = random.randint(1, size.height()-1)
paint.drawPoint(x, y)
paint.end()
............
That method draws points on main window. How to make paintEvent() draw on exact frame of my form? And one more question: how make it only when I press some button because the code above redraws my window after any event.
I use PyQt v4.10 and Python 3.3 if it's important.
Thanks in advance for any help.
I've solved my problem so: I create my own widget (called PaintSpace) and put it into layout on my main form. Following code is inside MainForm class:
class MyPaintSpace(QtGui.QWidget):
"""My widget for drawing smth"""
def __init__(self):
super(PaintSpace, self).__init__()
<some code>
def paintEvent(self, QPaintEvent):
"""Reimpltmented drawing method of my widget"""
paint = QtGui.QPainter()
paint.begin(self)
<smth we want to draw>
paint.end()
# Make an object...
self.myPaintSpaceYZ = MyPaintSpace()
# ...and put it in layout
self.verticalLayoutYZ.addWidget(self.myPaintSpaceYZ)
After that to redraw my widget I use .update() method.

Resources