Please support our Python advertiser: Programming Forums
Views: 1593 | Replies: 8
![]() |
•
•
Join Date: Mar 2006
Posts: 56
Reputation:
Rep Power: 3
Solved Threads: 0
Hi, it's me again and i have new question:
This is my code:
if i write in entry for example 4,5,4,40 than will becreated line at this coordinates. But if i press button Show, the line is showed, but i get some error. Do you can tell me please what i am doing bad?
This is my code:
# -*- coding: cp1250 -*-
import string as _string
import time as _time
import wx
from math import*
class Canvas:
def __init__(self,parent):
self.okno=parent
self.okno.SetBackgroundColour("#FCFCFE")
self.radic = wx.FlexGridSizer(2,2,0,0)
self.canvas = wx.ScrolledWindow(self.okno, -1)
self.canvas.EnableScrolling(True, True)
self.P_WIDTH = 1000
self.P_HEIGHT = 1000
self.canvas.SetScrollbars(20, 20, self.P_WIDTH/20, self.P_HEIGHT/20)
self.radic.Add(self.canvas, 1, wx.EXPAND)
self.radic.Add((0,0))
sizer=wx.BoxSizer(wx.VERTICAL)
self.radic.Add(sizer, 1, wx.EXPAND)
self.radic.Add((0,0))
self.radic.AddGrowableRow(0, 1)
self.radic.AddGrowableCol(0, 1)
sizer2=wx.BoxSizer(wx.HORIZONTAL)
sizer2.Add(wx.StaticText(self.okno,label=" f(y)= "),0,wx.ALIGN_CENTER)
self.vstup=wx.TextCtrl(self.okno)
sizer2.Add(self.vstup,1,0,wx.ALL)
sizer.Add(sizer2,0,wx.EXPAND)
sizer3=wx.BoxSizer(wx.HORIZONTAL)
button1=wx.Button(self.okno,label="Show")
sizer3.Add(button1,0,wx.ALIGN_RIGHT)
sizer.Add(sizer3,0,wx.EXPAND)
##
self.canvas.SetCursor(wx.CROSS_CURSOR)
self.canvas.Bind(wx.EVT_PAINT, self.OnPaint)
self.okno.SetSizer(self.radic)
button1.Bind(wx.EVT_BUTTON,lambda e:self.vykresli())
self.body=[(0,0,0,0)]
self.pocet=0
self.dc=False
def vykresli(self):
l=[]
for prvek in self.vstup.GetValue().split(','):
l.append(int(prvek))
self.body=l
self.dc.BeginDrawing()
self.dc.DrawLineList([l])
self.dc.EndDrawing()
def OnPaint(self, evt):
self.dc=wx.PaintDC(self.canvas)
self.dc.BeginDrawing()
self.dc.DrawLineList(self.body)
self.dc.EndDrawing()
if __name__ == "__main__":
okno = wx.App(0)
parent=wx.MDIParentFrame(None,size=wx.Size(500,500))
child=wx.MDIChildFrame(parent,title="Graf",id=-1)
Canvas(child)
child.Maximize()
parent.Show()
okno.MainLoop()if i write in entry for example 4,5,4,40 than will becreated line at this coordinates. But if i press button Show, the line is showed, but i get some error. Do you can tell me please what i am doing bad?
•
•
Join Date: Mar 2006
Posts: 56
Reputation:
Rep Power: 3
Solved Threads: 0
Well, try to write in entry coordinates "4,4,40,40" and press Show. There will create onle line, but i will get error:
TypeError: Expected a sequence of (x1,y1, x1,y2) sequences.
Traceback (most recent call last):
File "C:\Documents and Settings\Blu\Plocha\MaRoWx\graf_zkouska.py", line 140,
in OnPaint
self.dc.DrawLineList(self.body)
File "C:\Python24\lib\site-packages\wx-2.6-msw-unicode\wx\_gdi.py", line 4100,
in DrawLineList
return self._DrawLineList(lines, pens, [])
File "C:\Python24\lib\site-packages\wx-2.6-msw-unicode\wx\_gdi.py", line 4042,
in _DrawLineList
return _gdi_.DC__DrawLineList(*args, **kwargs)•
•
Join Date: Jul 2006
Posts: 562
Reputation:
Rep Power: 4
Solved Threads: 72
OK, buddy, you owe me one
Just kidding; I'm learning wxPython, and it was helpful to work through the code.
Comments about your code:
(1) The reason it crashed and printed multiple error messages, I *think*, was that you were passing non-tuples to DrawLines.
And, if you are using IDLE and get an error while working with wxPython -- you may not get your system back. The error messages just kept scrolling down the screen, and I had to restart twice.
(2) In general, the code had a lot of unneeded stuff. BeginDrawing() and EndDrawing() are listed in the docs as doing nothing and are deprecated. The two separate paint methods (vykresli, OnPaint) were muddling the picture. I wasn't able to find a use for the Add((0,0)) calls.
(3) I recommend having all of your widgets be members of the parent class. That way, you can refer to them as needed in the code. See below for examples.
(4) jste cech?
Anyways, here's a working version:
Hope it helps,
Jeff
Just kidding; I'm learning wxPython, and it was helpful to work through the code.Comments about your code:
(1) The reason it crashed and printed multiple error messages, I *think*, was that you were passing non-tuples to DrawLines.
And, if you are using IDLE and get an error while working with wxPython -- you may not get your system back. The error messages just kept scrolling down the screen, and I had to restart twice.

