pyside2 Implement an input box with a slider visual - pyside2

I want to implement a blender-like property adjustment box with pyside2 in Autodesk Maya, as shown below.
I have found some similar links, but without success specifically how to do it.
How to create graphic slider in Python that can be modified with mouse?
import sys
from PySide2.QtCore import Qt, QEvent
from PySide2.QtGui import QStandardItemModel, QStandardItem
from PySide2.QtWidgets import QApplication, QWidget, QTableView, QHBoxLayout, QStyledItemDelegate, QStyle, QStyleOptionProgressBar, QStyleOptionButton
class MyTableView(QTableView):
def __init__(self):
super(MyTableView, self).__init__()
class MyDelgate(QStyledItemDelegate):
def __init__(self):
super(MyDelgate, self).__init__()
def paint(self, painter, option, index):
if index.column() == 1:
style = QStyleOptionProgressBar()
style.minimum = 0
style.maximum = 10
style.progress= index.data(Qt.DisplayRole)
style.rect = option.rect
QApplication.style().drawControl(QStyle.CE_ProgressBar, style, painter)
elif index.column() == 2:
style = QStyleOptionButton()
if index.data(Qt.DisplayRole) == True:
style.state = QStyle.State_On
else:
style.state = QStyle.State_Off
style.state |= QStyle.State_Enabled
style.rect = option.rect
style.rect.setX(option.rect.x() + option.rect.width() / 2 - 7)
QApplication.style().drawControl(QStyle.CE_CheckBox, style, painter)
else:
return QStyledItemDelegate.paint(self, painter, option, index)
def editorEvent(self, event, model, option, index):
if index.column() == 2:
if event.type() == QEvent.MouseButtonPress and option.rect.contains(event.pos()):
data = not index.data(Qt.DisplayRole)
model.setData(index, data, Qt.DisplayRole)
return True
else:
return QStyledItemDelegate.editorEvent(self, event, model, option, index)
class MyWidget(QWidget):
def __init__(self):
super(MyWidget, self).__init__()
self.mode = QStandardItemModel()
root = self.mode.invisibleRootItem()
item1 = QStandardItem()
item1.setData('a', Qt.DisplayRole)
item2 = QStandardItem()
item2.setData(1, Qt.DisplayRole)
item3 = QStandardItem()
item3.setData(False, Qt.DisplayRole)
item4 = QStandardItem()
item4.setData('b', Qt.DisplayRole)
item5 = QStandardItem()
item5.setData(2, Qt.DisplayRole)
item6 = QStandardItem()
item6.setData(True, Qt.DisplayRole)
root.setChild(0, 0, item1)
root.setChild(0, 1, item2)
root.setChild(0, 2, item3)
root.setChild(1, 0, item4)
root.setChild(1, 1, item5)
root.setChild(1, 2, item6)
tableView = MyTableView()
tableView.setModel(self.mode)
tableView.setItemDelegate(MyDelgate())
layout = QHBoxLayout()
layout.addWidget(tableView)
self.setLayout(layout)
if __name__ == '__main__':
app = QApplication(sys.argv)
w = MyWidget()
w.resize(500, 300)
w.move(300, 300)
w.setWindowTitle('Simple')
w.show()
sys.exit(app.exec_())
Thanks for any advice.

You need to track the mouse position in the editorEvent and compute the ratio based on the sub element rectangle of the style option.
def editorEvent(self, event, model, option, index):
if index.column() == 1:
if event.type() in (event.MouseMove, event.MouseButtonPress):
progressOpt = QStyleOptionProgressBar()
progressOpt.rect = option.rect
style = option.widget.style()
rect = style.subElementRect(style.SE_ProgressBarGroove,
progressOpt, option.widget)
pos = max(0, min(rect.width(), event.x() - rect.x()))
model.setData(index, round(pos / rect.width() * 10), Qt.DisplayRole)
return True
elif index.column() == 2:
if event.type() == QEvent.MouseButtonPress and option.rect.contains(event.pos()):
data = not index.data(Qt.DisplayRole)
model.setData(index, data, Qt.DisplayRole)
return True
return super().editorEvent(event, model, option, index)

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.

setData for second column of QstandardItem

