wxpython's treectrl can't expand in windows - windows

Why my wxpython's treectrl can't show and expand in windows but ok in mac:
import wx
class MyFrame(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, wx.DefaultPosition, wx.Size(450, 350))
hbox = wx.BoxSizer(wx.HORIZONTAL)
vbox = wx.BoxSizer(wx.VERTICAL)
panel1 = wx.Panel(self, -1)
panel2 = wx.Panel(self, -1)
self.tree = wx.TreeCtrl(panel1, 1, wx.DefaultPosition, (-1,-1), wx.TR_HIDE_ROOT|wx.TR_HAS_BUTTONS)
root = self.tree.AddRoot('Programmer')
os = self.tree.AppendItem(root, 'Operating Systems')
self.tree.AppendItem(os, 'Linux')
self.tree.AppendItem(os, 'FreeBSD')
self.tree.AppendItem(os, 'OpenBSD')
self.tree.AppendItem(os, 'NetBSD')
self.tree.AppendItem(os, 'Solaris')
self.tree.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelChanged, id=1)
self.display = wx.StaticText(panel2, -1, '',(10,10), style=wx.ALIGN_CENTRE)
self.tree.Bind(wx.EVT_TREE_ITEM_EXPANDING,self.OnExpanding, id=1)
self.tree.Bind(wx.EVT_TREE_ITEM_EXPANDED,self.OnExpanded, id=1)
self.tree.Bind(wx.EVT_TREE_ITEM_ACTIVATED,self.OnActivated, id=1)
self.tree.Bind(wx.EVT_TREE_ITEM_COLLAPSED,self.OnCollapsed, id=1)
self.tree.Bind(wx.EVT_TREE_ITEM_COLLAPSING,self.OnCollaping, id=1)
vbox.Add(self.tree, 1, wx.EXPAND)
hbox.Add(panel1, 1, wx.EXPAND)
hbox.Add(panel2, 1, wx.EXPAND)
panel1.SetSizer(vbox)
self.SetSizer(hbox)
self.Centre()
def OnSelChanged(self, event):
item = event.GetItem()
self.display.SetLabel(self.tree.GetItemText(item))
def OnExpanding(self,evt):
print "OnExpanding"
def OnExpanded(self,evt):
print "OnExpaned"
def OnActivated(self,evt):
print "OnActivated"
def OnCollapsed(self,evn):
print "OnCollapsed"
def OnCollaping(self,evt):
print "OnCollaping"
class MyApp(wx.App):
def OnInit(self):
frame = MyFrame(None, -1, 'treectrl.py')
frame.Show(True)
self.SetTopWindow(frame)
return True
app = MyApp(0)
app.MainLoop()
I run this code with:
python2.7-win32
wxPython3.0-win32-3.0.2.0-py27
window7-64
and in windows then event about expand and collaps is never be sended too
so how can tell me where am i wrong?

Apparently wx.TR_LINES_AT_ROOT is needed on Windows when hiding the root and you still want to display the expand/collapse buttons. Alternatively, you can just add the hide-root style to the default style and not have to worry about this platform specific difference, like: wx.TR_HIDE_ROOT | wx.TR_DEFAULT_STYLE

Related

PySide2: Children move weirdly when they are selected and the parent is moving