(2) In general, the code had a lot of unneeded stuff. BeginDrawing() and EndDrawing() are listed in the docs as doing nothing and are deprecated. The two separate paint methods (vykresli, OnPaint) were muddling the picture. I wasn't able to find a use for the Add((0,0)) calls.
(3) I recommend having all of your widgets be members of the parent class. That way, you can refer to them as needed in the code. See below for examples.
(4) jste cech?
Anyways, here's a working version:
Python Syntax (Toggle Plain Text)
import wx class MyFrame(wx.Frame): PENS = ['blue','red','green','black','purple'] def __init__(self,parent=None,id=wx.ID_ANY,title="Line Drawer"): wx.Frame.__init__(self, parent, id, title) self.sizer = wx.FlexGridSizer(2,2,0,0) # Add canvas self.canvas = wx.ScrolledWindow(self, id=wx.ID_ANY) self.canvas.EnableScrolling(True, True) self.P_WIDTH = 1000 self.P_HEIGHT = 1000 self.canvas.SetScrollbars(20, 20, self.P_WIDTH/20, self.P_HEIGHT/20) self.sizer.Add(self.canvas, 1, wx.EXPAND) # Pad spacing to sizer self.pad_sizer=wx.BoxSizer(wx.VERTICAL) self.sizer.Add(self.pad_sizer, 1, wx.EXPAND) self.sizer.AddGrowableRow(0, 1) self.sizer.AddGrowableCol(0, 1) # Add text entry self.text_sizer=wx.BoxSizer(wx.HORIZONTAL) self.text_sizer.Add(wx.StaticText(self,label=" f(y)= "),0,wx.ALIGN_CENTER) self.entry=wx.TextCtrl(self,style=wx.TE_PROCESS_ENTER) self.text_sizer.Add(self.entry,1,0,wx.ALL) self.sizer.Add(self.text_sizer,0,wx.EXPAND) # Add button self.button_sizer = wx.BoxSizer(wx.HORIZONTAL) self.button1=wx.Button(self,label="Show") self.button_sizer.Add(self.button1,0,wx.ALIGN_RIGHT) self.sizer.Add(self.button_sizer,0,wx.EXPAND) self.SetSizer(self.sizer) # housekeeping self.lines = [] self.button1.Bind(wx.EVT_BUTTON,self.OnClick,self.button1) #self.entry.Bind(wx.EVT_COMMAND_ENTER,self.OnClick,self.entry) # <--- This doesn't work correctly. TO-DO: make TextCtrl respond to <Enter>. self.canvas.Bind(wx.EVT_PAINT, self.OnPaint) def OnPaint(self, event): dc = wx.PaintDC(self.canvas) # This does different colors. for line_no in range(len(self.lines)): dc.SetPen(wx.Pen(self.PENS[line_no % len(self.PENS)],1)) dc.DrawLine(*self.lines[line_no]) # If you want all one color, use this instead: # dc.SetPen('black',1) # for line in self.lines: # dc.DrawLine(*line) def OnClick(self, event=None): text = self.entry.GetValue() coords = text.split(',') try: x0,y0,x1,y1 = [int(x) for x in coords] except: return else: self.lines.append((x0,y0,x1,y1)) self.canvas.Refresh() # <-- The key to getting the drawing to work. if __name__ == "__main__": app = wx.PySimpleApp() # <-- much easier than MDIParentFrame... app.frame = MyFrame() app.frame.Show() app.MainLoop()
Hope it helps,
Jeff
•
•
Join Date: Mar 2006
Posts: 56
Reputation:
Rep Power: 3
Solved Threads: 0
omg, i found another problem. If i sroll canvas, is called functin OnPaint and all objects are redraw. If you have there 2 lines, its no problem, but if you have there around milion lines, each redraw takes several seconds......
For exapmle, same program in Tkinter is faster. I thought, that wx is waster then Tkinter, so i think there is some way to draw lines a scroll it without redrawing. Do you know how to solve it?
Thanks a lot...
For exapmle, same program in Tkinter is faster. I thought, that wx is waster then Tkinter, so i think there is some way to draw lines a scroll it without redrawing. Do you know how to solve it?
Thanks a lot...
•
•
Join Date: Jul 2006
Posts: 562
Reputation:
Rep Power: 4
Solved Threads: 72
I know generally how to solve it, but not specifically in wxPython (yet).
Basically, the OnPaint needs to distinguish between dirty and not-dirty: if you've drawn new lines since the last OnPaint, the canvas is dirty and has to be redrawn. If not, then you just need to blit the right area of the canvas onto the display screen.
That's the basic idea, but I'm not sure how to implement it specifically in wxPython. Let us know when you find out!
Jeff
Basically, the OnPaint needs to distinguish between dirty and not-dirty: if you've drawn new lines since the last OnPaint, the canvas is dirty and has to be redrawn. If not, then you just need to blit the right area of the canvas onto the display screen.
That's the basic idea, but I'm not sure how to implement it specifically in wxPython. Let us know when you find out!
Jeff
![]() |
•
•
•
•
Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)






Linear Mode