2010-08-18 3 views
3

저는 pycairo를 사용하기 시작했습니다. 다음 흥미로운 오류가 발생했습니다. 필자가 작성한 프로그램은 간단한 gtk 창을 만들고 사각형에 그려 넣은 다음 모든 종류의 키보드 입력에 임의의 줄을 그리는 콜백을 갖고 있습니다. 그러나 각 키보드 입력에서 새로운 컨텍스트를 만들어야하거나, 프로그램이 첫 번째 키보드 입력 (특히 .stroke() 행)을 수신하는 순간 오류가 발생하는 것으로 보입니다. 오류가있는 경우 다음과 같습니다. 'BadDrawable (Pixmap 또는 Window 매개 변수가 잘못되었습니다)'. (세부 정보 : 시리얼 230 오류 코드 9 요청 코드 53 마이너 코드 0)카이로 문맥과 지속성?

#! /usr/bin/env python 
import pygtk 
pygtk.require('2.0') 
import gtk, gobject, cairo, math, random 
# Create a GTK+ widget on which we will draw using Cairo 
class Screen(gtk.DrawingArea): 
# Draw in response to an expose-event 
    __gsignals__ = { "expose-event": "override" } 

    # Handle the expose-event by drawing 
    def do_expose_event(self, event): 
    # Create the cairo context 
    self.cr = self.window.cairo_create() 
    # Restrict Cairo to the exposed area; avoid extra work 
    self.cr.rectangle(event.area.x, event.area.y, event.area.width, event.area.height) 
    self.cr.clip() 

    self.draw(*self.window.get_size()) 

    def key_press_event(self, *args): 
    # print args 
    self.cr = self.window.cairo_create() # This is the line I have to add 
    # in order to make this function not throw the error. Note that cr is only 
    # given as attribute of self in order to stop it going out of scope when this line 
    # doesn't exist 
    self.cr.set_source_rgb(random.random(), random.random(), random.random()) 
    self.cr.move_to(*[z/2.0 for z in self.window.get_size()]) 
    self.cr.line_to(*[z*random.random() for z in self.window.get_size()]) 
    self.cr.stroke() 

    def draw(self, width, height): 
    # Fill the background with gray 
    self.cr.set_source_rgb(.5,.5,.5) 
    self.cr.rectangle(0, 0, width,height) 
    self.cr.fill() 

    self.cr.set_source_rgb(1,0,0) 
    self.cr.arc(width/2.0, height/2.0, min(width,height)/2.0 - 20.0, 0.0, 2.0*math.pi) 
    self.cr.stroke() 

#create a gtk window, attach to exit button, and whatever is passed as arg becomes the body of the window. AWESOME 
def run(Widget): 
    window = gtk.Window() 
    widget = Widget() 
    window.connect("delete-event", gtk.main_quit) 
    window.connect('key-press-event',widget.key_press_event) 
    widget.show() 
    window.add(widget) 
    window.present() 
    gtk.main() 

if __name__ == "__main__": 
    run(Screen) 

당신의 도움에 감사드립니다!

(업데이트 : 나는 주위를 연주했다, 나는 깨달았다 다음 : 나는 창 크기를 조정할 때, 추가 된 모든 새로운 객체가 더 이상로 삭제 (또는 적어도 표시되지 않습니다)?)

+1

http://wiki.github.com/tbaugis/hamster_experiments/에 관심이있을 수 있습니다. 카이로 위에서 매우 유용한 추상화를 제공합니다. 전체 라이브러리를 사용하지 않더라도 포함 된 트위터는 확실히 볼만한 가치가 있습니다. –

답변

2

카이로 도면 전혀 존속하지 마십시오. (그것들을 "객체"라고 생각하지 않는 것이 가장 좋습니다. 드로잉을 한 후에 캔버스 라이브러리를 옮기거나 변형 할 수있는 캔버스 라이브러리와는 다릅니다.) 노출 핸들러에서 모든 드로잉을 수행해야합니다. 당신이 알았 듯이, 창이 다시 그려 질 때마다 사라질 것입니다.

이중 버퍼링으로 인해 cairo 컨텍스트가 지속되지 않습니다. note in the C documentation을 참조하십시오. 불행히도 PyGTK 문서에서 아무 것도 찾을 수 없었습니다.

위의 코드에서 keypress 핸들러에서 무작위 라인의 좌표와 색상을 생성하고 배열에 저장해야합니다. 그런 다음 노출 핸들러에서 배열의 각 행을 순서대로 그립니다.

+0

문제를 자고 나면, 그것이 아마 캔버스 아이디어와 비슷한 것이라고 깨달았습니다. 카이로가 작동하는 방식에 대해 공백을 메꾸어 주셔서 감사합니다. 나는 캔버스의 은유를 진지하게 받아들이지 않을 것이라고 생각한다. –

0

많은 맛을 논의하기 : 일부 표면이 유지되지 않습니다

도면 : GUI 표면

여기에 그냥 않는 햄스터 그래픽 라이브러리를 사용하는 예입니다. 노출 콜백에서 다시 그려야합니다.

PyCairo 개체 (C. 상기 카이로 라이브러리 함수 만의 인터페이스로서, 영구 객체로 스트로크 이상 지속되지 않는 카이로 컨텍스트

내용 (경로 채운다)로 처리되어서는 안된다) 또는 fill() 작업.

GUI 표면의 컨텍스트가 노출 이벤트 사이에 지속되지 않습니다 (이중 버퍼링으로 인해?) (컨텍스트가 다른 표면, 즉 장치에 지속되는지는 모르겠습니다.) 따라서 카이로 컨텍스트를 사용할 수 없습니다 뷰포트의 속성 (문서상의 윈도우, 즉 사용자 좌표의 모델)을 저장합니다.

시각적 지속성은 정지 한 후에 사람의 눈이 빛을 보는 경향입니다. 유령과 깜박임은 애니메이션이나 비디오에서 나타나는 증상입니다. 이중 버퍼링을 비활성화하면 노출 된 이벤트 (즉, 시각적 지속성의 증상 시뮬레이션) 내에서 애니메이션을 사용할 수있게됩니다. 이중 버퍼링을 사용하지 않으면 GUI 화면의 컨텍스트가 노출 이벤트간에 지속되지 않습니다.

기억의 지속성은 진정한 끈기 또는 내가 초현실적이라고 말해야합니다.