Let me explain my problem in detail. I have a QGraphicsRectItem as a parent in QGraphicsScene, and I have QGraphicsPolygonItems as its children. When The children are not selected and I move the parent everything's fine - they keep their positions relative to the parent and move with it. But when children are selected and I move the parent children move weirdly (I would like them to behave the same way as if they were not selected - move relative to their parent). Here's the code and a gif displaying both situations.
class Test(QWidget):
def __init__(self, parent=None):
super(Test, self).__init__(parent)
self.resize(1000, 800)
self.generalLayout = QVBoxLayout()
self.view_ = GraphicsView()
self.size_grip = QSizeGrip(self)
self.generalLayout.addWidget(self.size_grip, 0, Qt.AlignBottom | Qt.AlignRight)
self.generalLayout.addWidget(self.view_)
self.setLayout(self.generalLayout)
def contextMenuEvent(self, event):
self.menu = QMenu(self)
self.new_children_menu = QMenu("New child", self.menu)
parentAction = QAction("New Parent", self)
childAction = QAction('Child', self)
click_pos = self.view_.mapToScene(event.pos())
parent_item = self.itemUnderMouse()
mouse_pos = self.mousePosition(click_pos, parent_item)
parentAction.triggered.connect(lambda: self.view_.addParent(mouse_pos, parent_item))
childAction.triggered.connect(lambda: self.view_.addButton(mouse_pos, parent_item))
self.new_children_menu.addAction(childAction)
self.menu.addAction(parentAction)
self.menu.addMenu(self.new_children_menu)
self.menu.popup(QCursor.pos())
def mousePosition(self, click, prnt_item):
if prnt_item is None:
return click
else:
return prnt_item.mapFromScene(click)
def itemUnderMouse(self):
for item in self.view_.scene().items():
if item.isUnderMouse():
return item
else:
continue
class GraphicsView(QGraphicsView):
def __init__(self):
super(GraphicsView, self).__init__()
self.setAttribute(Qt.WA_StyledBackground, True)
self.setStyleSheet('background-color: white;')
self.setRenderHints(QPainter.Antialiasing | QPainter.SmoothPixmapTransform)
self.setMouseTracking(True)
self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
self.setFrameShape(QFrame.NoFrame)
self.setCursor(QCursor(Qt.PointingHandCursor))
self.size_grip = QSizeGrip(self)
self._scene = QGraphicsScene()
self._scene.setSceneRect(0, 0, 400, 400)
self.setScene(self._scene)
self.fitInView(self.scene().sceneRect(), Qt.KeepAspectRatio)
self.setDragMode(QGraphicsView.ScrollHandDrag)
self.parent = GraphicsRectItem
self.child = newButton
def addParent(self, pos, prnt):
new_parent = self.parent(0, 0, 100, 150)
new_parent.setPos(pos)
if prnt is None:
self.scene().addItem(new_parent)
else:
new_parent.setParentItem(prnt)
def addButton(self, pos, parent_item):
new_button = self.child(pos)
if parent_item is None:
self.scene().addItem(new_button)
else:
new_button.setParentItem(parent_item)
class GraphicsRectItem(QGraphicsRectItem):
def __init__(self, *args):
super().__init__(*args)
self.setAcceptHoverEvents(True)
self.setFlag(QGraphicsItem.ItemIsMovable, True)
self.setFlag(QGraphicsItem.ItemSendsGeometryChanges, True)
self.setFlag(QGraphicsItem.ItemIsFocusable, True)
class newButton(QGraphicsPolygonItem):
def __init__(self, pos):
super(newButton, self).__init__()
self.newPoly = QPolygonF()
self.newPolyPoints = (QPointF(0, 0),
QPointF(0, 50),
QPointF(50, 50),
QPointF(50, 0))
for point in self.newPolyPoints:
self.newPoly.append(point)
self.setPolygon(self.newPoly)
self.setBrush(QBrush(QColor("violet")))
self.setPen(QPen(QColor("gray")))
self.setFlags(
self.ItemIsSelectable
| self.ItemIsMovable
| self.ItemIsFocusable
| self.ItemSendsGeometryChanges
)
self.setAcceptHoverEvents(True)
poly_center = self.boundingRect().center()
self.setTransformOriginPoint(poly_center)
self.setPos(pos)
if __name__ == '__main__':
app = QApplication([])
win = Test()
win.show()
app.exec_()
I also want the children to not go out of the parent's bounding rectangle area, but if I set the "ItemClipsChildrenToShape" flag the children disappear inside the parent. This gif illustrates that situation.

Matplotlib embedded in wxPython: TextCtrl in Navigation toolbar not working on macos

