I have researched heavily on how to get the variables from a different class in wxPython without much luck. My problem is that I want to update a combobox in the main window after the user closes the second window. I thought the best way to do this was to try to get the main window combobox variable somehow. Example:
import wx
class oranges(wx.Frame):
#----------Main Window---------#
def __init__(self,parent,id):
wx.Frame.__init__(self,parent,id,'Test',size=(1024,768))
self.frame=wx.Panel(self)
self.tickers=['Apples','a','1234']
self.dropdown=wx.ComboBox(self.frame,choices=self.tickers,pos=(750,62),style=wx.CB_READONLY)
self.Bind(wx.EVT_COMBOBOX, self.get_stuff,self.dropdown)
apples=wx.Button(self.frame,label='Click here',pos=(300,300),size=(100,100))
self.Bind(wx.EVT_BUTTON, self.plus,apples)
def get_stuff(self,event):
pass
def plus(self,event):
class orange(wx.Frame):
#----------Second Window---------#
def __init__(self,parent,id):
wx.Frame.__init__(self,parent,id,'Testing',size=(500,500))
self.frames=wx.Panel(self)
apples=wx.Button(self.frames,label='Collect Info',pos=(300,300),size=(100,100))
self.Bind(wx.EVT_BUTTON, self.click,apples)
self.what=wx.TextCtrl(self.frames,-1,'12',pos=(200,48))
def click(self,event):
asdf=self.what.GetValue()
self.tickers=[]
self.tickers.append(asdf)
self.dropdown.Clear()
self.dropdown.AppendItems(self.tickers)
#Need to update dropdown#
self.Destroy()
if __name__ =='__main__':
apps = wx.PySimpleApp()
windows = orange(parent=None,id=-1)
windows.Show()
apps.MainLoop()
if __name__ =='__main__':
app = wx.PySimpleApp()
window = oranges(parent=None,id=-1)
window.Show()
app.MainLoop()
I am really confused on how to go about fixing this problem. Thanks in advance! I am looking forward to the answers!
in your parent Frame, add a method called UpdateComboBox(self, newVal) that takes in the new string... then since your popup is a child of that, just before you call self.Destroy in the child, call self.GetParent().UpdateComboBox(asdf) (where asdf is from your example, i.e. the string you want to pass back)
import wx
class SomeUserForm(wx.Dialog):
def __init__(self):
wx.Dialog.__init__(self,None,-1,"Enter User Info In this Frame")
self.txt = wx.TextCtrl(self,-1,pos=(50,50))
self.txt2 = wx.TextCtrl(self,-1,pos=(50,100))
self.ok = wx.Button(self,wx.ID_OK,pos=(50,125))
def GetValue(self):
return self.txt.GetValue() + "::"+ self.txt2.GetValue()
class oranges(wx.Frame):
#----------Main Window---------#
def __init__(self,parent,id):
wx.Frame.__init__(self,parent,id,'Test',size=(1024,768))
self.frame=wx.Panel(self)
self.tickers=['Apples','a','1234']
self.dropdown=wx.ComboBox(self.frame,choices=self.tickers,pos=(750,62),style=wx.CB_READONLY)
self.Bind(wx.EVT_COMBOBOX, self.get_stuff,self.dropdown)
apples=wx.Button(self.frame,label='Click here',pos=(300,300),size=(100,100))
self.Bind(wx.EVT_BUTTON, self.plus,apples)
def get_stuff(self,event):
pass
def plus(self,evt):
dlg = SomeUserForm()
if dlg.ShowModal() != wx.ID_OK:
wx.MessageBox("User Cancelled Add!","Cancelled!")
return
self.dropdown.Append(dlg.GetValue())
if __name__ =='__main__':
app = wx.PySimpleApp()
window = oranges(parent=None,id=-1)
window.Show()
app.MainLoop()
may do what you are asking for ...
Related
I am trying to use PyQt5 QtChart module to plot multiple charts on two different tab widgets with custom mouse and key events to zoom in and out from the charts.
So I created another class to override the QChartView class events like follows:
class my_view(QChartView):
def keyPressEvent(self,event):
if event.key() == Qt.Key_Plus:
ex.my_chart.zoomIn() # ex.chart is accessed from outside
if event.key() == Qt.Key_Minus: # self.passed_parameter would be the solution
ex.my_chart.zoomOut()
def mousePressEvent(self, event):
...
def mouseMoveEvent(self, event):
...
def mouseReleaseEvent(self, event):
...
and in the class Window is the call to my_view:
self.my_chart = QChart()
self.my_chart_view = my_view(self.my_chart, self.parent)
There is the call of the Window class from which the chart can be accessed outside the window class:
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Window()
ex.show()
sys.exit(app.exec_())
The problem came out when I created two instances of my_view like this:
self.my_chart = QChart()
self.my_chart_view = my_view(self.my_chart, self.parent)
self.my_chart1 = QChart()
self.my_chart1_view = my_view(self.my_chart1, self.parent1)
and if I zoomed the second one, the first one was zoomed on the other tab...
So my question is, how can I access self.my_chart from inside the overrided class if I don't know how it is named inside the class?
As ekhumoro stated in his comment, the solution was
self.chart().zoomIn()
Still new to using wx.python, so please let me know if I am doing anything wrong. I am trying to create a pseudo Bitmap toggle button. I have 2 or more Bitmap buttons with an initial background of blue, and when one is clicked its background is supposed to change to green. When this happens, all of the other buttons are supposed to change back to blue, but they stay green. Any ideas?
I have recreated my issue below.
BMP image used, but the image doesn't matter:
*Edit: GenBitmapToggleButton suddenly decided to work now, so I will be using that. I am going to leave this up though as this is still a strange bug since it appears to be working on Linux but not on Windows.
import wx
import wx.lib.buttons as buttons
class MainFrame(wx.Frame):
#----------------------------------------------------------------------
def __init__(self):
wx.Frame.__init__(self, None, title="Test",size=(800,800))
panel = wx.Panel(self,-1,name="panel")
bmp = wx.Bitmap("Discord.bmp", wx.BITMAP_TYPE_ANY)
self.Button1 = buttons.GenBitmapButton(panel,bitmap=bmp,pos=(200,400),size=(bmp.GetWidth()+10, bmp.GetHeight()+10),style=wx.NO_BORDER,name="Button1")
self.Button1.SetBackgroundColour("Blue")
self.Button2 = buttons.GenBitmapButton(panel,bitmap=bmp,pos=(600,400),size=(bmp.GetWidth()+10, bmp.GetHeight()+10),style=wx.NO_BORDER,name="Button2")
self.Button2.SetBackgroundColour("Blue")
self.Bind(wx.EVT_BUTTON, self.OnClick)
self.BitmapButtons = [self.Button1,self.Button2]
self.Show()
def OnClick(self,event):
parent = event.GetEventObject().GetParent().GetName()
name = event.GetEventObject().GetName()
if parent == "panel":
for i in range(0,len(self.BitmapButtons)):
buttonName = self.BitmapButtons[i].GetName()
if buttonName == name:
self.BitmapButtons[i].SetBackgroundColour("Green")
else:
self.BitmapButtons[i].SetBackgroundColour("Blue")
#----------------------------------------------------------------------
if __name__ == "__main__":
app = wx.App(False)
frame = MainFrame()
app.MainLoop()
Here is an option, it uses the state of the button and multiple images to achieve what you are doing and I'd argue should be the preferred method of doing it.
Here, I am only using 2 images but you could use 4, one for each state
Normal state
Focused state
Selected state
and Disabled state
import wx
import wx.lib.buttons as buttons
class MainFrame(wx.Frame):
#----------------------------------------------------------------------
def __init__(self):
wx.Frame.__init__(self, None, title="Test",size=(800,800))
panel = wx.Panel(self,-1,name="panel")
bmp = wx.Bitmap("Discord.png", wx.BITMAP_TYPE_ANY)
bmp2 = wx.Bitmap("Discord1.png", wx.BITMAP_TYPE_ANY)
self.Button1 = buttons.GenBitmapButton(panel,bitmap=bmp,pos=(100,100),name="Button1")
self.Button2 = buttons.GenBitmapButton(panel,bitmap=bmp,pos=(200,100),name="Button2")
self.Button3 = buttons.GenBitmapButton(panel,bitmap=bmp,pos=(300,100),name="Button3")
self.BitmapButtons = [self.Button1,self.Button2,self.Button3]
for i in range(0,len(self.BitmapButtons)):
self.BitmapButtons[i].SetBitmapLabel(bmp)
self.BitmapButtons[i].SetBitmapFocus(bmp2)
self.BitmapButtons[i].SetBitmapSelected(bmp2)
self.Show()
#----------------------------------------------------------------------
if __name__ == "__main__":
app = wx.App(False)
frame = MainFrame()
app.MainLoop()
I have created a window with QTableWidget having a cell with 2 buttons.
Buttons are created in seperate class where i am passing QTableWidget instance from main procedure.
I am not able to get the button events, which are connected in button Creation class. My code snippet is as below
class Buttons():
def __init__(self,tab):
buttonLayout = QtGui.QHBoxLayout()
buttonLayout.setContentsMargins(0,0,0,0)
self.saveButtonItem = QtGui.QPushButton('Save')
self.deleteButtonItem = QtGui.QPushButton('Delete')
buttonLayout.addWidget(self.saveButtonItem)
buttonLayout.addWidget(self.deleteButtonItem)
cellWidget = QtGui.QWidget()
cellWidget.setLayout(buttonLayout)
tab.insertRow(tab.rowCount())
tab.setCellWidget(tab.rowCount() - 1,0,cellWidget)
self.setconncection()
def setconncection(self):
self.saveButtonItem.clicked.connect(self.btnSaveClicked)
self.deleteButtonItem.clicked.connect(self.btnDeleteClicked)
print 'connections are set'
def btnSaveClicked(self):
print 'save clicked'
def btnDeleteClicked(self):
print 'delete clicked'
class testing(QtGui.QTableWidget):
def __init__(self):
super(testing,self).__init__()
self.setColumnCount(1)
for i in xrange(3):
self.r = Buttons(self)
if __name__ == "__main__" :
import sys
app = QtGui.QApplication (sys.argv)
win = testing ()
win.show()
sys.exit(app.exec_())
My window at run time is as below
After the __init__ of testing, the reference to Buttons instance is lost and the object is destroyed. (Variable r is affected but not used.)
Keeping a link to it (see last line in following code snippet) makes it work.
class testing(QtGui.QTableWidget):
def __init__(self):
super(testing,self).__init__()
self.setColumnCount(1)
self.setRowCount(1)
self.buttons = []
for i in xrange(3):
self.buttons.append(Buttons(self))
I have a problem with passing textCtrl data from one class to another in wxpython. I tried using the instance method of passing variables but if I use init_function it is only relevant at the start of the program and doesn't take into account any changes to the text control box after the initial start. Tried the Update() or Refresh() and it didn't work either.
Here is the code simplified.
class DropTarget(wx.DropTarget):
def __init__(self,textCtrl, *args, **kwargs):
super(DropTarget, self).__init__( *args, **kwargs)
self.tc2=kwargs["tc2"]
print self.tc2
class Frame(wx.Frame):
def __init__(self, parent, tc2):
self.tc2 = wx.TextCtrl(self, -1, size=(100, -1),pos = (170,60))#part number
def main():
ex = wx.App()
frame = Frame(None, None)
frame.Show()
b = DropTarget(None, kwarg['tc2'])
ex.MainLoop()
if __name__ == '__main__':
main()
The following way of passing the variable gives me a keyerror. Any help is appreciated.
This isn't the most elegant solution to the problem, but I had a similar issue. If you dump your text to a temporary text file, you can pick it back up whenever you want. So it would be something like this:
tmpFile = open("temp.txt",'w')
tmpFile.write(self.tc2.GetValue())
tmpFile.close()
#when you want the string back in the next class
tmpFile = open("temp.txt",'r')
string = tmpFile.read()
tmpFile.close()
os.system("del temp.txt") #This just removes the file to clean it up, you'll need to import os if you want to do this
import wx
class DropTarget(wx.DropTarget):
def __init__(self,textCtrl, *args, **kwargs):
self.tc2 = kwargs.pop('tc2',None) #remove tc2 as it is not a valid keyword for wx.DropTarget
super(DropTarget, self).__init__( *args, **kwargs)
print self.tc2
class Frame(wx.Frame):
def __init__(self, parent, tc2):
#initialize the frame
super(Frame,self).__init__(None,-1,"some title")
self.tc2 = wx.TextCtrl(self, -1, size=(100, -1),pos = (170,60))#part number
def main():
ex = wx.App(redirect=False)
frame = Frame(None, None)
frame.Show()
#this is how you pass a keyword argument
b = DropTarget(frame,tc2="something")
ex.MainLoop()
if __name__ == '__main__':
main()
there were at least a few errors in your code ... it at least makes the frame now
I have been looking around the Internet but I am not sure if there is a way to show 2 classes in wxPython in 2 separate windows. And could we communicate between them (like one class being the dialog and the other the main class)?
I think I did this before using Show() but I am not sure how to repeat this.
So basically I would like to be able to have a dialog but by using a class instead. This would be more powerful than using Modal dialogs.
Thanks
Here you have a simple example of two frames communicating:
The trick is in sending an object reference to share between frames, either creating one inside the other (as in this case) or through a common parent.
The code is:
import wx
class MainFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, size=(150,100), title='MainFrame')
pan =wx.Panel(self)
self.txt = wx.TextCtrl(pan, -1, pos=(0,0), size=(100,20), style=wx.DEFAULT)
self.but = wx.Button(pan,-1, pos=(10,30), label='Tell child')
self.Bind(wx.EVT_BUTTON, self.onbutton, self.but)
self.child = ChildFrame(self)
self.child.Show()
def onbutton(self, evt):
text = self.txt.GetValue()
self.child.txt.write('Parent says: %s' %text)
class ChildFrame(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, None, size=(150,100), title='ChildFrame')
self.parent = parent
pan = wx.Panel(self)
self.txt = wx.TextCtrl(pan, -1, pos=(0,0), size=(100,20), style=wx.DEFAULT)
self.but = wx.Button(pan,-1, pos=(10,30), label='Tell parent')
self.Bind(wx.EVT_BUTTON, self.onbutton, self.but)
def onbutton(self, evt):
text = self.txt.GetValue()
self.parent.txt.write('Child says: %s' %text)
if __name__ == "__main__":
App=wx.PySimpleApp()
MainFrame().Show()
App.MainLoop()
You can also use pubsub to communicate between two frames. I show one way of doing just that in this article: http://www.blog.pythonlibrary.org/2010/06/27/wxpython-and-pubsub-a-simple-tutorial/
If you don't want the first frame to hide itself, just remove the line with the Hide() in it.