3

私はpycairoを使い始めたばかりで、次の興味深いエラーに遭遇しました。私が書いたプログラムは、単純な gtk ウィンドウを作成し、その上に四角形を描画し、任意の種類のキーボード入力でランダムな線を描画するコールバックを持っています。ただし、キーボード入力ごとに新しいコンテキストを作成する必要があるようです。そうしないと、プログラムが最初のキーボード入力を受け取った時点で (具体的には .stroke() 行で) エラーが発生します。問題がある場合、エラーは次のとおりです。「BadDrawable (無効な Pixmap または Window パラメーター)」。(詳細: serial 230 error_code 9 request_code 53 minor_code 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)

ご協力いただきありがとうございます!

(更新: 遊んでいて、次のことに気付きました: ウィンドウのサイズを変更すると、追加されたすべての新しいオブジェクトが削除されます (または、少なくとも表示されなくなりますか?) )

4

3 に答える 3

2

カイロの描画はまったく保持されません。(オブジェクトを「オブジェクト」と考えないことをお勧めします。これは、描画後にオブジェクトを移動したり変形したりできるキャンバス ライブラリとは異なります。) すべての描画を公開ハンドラーで行う必要があります。お気づきのように、ウィンドウが再描画されるたびに消えます。

ダブル バッファリングのため、cairo コンテキストは持続しません。残念ながら PyGTK ドキュメントのどこにも見つかりませんでした

上記のコードでは、keypress ハンドラーでランダム ラインの座標と色を生成し、それらを配列に保存する必要があります。次に、エクスポーズ ハンドラーで、配列内の各行を順番に描画します。

于 2010-08-19T07:46:45.297 に答える
1

実行ごとにコンテキストを作成する必要がありますが、ウィジェットのダブルバッファリングを無効にすることで、探している永続性を実現できます。

ハムスター グラフィックス ライブラリを使用した例を次に示します。

https://github.com/projecthamster/experiments/blob/master/many_lines.py

于 2010-09-25T21:18:05.840 に答える
0

議論すべき持続性の多くのフレーバー:

一部のサーフェスでの描画が保持されない: GUI サーフェス。公開コールバックでそれらを再描画する必要があります。

PyCairo オブジェクトは永続オブジェクトとして扱われるべきではなく、C の Cairo ライブラリの関数へのインターフェースとしてのみ扱われるべきです。

Cairo コンテキストのコンテンツ (パスと塗りつぶし) は、 stroke() または fill() 操作を超えて保持されません。

GUI サーフェスのコンテキストは、公開イベント間で保持されません (ダブル バッファリングが原因ですか?) (コンテキストが他のサーフェス、つまりデバイスで保持されるかどうかはわかりません)。そのため、cairo コンテキストを使用して属性を保存することはできません。ビューポート (ドキュメント上のウィンドウ、つまりユーザー座標のモデル)

視覚的持続性とは、人間の目が、光が止まった後に光を見る傾向です。ゴーストやちらつきは、アニメーションやビデオでの症状です。ダブル バッファリングを無効にすると、描画されているものを見ることができます。つまり、1 つの公開イベント内でアニメーションを有効にできます (視覚的な永続性の症状のシミュレーション)。

記憶の永続性こそが本当の永続性であり、シュールとでも言うべきか。

于 2010-10-01T14:56:51.087 に答える