I'm doing a simple embedded graph with Matplotlib APIs (2.2.2) in wxPython (Phoenix 4.0.1) and Python 3.6.4. I have subclassed the WXAgg Navigation toolbar so I can remove the "configure subplots" tool and this is working fine.
In addition, I have added a read-only TextCtrl into my subclassed toolbar to show mouse coordinates (just like it appears in the pyplot state-based version of matplotlib). I've implemented a simple handler for the mouse move events per the Matplotlib docs and this is all working fine on Windows 10.
However, this code does not fully work on macOS (10.13.4 High Sierra). The graph displays just fine, the toolbar displays fine, the toolbar buttons work fine, but I don't get any display of my TextCtrl with the mouse coordinates in the toolbar (or even the initial value as set when I create the TextCtrl).
Can anyone shed light on why the TextCtrl in the Matplotlib toolbar doesn't work on the mac? Is there a way to do this on the mac? And if this is simply not possible, what are my alternatives for showing the mouse coordinates elsewhere in my Matplotlib canvas?
Here's my sample code:
import wx
from matplotlib.figure import Figure
from matplotlib import gridspec
import numpy as np
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.backends.backend_wx import NavigationToolbar2Wx as NavigationToolbar
class MyToolbar(NavigationToolbar):
def __init__(self, plotCanvas):
# create the default toolbar
NavigationToolbar.__init__(self, plotCanvas)
# Add a control to display mouse coordinates
self.info = wx.TextCtrl(self, -1, value = 'Coordinates', size = (100,-1),
style = wx.TE_READONLY | wx.BORDER_NONE)
self.AddStretchableSpace()
self.AddControl(self.info)
# Remove configure subplots
SubplotsPosition = 6
self.DeleteToolByPos(SubplotsPosition)
self.Realize()
class Graph(wx.Frame):
def __init__(self, parent, title='Coordinates Test'):
super().__init__(parent, title=title)
self.SetSize((900, 500))
# A simple embedded matplotlib graph
self.fig = Figure(figsize = (8.2,4.2), facecolor = 'gainsboro')
self.canvas = FigureCanvas(self, -1, self.fig)
gs = gridspec.GridSpec(2, 1, left = .12, right = .9, bottom = 0.05, top = .9, height_ratios = [10, 1], hspace = 0.35)
ax = self.fig.add_subplot(gs[0])
t = np.arange(0.0, 2.0, 0.01)
s = 1 + np.sin(2 * np.pi * t)
ax.plot(t, s)
ax.set(xlabel='time (s)', ylabel='voltage (mV)',
title='About as simple as it gets, folks')
ax.grid()
ax.set_navigate(True)
# Get a toolbar instance
self.toolbar = MyToolbar(self.canvas)
self.toolbar.Realize()
# Connect to matplotlib for mouse movement events
self.canvas.mpl_connect('motion_notify_event', self.onMotion)
self.toolbar.update()
# Layout the frame
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(self.canvas, 1, wx.LEFT | wx.EXPAND)
self.sizer.Add(self.toolbar, 0, wx.LEFT | wx.EXPAND)
self.SetSizer(self.sizer)
def onMotion(self, event):
if event.inaxes:
xdata = event.xdata
ydata = event.ydata
self.toolbar.info.ChangeValue(f'x = {xdata:.1f}, y = {ydata:.1f}')
else:
self.toolbar.info.ChangeValue('')
class MyFrame(wx.Frame):
def __init__(self, parent, title=""):
super().__init__(parent, title=title)
self.SetSize((800, 480))
self.graph = Graph(self)
self.graph.Show()
class MyApp(wx.App):
def OnInit(self):
self.frame = MyFrame(None, title='Main Frame')
self.frame.Show()
return True
if __name__ == "__main__":
app = MyApp(False)
app.MainLoop()
I realize this is late, but I think that the simplest solution is to not subclass NavigationToolbar at all, but just to add a TextCtrl of your own.
That is, getting rid of your MyToolbar altogether and modifying your code to be
# Get a toolbar instance
self.toolbar = NavigationToolbar(self.canvas)
self.info = wx.TextCtrl(self, -1, value = 'Coordinates', size = (100,-1),
style = wx.TE_READONLY | wx.BORDER_NONE)
self.canvas.mpl_connect('motion_notify_event', self.onMotion)
self.toolbar.update()
# Layout the frame
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(self.canvas, 1, wx.LEFT | wx.EXPAND)
bottom_sizer = wx.BoxSizer(wx.HORIZONTAL)
bottom_sizer.Add(self.toolbar, 0, wx.LEFT | wx.EXPAND)
bottom_sizer.Add(self.info, 1, wx.LEFT | wx.EXPAND)
self.sizer.Add(bottom_sizer, 0, wx.LEFT | wx.EXPAND)
self.SetSizer(self.sizer)
def onMotion(self, event):
if event.inaxes is not None:
xdata = event.xdata
ydata = event.ydata
self.info.ChangeValue(f'x = {xdata:.1f}, y = {ydata:.1f}')
else:
self.info.ChangeValue('')
will give TextCtrl that does display the motion events.