How can i set the data for the second column of a QStandardItem which i then add to a QTreeview?
In my case I just want to place a checkbox or text for the sake of example.
import sys
from PySide import QtGui, QtCore
class Browser(QtGui.QDialog):
def __init__(self, parent=None):
super(Browser, self).__init__(parent)
self.initUI()
def initUI(self):
self.resize(200, 300)
self.setWindowTitle('Assets')
self.items_model = QtGui.QStandardItemModel()
self.ui_items = QtGui.QTreeView()
self.ui_items.setAlternatingRowColors(True)
self.ui_items.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)
self.ui_items.header().setResizeMode(QtGui.QHeaderView.ResizeToContents)
self.ui_items.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
self.ui_items.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)
self.ui_items.setModel(self.items_model)
grid = QtGui.QGridLayout()
grid.setContentsMargins(0, 0, 0, 0)
grid.addWidget(self.ui_items, 0, 0)
self.setLayout(grid)
self.update_model()
def update_model(self):
model = self.ui_items.model()
model.clear()
model.setHorizontalHeaderLabels(['Assets'])
# Create Data
for i in range(1,5):
root = QtGui.QStandardItem()
root.setData('Apple', role=QtCore.Qt.DisplayRole)
root.setColumnCount(2)
model.appendRow(root)
self.ui_items.expandAll()
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
ex = Browser()
ex.show()
sys.exit(app.exec_())
You can pass a list of items to appendRow, with each item representing a column:
# Create Data
for i in range(1,5):
column1 = QtGui.QStandardItem('Apple')
column2 = QtGui.QStandardItem('Orange')
column2.setCheckable(True)
model.appendRow([column1, column2])

Embedding Matplotlib in Tkinter doesn't dispay anything

I am trying to use the figure that is being created inside the class "SubplotAnimation" and place it to my graph page but it doesn't work.. Please help me... Here is my code (Tried to take all the unnecessary stuff, but some are left...):
import matplotlib
matplotlib.use("TkAgg")
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
#import tkinter as tk
import Tkinter as tk
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.lines import Line2D
import matplotlib.animation as animation
class SubplotAnimation(animation.TimedAnimation):
def __init__(self):
fig = plt.figure()
fig.set_size_inches(10, 7)
ax2 = plt.subplot2grid((2, 2), (0, 0), colspan=2)
ax3 = plt.subplot2grid((2, 2), (1, 0), colspan=2)
self.t = np.linspace(0, 80, 400)
self.x = np.cos(2 * np.pi * self.t / 10.)
self.y = np.sin(2 * np.pi * self.t / 10.)
self.z = 10 * self.t
ax2.set_xlabel('y')
ax2.set_ylabel('z')
self.line2 = Line2D([], [], color='black')
ax2.add_line(self.line2)
ax2.set_xlim(0, 800)
ax2.set_ylim(-1, 1)
ax3.set_xlabel('x')
ax3.set_ylabel('z')
self.line3 = Line2D([], [], color='black')
ax3.add_line(self.line3)
ax3.set_xlim(0, 800)
ax3.set_ylim(-1, 1)
animation.TimedAnimation.__init__(self, fig, interval=50, blit=True)
def _draw_frame(self, framedata):
i = framedata
self.line2.set_data(self.z[:i], self.y[:i])
self.line3.set_data(self.z[:i], self.x[:i])
self._drawn_artists = [self.line2, self.line3]
def new_frame_seq(self):
return iter(range(self.t.size))
def _init_draw(self):
lines = [self.line2, self.line3]
for l in lines:
l.set_data([], [])
#ani.save('test_sub.mp4')
#property
def fig(self):
return self._fig
plt.show()
class MainPage(tk.Tk):
def __init__(self, *args, **kwargs):
root = tk.Tk.__init__(self, *args, **kwargs)
tk.Tk.wm_title(self, "Heeeeelp")
container = tk.Frame(self)
container.pack(side="top", fill="both", expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
#********** FRAMES*******#
self.frames = {} #empty..
frame = GraphPage(container, self)
self.frames[GraphPage] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(GraphPage)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class GraphPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self,parent)
label = tk.Label(self, text="Help")
label.grid(row=0, column=0, sticky='NW')
ani = SubplotAnimation()
canvas = FigureCanvasTkAgg(ani.fig, self)
canvas.show()
canvas.get_tk_widget().grid(row=1, column=0, rowspan=6, columnspan=3, sticky='NSEW')
app = MainPage()
app.geometry("980x640")
app.mainloop()
Okay, some things are needed to make this work.
First of all, I don't really understand why you have the code
#property
def fig(self):
return self._fig
but I think you need to just delete this. Also remove the plt.show() beneath it since that does nothing.
Then you need to rename fig in SubplotAnimation to self.fig:
self.fig = plt.figure()
self.fig.set_size_inches(10, 7)
Lastly, you should take the call to animation.TimedAnimation.__init__, put it right behind canvas = FigureCanvasTkAgg(ani.fig, self) and change it to
animation.TimedAnimation.__init__(ani, ani.fig, interval=50, blit=True)
I believe that are all the steps needed to make it work.
If you want to keep the initialization of the animation in your SubplotAnimation class, you can also make a new function to initialize it like
def _init_animation(self):
animation.TimedAnimation.__init__(self, self.fig, interval=50, blit=True)
And call it after canvas = FigureCanvasTkAgg(...) using
ani._init_animation()

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