I would like to animate a blue box inside a panel, using a wxTimer. But nothing happens
I set up a custom panel class in which i draw the box
I set up a custom frame, which integrates my custom panel
Here my code :
#!/usr/bin/python
# -*- coding: iso-8859-15 -*-
import wx
WHITE_COLOR = (255,255,255)
class AnimationPanel(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
self.boxParameters = [10,10,60,60]
self.SetBackgroundColour(wx.Colour(*WHITE_COLOR))
self.Bind(wx.EVT_PAINT, self.OnPaint)
timer = wx.Timer(self)
timer.Start(100)
self.Bind(wx.EVT_TIMER, self.OnTimer, timer)
def OnPaint(self, event):
dc = wx.PaintDC(self)
self.paintBox(dc)
def OnTimer(self, event):
self.boxParameters[0] += 3
self.Update()
def paintBox(self, dc):
dc.SetBrush(wx.Brush("blue"))
dc.DrawRectangle(*self.boxParameters)
class MainFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, title="Box with far and back movement", size=(300,200))
AnimationPanel(self)
if __name__ == "__main__":
app = wx.PySimpleApp()
frame = MainFrame()
frame.Show(True)
app.MainLoop()
Thanks in advance
You are missing a couple of things. First is that the wx.Timer is going out of scope once you've reached the end of the init method, so it's destroyed before it even gets to do anything. Next, you want to use Refresh() instead of Update() as Refresh() will mark the rectangle (or the entire screen) as "dirty" and cause it to be repainted. See the docs for more info: http://www.wxpython.org/docs/api/wx.Window-class.html
Here's an updated version that works on my Windows box:
import wx
WHITE_COLOR = (255,255,255)
class AnimationPanel(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
self.boxParameters = [10,10,60,60]
self.SetBackgroundColour(wx.Colour(*WHITE_COLOR))
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.timer = wx.Timer(self)
self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer)
self.timer.Start(100)
def OnPaint(self, event):
dc = wx.PaintDC(self)
self.paintBox(dc)
def OnTimer(self, event):
self.boxParameters[0] += 3
print self.boxParameters
self.Refresh()
def paintBox(self, dc):
dc.SetBrush(wx.Brush("blue"))
dc.DrawRectangle(*self.boxParameters)
class MainFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, title="Box with far and back movement", size=(300,200))
AnimationPanel(self)
if __name__ == "__main__":
app = wx.PySimpleApp()
frame = MainFrame()
frame.Show(True)
app.MainLoop()
Related
If use override def afterAll in base class.
I want override def afterAll at all testcase finished after,but i enabling parallel after, as each testcase will call override def afterAll.Causes the file to be deleted early every time.
But i must use parallel.
code:
abstract class TestBaseWithFunSuite extends FunSuite with BeforeAndAfterAll{
def cleanFolder(sparkPath:String): Unit =
{
val fs = FileSystem.get(spark.sparkContext.hadoopConfiguration)
val srcPath = new Path(sparkPath)
if (fs.exists(srcPath) && fs.getFileStatus(srcPath).isDirectory)
fs.delete(srcPath, true)
}
protected def csvOptions: Map[String, String] = Map("header"->"true", "delimiter"->",")
protected def sparkPath: String = s"${folderPath}/target/com.microsoft.mpdp/pipeline/spark-warehouse"
protected def streamName: String = TEST_DATASOURCE
protected def csvPath: String = sparkPath
override def afterAll{
cleanFolder(sparkPath)
}
}
Becauses all testcase will call this method.
So some test can't load this file dir.
java.io.FileNotFoundException: File file:/D:/Marketplace.DataPlatform/src/pipeline/target/com.microsoft.mpdp/pipeline/spark-warehouse/test/watermark/part-00000-a65b3b2e-b6cf-4415-a65a-79a7549a4d71-c000.csv does not exist
Python 3.7+wxPython 4.0.6 (same as 4.0.2)+windows 10 (64-bit)
Because I need a sub frame which can floating on main frame, so use style: wx.FRAME_FLOAT_ON_PARENT.
Operations: First open the sub frame, then minimize the main frame. After restoring from minimize, hide the sub frame (using Hide()). Then minimize->restore again. The sub frame is shown automatically, and can not be hidden.
I have tested that at this time, frame.IsShown() returns False.
Sample as follows.
import wx
class MainFrame(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, id=-1, parent=parent, size=wx.Size(600, 500),
title='Test')
self.panel = wx.Panel(self, id=-1, pos=(200, 300))
self.button = wx.Button(self.panel, id=-1, label='button',
pos=wx.Point(20, 56), size=wx.Size(87, 28))
self.button.Bind(wx.EVT_BUTTON, self.OnButton, id=-1)
self.frame = MyFrame(self)
def OnButton(self, event):
self.frame.Show()
event.Skip()
class MyFrame(wx.Frame):
def __init__(self, parent):
style = wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX | \
wx.MINIMIZE_BOX | wx.FRAME_NO_TASKBAR | wx.FRAME_FLOAT_ON_PARENT
wx.Frame.__init__(self, id=-1, parent=parent, size=wx.Size(300, 200),
title='Sub', style=style)
self.Bind(wx.EVT_CLOSE, self.OnClose)
def OnClose(self, evt):
self.Hide()
if __name__ == '__main__':
app = wx.App()
frame = MainFrame(None)
frame.Show()
app.MainLoop()
I do not need to close the sub frame. I need to hide it.
The detail operations are:
Click the button to open the sub frame.
Click the minimize button of the main frame. (-> All the frames are minimized.)
Click the icon in taskbar to restore the main frame.
Click the "×" button of the sub frame.
Click the minimize button of the main frame again.
Click the icon in taskbar to restore the main frame.
-> Problem: the sub frame is shown. And can not use "×" button to hide it.
I need the sub frame shown on main frame when it loses focus, so I used wx.FRAME_FLOAT_ON_PARENT.
Any advice?
I cannot reproduce the behavior you describe using wxPython 4.0.4, python 3.7 and macOS. But anyway, I do not think that you will be able to close MyFrame using the GUI because you are modifying the normal behavior of the wx.EVT_CLOSE event and do not include self.Destroy() or equivalent in the MyFrame.OnClose method. With your code, the only way to close MyFrame is to close the MainFrame because you make MyFrame a child of MainFrame.
Nevertheless, with your code, if MyFrame is minimized then I cannot see it again by pressing the button. I changed your code a little bit and now I can hide/minimize and then show/restore MyFrame. I needed to remove wx.FRAME_FLOAT_ON_PARENT for the Restore() method to properly work. Hope this helps.
import wx
class MainFrame(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, id=-1, parent=parent, size=wx.Size(600, 500),
title='Test')
self.panel = wx.Panel(self, id=-1, pos=(200, 300))
self.button = wx.Button(self.panel, id=-1, label='button',
pos=wx.Point(20, 56), size=wx.Size(87, 28))
self.button.Bind(wx.EVT_BUTTON, self.OnButton, id=-1)
self.frame = MyFrame(self)
def OnButton(self, event):
if self.frame.IsShown():
self.frame.Restore()
else:
self.frame.Show()
class MyFrame(wx.Frame):
def __init__(self, parent):
style = wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX | \
wx.MINIMIZE_BOX | wx.FRAME_NO_TASKBAR
wx.Frame.__init__(self, id=-1, parent=parent, size=wx.Size(300, 200),
title='Sub', style=style)
self.Bind(wx.EVT_CLOSE, self.OnClose)
def OnClose(self, evt):
self.Hide()
if __name__ == '__main__':
app = wx.App()
frame = MainFrame(None)
frame.Show()
app.MainLoop()
Community,
i'm a complete noob in programming but i've learned quite a lot from stackoverflow (i hope...)
my question:
i'm working with ironpython and trying to create a GUI. Currently i'm struggling to get the KeyPress Event to work. I have TextBox and if someone presses the "Enter Key" it should do something. Like starting another function.
I'm using the IDE PyCharm to code.
I appreciate your help with this question. Thanks in advance :)
Here is what i've tried so far (just an example, not the real code):
import clr
# Set references
clr.AddReference("System.Drawing")
clr.AddReference("System.Windows.Forms")
# Import Winforms
from System.Drawing import *
from System.Windows.Forms import *
class MyClass(Form):
def __init__(self):
self.Text = "MyGui"
self.Size = Size(500, 500)
self.CenterToScreen()
self.create_textbox()
def create_textbox(self):
mytxtbox = TextBox()
mytxtbox.Name = "Textbox1"
mytxtbox.Location = Point(50, 50)
mytxtbox.Size = Size(100, 25)
mytxtbox.KeyPress += KeyPressEventHandler(self.press)
def press(self, sender, args):
key = args.KeyChar
if key == Keys.Enter:
print("You pressed Enter in the TextBox")
# Run this thang
form1 = MyClass()
Application.Run(form1)
You want to use KeyDown to get Enter key, instead of KeyPress:
mytxtbox.KeyDown += on_enter
def on_enter(self, e, args):
key = e.KeyChar
if key == Keys.Enter:
print("You pressed Enter in the TextBox")
I am trying to center a CheckBox widget vertically inside a panel. I cannot figure out why it's aligned to the top.
I had to create a Panel for the CheckBox because without that the background looks ugly (Windows 10 -- see second image)
Thanks for suggestions!
class wxUIE(wx.Frame):
def __init__(self, parent, title):
wx.Frame.__init__(self, parent, size=(800, 400), title=title)
self.editorText = wx.TextCtrl (self, style=wx.TE_MULTILINE+wx.SUNKEN_BORDER+wx.TE_BESTWRAP)
self.myBar = wx.TextCtrl (self, -1)
# Checkbox
self.myCheckBoxPanel = wx.Panel(self, size=(-1, 25))
self.myCheckBox = wx.CheckBox(self.myCheckBoxPanel, label="Highlight", style=wx.ALIGN_CENTER_VERTICAL)
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer2 = wx.BoxSizer(wx.HORIZONTAL)
self.sizer.Add(self.editorText, 1, wx.EXPAND)
self.sizer.Add(self.sizer2, 0, wx.EXPAND)
self.sizer2.Add(self.myBar, 10, wx.EXPAND)
self.sizer2.Add(self.myCheckBoxPanel, 0, wx.EXPAND)
self.SetSizeHints(800,400)
self.SetSizer(self.sizer)
self.SetAutoLayout(True)
self.Show()
# Run the program
if __name__ == "__main__":
app = wx.App(False)
frame = wxUIE(None, "My Edit Control")
frame.Show()
app.MainLoop()
CheckBox aligned to top of panel
CheckBox is aligned vertically correctly but the background sucks.
I developed an IronPython-wpf application with GUI using XAML. The user enter all the inputs in the GUI and I can save them. My problem is how I could pass those variables to my main python code after USER closes the GUI? To close the GUI, I have a button, which closes the GUI, If the USER click it.
What I did is as follows (I just copied some portion of the code):
import wpf
class MyApp(Window):
def __init__(self):
self.opencfgfile()
self.ictemp = self.FindName('pipent')
self.ictemp.Text = self.ictest
self.button = self.FindName('button')
self.button.Click += self.onClick
def onClick(self, sender, event):
self.Close()
def opencfgfile(self):
sstest = os.environ['test']
infile = open (sstest + '\config\test_Config.cfg' , 'r')
for line in infile:
if line != "\n":
line = line[:-1]
fields = line.split('=')
if fields[0] == 'Initial test ID ':
self.ictest = fields[1].lstrip()
def getsetname(self):
try:
return self.ictemp
except AttributeError:
return
if __name__ == "__main__":
c = MyApp()
Application().Run(c)
iset = c.getsetname()
In my class, if I put a break point, self.ictest has a value of 'test' and self.ictemp has a value of {System.Windows.Controls.TextBox:test}, however if I put the break point in my main program for iset, I will get this Value: 'The name iset does not exist in the current context. I really appreciate if you can help me on this issue.
Your problem is, that the code iset = c.getsetname() will only be reached, after the main window is closed. The reason for this is, that Application().Run() contains your "application main loop", which will run until the main window is closed. So in your case, you should implement all interaction logic in MyApp, not in the application entry point. Everything under if __name__ == "__main__" should only be used for initializing some modules or similar things.
If you want to encapsulate some logic, put it in own modules and call it from MyApp. For example if you want to react on some button click, just do this:
# Short
def __init__(self, ...):
# Init component
self.yourButton.Click += self.OnButtonClick
def OnButtonClick(self, sender, args):
MessageBox.Show("Clicked on some button!") # Import Message box before :)
Hope this helps.
EDIT
This is working pretty well:
import wpf
from System.Windows import Window, Application
from System.Windows.Controls import TextBox
class MyApp(Window):
box = None
def __init__(self):
self.Width = 200
self.Height = 200
self.box = TextBox()
self.box.Height = 24
self.box.Width = 150
self.Content = self.box
def getBoxContent(self):
return self.box.Text
if __name__ == "__main__":
c = MyApp()
Application().Run(c)
print (c.getBoxContent())
Info passing
If you want to pass info to and from the ui, just create some class which hold the information. This will be the best solution:
import wpf
from System.Windows import Window, Application
from System.Windows.Controls import TextBox
class Information:
InformationOne = 1
InformationTwo = "Hello World"
class MyApp(Window):
box = None
information = None
def __init__(self, info):
self.information = info
self.Width = 200
self.Height = 200
self.box = TextBox()
self.box.Height = 24
self.box.Width = 150
# Init information
self.box.Text = self.information.InformationTwo
self.Content = self.box
# Information property
#property
def Information(self):
self.information.InformationTwo = self.box.Text
return self.information
if __name__ == "__main__":
info = Information()
c = MyApp(info)
Application().Run(c)
# Get information
print (c.Information.InformationTwo)