wxpython, how to set background color and foreground color in textctrl?

I want to set color for words, background and foreground colors both are needed. I learned tkinter first, but it seems wxpython have no similar methods.
the following code is easy to test, copy "hello world, Hello World, heLLo WORLD" to area_example, tell me how to highlight "hello", ignorecase
#!/usr/bin/env python
# coding=utf8
import wx
rows = 5
cols = 2
vgap = 20
hgap = 10
class Search(wx.Frame):
#not_resizable = wx.DEFAULT_FRAME_STYLE ^ (wx.RESIZE_BORDER | wx.MAXIMIZE_BOX) # ok
not_resizable = wx.DEFAULT_FRAME_STYLE & ~(wx.RESIZE_BORDER | wx.MAXIMIZE_BOX)
def __init__(self, parent, title, size):
super(Search, self).__init__(parent, title=title, size=size, style=self.not_resizable)
self.init_elements()
self.lay_out()
self.Centre()
self.Show()
def init_elements(self):
self.panel = wx.Panel(self)
self.entry_name = wx.TextCtrl(self.panel)
self.entry_name.SetFocus()
self.btn_add = wx.Button(self.panel, label="Add")
self.btn_add.Disable()
self.btn_recite = wx.Button(self.panel, label="Recite")
self.btn_recite.Disable()
self.btn_flash = wx.Button(self.panel, label="Flash")
self.btn_flash.Disable()
self.label_phonetic = wx.StaticText(self.panel, label='')
self.area_meaning = wx.TextCtrl(self.panel, style=wx.TE_MULTILINE)
self.area_example = wx.TextCtrl(self.panel, style=wx.TE_MULTILINE)
self.btn_save = wx.Button(self.panel, label="Save")
self.btn_sort = wx.Button(self.panel, label="Sort")
def lay_out(self):
hbox = wx.BoxSizer(wx.HORIZONTAL)
grid = wx.FlexGridSizer(rows, cols, vgap, hgap)
grid.AddMany([
(self.entry_name), (self.btn_add),
(self.label_phonetic), (self.btn_recite),
(self.area_meaning, 1, wx.EXPAND), (self.btn_flash),
(self.area_example, 1, wx.EXPAND), (self.btn_sort),
(self.btn_save),
])
grid.AddGrowableCol(0, 1)
grid.AddGrowableRow(2, 1)
grid.AddGrowableRow(3, 1)
hbox.Add(grid, proportion=1, flag=wx.ALL | wx.EXPAND, border=15)
self.panel.SetSizer(hbox)
#self.panel.SetSizerAndFit(hbox)
def OnKeyUp(self, e):
code = e.GetKeyCode()
if code == wx.WXK_RETURN:
self.enter_handler(e)
def enter_handler(self, e):
word = self.entry_name.GetValue()
if word:
self.highlight(word)
def highlight(self, name):
# todo
# add background color and foreground color, ignore case
print 'highlight'
def search_test():
app = wx.App()
title = 'Search Test'
size = (800, 500)
s = Search(None, title, size)
s.entry_name.Bind(wx.EVT_KEY_UP, s.OnKeyUp)
app.MainLoop()
if __name__ == '__main__':
search_test()
the doc version when I asked the question was wxPython 3.0.3, last updated 13 March 2015 from revision 1725+2c3b7a8.
but the wxPython version brew install on osx was 3.0.2, some classes and methods were not available.
On the docs it explains how to do this: http://wxpython.org/Phoenix/docs/html/TextCtrl.html#phoenix-title-textctrl-styles
Here is an example snippet (Should go below your definition of self.area_example)
self.area_example.SetDefaultStyle(wx.TextAttr(wx.RED))
self.area_example.AppendText("Red text\n")
self.area_example.SetDefaultStyle(wx.TextAttr(wx.NullColour,
wx.LIGHT_GREY))
self.area_example.AppendText("Red on grey text\n")
self.area_example.SetDefaultStyle(wx.TextAttr(wx.BLUE))
self.area_example.AppendText("Blue on grey text\n")
As for checking if the word is "hello", I can only think right now as to bind it and check it.
self.area_example.Bind(wx.EVT_CHAR, self.OnKeyDown)
The "OnKeyDown" function is just an example. It runs but you'll most likely want a better way of doing it.
def OnKeyDown(self, e):
last_word = self.area_example.GetValue().split()[-1]
if last_word.lower() == "hello":
print("Change color")
e.Skip()
From there you should be able to accomplish what you need.

wxPython: Getting a EVT_KEY_DOWN event for CMD+[other key] on OSX

I'm trying to catch an event when the user presses COMMAND + [any other key] on OSX. Since these are actually two key presses I expect two events: One when COMMAND is pressed and one when the other key is pressed (without releasing the COMMAND key). This works fine for every modifier except COMMAND where I only get the first event. Why is that and how can I fix it?
Version: wxPython3.0-osx-cocoa-py2.7
Example code:
import wx
def OnKeyDown(e):
print "Modifiers: {} Key Code: {}".format(e.GetModifiers(), e.GetKeyCode())
app = wx.App()
frame = wx.Frame(None)
textctrl = wx.TextCtrl(frame, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, wx.WANTS_CHARS)
textctrl.Bind(wx.EVT_KEY_DOWN, OnKeyDown)
frame.Show()
app.MainLoop()
For ALT + d the output is:
Modifiers: 1 Key Code: 307
Modifiers: 1 Key Code: 68
For SHIFT + d the output is:
Modifiers: 4 Key Code: 306
Modifiers: 4 Key Code: 68
Only for COMMAND + d the output is:
Modifiers: 2 Key Code: 308
Thanks for your help
Additional Information: I'm using OSX 10.8 on a virtual machine. As RobinDunn points out that it works on his laptop. So chances are that this is just a problem in my environment. wnnmaw provided a good workaround which works for me even on the virtual environment.
Alright, so it took me some time, but here's a working code block that does what you want.
Some Things to Note:
I did this on Windows (so there are some changes you can make such as adding support for wx.ACCEL_RAW_CTRL which corresponds to the actual control key on Mac whereas wx.ACCCEL_CTRL corresponds to the command key
This code definitely can (and needs to be) cleaned up
You'll have to add better error checking before you give this to a user
Whithout further adieu, here it is
import wx
from wx.lib.scrolledpanel import ScrolledPanel
class TestWindow(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1, 'Accelerator Table Test', size=(600, 400))
self.panel = ScrolledPanel(parent=self, id=-1)
self.panel.SetupScrolling()
#Create IDs to be used in initial acclerator table
self.functionList = [self.func1, self.func2, self.func3, self.func4, self.func5, self.OnAdd, self.OnDel]
self.functionListstr = ["self.func1", "self.func2", "self.func3", "self.func4", "self.func5", "self.OnAdd", "self.OnDel"]
self.IDDict = {i: wx.NewId() for i in range(len(self.functionList))}
self.IDDictrev = {val:key for key, val in self.IDDict.iteritems()}
self.aTableList = [(wx.ACCEL_ALT, ord('S'), self.IDDict[0]),(wx.ACCEL_CTRL, ord('Q'), self.IDDict[1])]
#Set up initial accelerator table
aTable = wx.AcceleratorTable(self.aTableList)
self.SetAcceleratorTable(aTable)
#Bind inital accelerator table IDs to functions
for i in range(len(self.functionList)):
self.Bind(wx.EVT_MENU, self.functionList[i], id=self.IDDict[i])
#Set up control widgets on GUI
self.flexgrid = wx.FlexGridSizer(cols=3, hgap=10, vgap=5)
cmdkeylbl = wx.StaticText(self.panel, -1, "Command Key")
self.cmdkey = wx.ComboBox(self.panel, style=wx.CB_READONLY)
cmdkeylist = ["Alt", "Control/Command", "Shift", "OSX Control", "None"]
self.cmdkeyconstants = {"Alt":wx.ACCEL_ALT, "Control/Command":wx.ACCEL_CTRL, "Shift":wx.ACCEL_SHIFT, "None":wx.ACCEL_NORMAL}
self.cmdkeyconstantsrev = {val:key for key, val in self.cmdkeyconstants.iteritems()}
self.cmdkey.SetItems(cmdkeylist)
hotkeylbl = wx.StaticText(self.panel, -1, "HotKey (single letter only)")
self.hotkey = wx.TextCtrl(self.panel, size=(50,-1))
funclbl = wx.StaticText(self.panel, -1, "Function")
self.func = wx.ComboBox(self.panel, style=wx.CB_READONLY)
self.func.SetItems(self.functionListstr)
self.hbox = wx.BoxSizer(wx.HORIZONTAL)
addBtn = wx.Button(self.panel, -1, "Add")
delBtn = wx.Button(self.panel, -1, "Delete")
self.Bind(wx.EVT_BUTTON, self.OnAdd, addBtn)
self.Bind(wx.EVT_BUTTON, self.OnDel, delBtn)
self.vbox = wx.BoxSizer(wx.VERTICAL)
self.curATable = wx.StaticText(self.panel, -1, self._DisplayATable())
self.flexgrid.Add(cmdkeylbl)
self.flexgrid.Add(hotkeylbl)
self.flexgrid.Add(funclbl)
self.flexgrid.Add(self.cmdkey)
self.flexgrid.Add(self.hotkey)
self.flexgrid.Add(self.func)
self.hbox.Add((20, 20), 0)
self.hbox.Add(addBtn)
self.hbox.Add((0, 0), 0)
self.hbox.Add(delBtn)
self.hbox.Add((20, 20), 0)
self.vbox.Add(self.flexgrid, flag=wx.TOP|wx.BOTTOM|wx.LEFT|wx.RIGHT|wx.EXPAND, border = 5)
self.vbox.Add(self.hbox, flag=wx.TOP|wx.BOTTOM|wx.LEFT|wx.RIGHT|wx.EXPAND, border = 5)
self.vbox.Add(self.curATable, flag=wx.TOP|wx.BOTTOM|wx.LEFT|wx.RIGHT|wx.EXPAND, border = 5)
self.panel.SetSizer(self.vbox)
self.panel.Layout()
#Class Functions
def _DisplayATable(self):
aTablelbl = ""
for cmdKey, hotKey, Func in self.aTableList:
aTablelbl += "{} + {} calls {}\n".format(self.cmdkeyconstantsrev[cmdKey], chr(hotKey), self.functionListstr[self.IDDictrev[Func]])
return aTablelbl
def OnAdd(self, event):
self.aTableList.append((self.cmdkeyconstants[self.cmdkey.GetValue()], ord(self.hotkey.GetValue()[:1].title()), self.IDDict[self.func.GetSelection()]))
print "Added {} + {} as a shortcut for {}!".format(self.cmdkey.GetValue(), self.hotkey.GetValue()[:1].title(), self.functionListstr[self.func.GetSelection()])
aTable = wx.AcceleratorTable(self.aTableList)
self.SetAcceleratorTable(aTable)
self.curATable.SetLabel(self._DisplayATable())
self.panel.Layout()
def OnDel(self, event):
if (self.cmdkeyconstants[self.cmdkey.GetValue()], ord(self.hotkey.GetValue()[:1].title()), self.IDDict[self.func.GetSelection()]) in self.aTableList:
self.aTableList.remove((self.cmdkeyconstants[self.cmdkey.GetValue()], ord(self.hotkey.GetValue()[:1].title()), self.IDDict[self.func.GetSelection()]))
aTable = wx.AcceleratorTable(self.aTableList)
self.SetAcceleratorTable(aTable)
self.curATable.SetLabel(self._DisplayATable())
self.panel.Layout()
else:
dlg = wx.MessageDialog(self, "ERROR: That combination is not in the accelerator table!", "Error", style=wx.OK)
dlg.ShowModal()
dlg.Destroy()
def func1(self, event):
dlg = wx.MessageDialog(self, "Func1", "Func1", style=wx.OK)
dlg.ShowModal()
dlg.Destroy()
def func2(self, event):
dlg = wx.MessageDialog(self, "Func2", "Func2", style=wx.OK)
dlg.ShowModal()
dlg.Destroy()
def func3(self, event):
dlg = wx.MessageDialog(self, "Func3", "Func3", style=wx.OK)
dlg.ShowModal()
dlg.Destroy()
def func4(self, event):
dlg = wx.MessageDialog(self, "Func4", "Func4", style=wx.OK)
dlg.ShowModal()
dlg.Destroy()
def func5(self, event):
dlg = wx.MessageDialog(self, "Func5", "Func5", style=wx.OK)
dlg.ShowModal()
dlg.Destroy()
app = wx.App(False)
frame = TestWindow()
frame.Show()
app.MainLoop()
Hopefully this is what you're looking for, let me know if you have any questions

Works on Fedora but not on Windows, wx.Phyton

Well im quite a noob with wx and i started learning it 5 days ago. I'm trying to make a game like memory with cards like bitmap buttons but events don't want to bind on my cards. I searched the Internet and asked some people for help but they don't know why. I sent the program to one person who works in Linux Fedora and he says it works...
The problem is in class MyDialog, function Cards. I made a test program, similar to this one and binded the events in the for command where it worked properly.
Sorry if the answer exists somewhere on this website, I couldn't find it...
import random
import wx
global n
global ControlVar
ControlVar = False
class MyDialog(wx.Dialog):
def __init__(self, parent, id, title):
wx.Dialog.__init__(self, parent, id, title, size=(200, 150))
wx.StaticBox(self, -1, 'Card pairs', (5, 5), size=(180, 70))
wx.StaticText(self, -1, 'Number: ', (15, 40))
self.spin = wx.SpinCtrl(self, -1, '1', (65, 40), (60, -1), min=3, max=5)
self.spin.SetValue(4)
wx.Button(self, 2, 'Ok', (70, 85), (60, -1))
self.Bind(wx.EVT_BUTTON, self.OnClose, id=2)
self.Centre()
self.ShowModal()
self.Destroy()
def OnClose(self, event):
pair = self.spin.GetValue()
self.Close()
return(pair)
class MyMenu(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, wx.DefaultPosition, wx.Size(1000, 700))
self.SetMinSize(wx.Size(400, 300))
self.panel = wx.Panel(self, wx.ID_ANY)
self.SetIcon(wx.Icon('computer.png', wx.BITMAP_TYPE_ANY))
bmp = wx.Image('wood.png', wx.BITMAP_TYPE_ANY).ConvertToBitmap()
bitmap = wx.StaticBitmap(self, -1, bmp, (0, 0))
menubar = wx.MenuBar()
file = wx.Menu()
edit = wx.Menu()
file.Append(101, '&New Game', 'Start a New Game')
file.AppendSeparator()
file.Append(105,'&Quit\tEsc', 'Quit the Application')
menubar.Append(file, '&File')
self.SetMenuBar(menubar)
self.statusbar = self.CreateStatusBar()
self.Centre()
self.Bind(wx.EVT_MENU, self.OnNew, id=101)
self.Bind(wx.EVT_MENU, self.OnQuit, id=105)
self.panel.Bind(wx.EVT_KEY_DOWN, self.OnKey)
def OnNew(self, event):
if ControlVar:
for i in range(n*2):
self.dugmad[i].Destroy()
md = MyDialog(None, -1, 'New Game')
n = md.OnClose(None)
self.statusbar.SetStatusText('You Selected {} Pairs.'.format(n))
self.Cards()
def OnButton(self, event):
print('ANYTHING PLEASE!')
## problem ahead!
def Cards(self):
image = wx.Image('cveteki.jpg', wx.BITMAP_TYPE_ANY).ConvertToBitmap()
self.dugmad = []
for i in range(2*n):
dugme = wx.BitmapButton(self, i, image)
self.dugmad.append(dugme)
self.Bind(wx.EVT_BUTTON, self.OnButton, id=i)
if n == 3:
self.Draw(2, 3)
if n == 4:
self.Draw(2, 4)
if n == 5:
self.Draw(2, 5)
def Draw(self,a, b):
gs = wx.GridSizer(a,b,40,40)
for i in range(n*2):
gs.Add(self.dugmad[i],0, wx.EXPAND)
vbox = wx.BoxSizer(wx.VERTICAL)
vbox.Add(gs, 1, wx.EXPAND | wx.ALL, 40)
self.SetSizer(vbox)
self.Layout()
self.Refresh()
global ControlVar
ControlVar=True
def OnKey(self, event):
keycode = event.GetKeyCode()
if keycode == wx.WXK_ESCAPE:
box = wx.MessageDialog(None, 'Are you sure you want to quit?', 'Quit', wx.YES_NO | wx.ICON_QUESTION)
if box.ShowModal() == wx.ID_YES:
self.Close()
def OnQuit(self, event):
box = wx.MessageDialog(None, 'Are you sure you want to quit?', 'Quit', wx.YES_NO | wx.ICON_QUESTION)
if box.ShowModal() == wx.ID_YES:
self.Destroy()
class MyApp(wx.App):
def OnInit(self):
frame = MyMenu(None, -1, 'Memory')
frame.Show(True)
return (True)
def main():
app = MyApp(False)
app.MainLoop()
main()
I tried to run your code but I don't have images with those names at the ready, and I can't understand all your globals, and I get an error about n not defined. So I made a simple test for you which I hope helps:
import wx
app = wx.App()
def onButton(evt):
print "button pressed!", evt.GetEventObject().GetLabel()
frm = wx.Frame(None)
for i in range(10):
but = wx.Button(frm, pos=(10, i*20), label="button %s" % i)
but.Bind(wx.EVT_BUTTON, onButton)
frm.Show()
app.MainLoop()
The but.Bind(...) could also be frm.Bind(...) if you really want. Note that I don't futz with the id's: I couldn't care less what id's wxPython assigned the buttons.
I'm not sure what's wrong with your code because I couldn't run it and didn't want to debug the other errors with it.
Again, I hope this helps.
But why are you destroying your MyDialog just after it is created? Check: there is self.Destroy() method call immediately after self.ShowModal().

Resources