QTを初めて使用し、カスタムペイントイベントを作成しようとすると、Windows7x64でクラッシュします。Ruby1.9.3p125とqtbindings-4.8.3.0-x86-mingw32を使用しています。このクラッシュは、私の仕事用マシン、Ruby1.9.2p180およびqtbindings-4.6.3.4を使用するRedhatLinuxでは表示されません。
「QT4を使用したC++GUIプログラミング」(Rubyに移植)のIconEditorの例に従うと、最初はこの問題に遭遇しましたが、以下の例では問題を単純化しています。
このサンプルコードは、サブクラス化されたQWidgetに単純な線を繰り返し描画するタイマーを作成します。Windowsでは、Rubyがセグメンテーション違反を出す前にpaintEventが約440回発生します。コードは次のとおりです。
#!/usr/bin/env ruby
require 'Qt'
class Painter < Qt::Widget
slots :startTimer
def initialize(parent=nil)
super(parent)
setAttribute Qt::WA_StaticContents
setSizePolicy(Qt::SizePolicy::Minimum, Qt::SizePolicy::Minimum)
@counter = 0
@timer = Qt::Timer.new(self)
connect(@timer, SIGNAL('timeout()'), self, SLOT(:startTimer))
startTimer
end
def sizeHint
Qt::Size.new(200,200)
end
def paintEvent(event)
puts "DEBUG: paintEvent #{@counter += 1} #{event.inspect}"
painter = Qt::Painter.new(self)
painter.setPen(palette.foreground.color)
painter.drawLine(0, 0, 200, 200)
end
def startTimer
@timer.start(5)
update
end
end
app = Qt::Application.new(ARGV)
painter = Painter.new
painter.show
app.exec
バックトレースは次のとおりです。
DEBUG: paintEvent 440 #<Qt::PaintEvent:0x3328938>
DEBUG: paintEvent 441 #<Qt::PaintEvent:0x3327de0>
DEBUG: paintEvent 442 #<Qt::PaintEvent:0x3327420>
DEBUG: paintEvent 443 #<Qt::PaintEvent:0x3326928>
./main.rb:27: [BUG] Segmentation fault
ruby 1.9.3p125 (2012-02-16) [i386-mingw32]
-- Control frame information -----------------------------------------------
c:0008 p:---- s:0024 b:0024 l:000023 d:000023 CFUNC :method_missing
c:0007 p:0107 s:0022 b:0022 l:000021 d:000021 METHOD ./main.rb:27
c:0006 p:---- s:0017 b:0017 l:000016 d:000016 FINISH
c:0005 p:---- s:0015 b:0015 l:000014 d:000014 CFUNC :method_missing
c:0004 p:0013 s:0011 b:0011 l:000010 d:000010 METHOD C:/Ruby193/lib/ruby/gems/1.9.1/gems/qtbindings-4.8.3.0-x86-mingw32/lib/Qt/qtruby4.rb:469
c:0003 p:0098 s:0008 b:0008 l:001aec d:0023bc EVAL ./main.rb:41
c:0002 p:---- s:0004 b:0004 l:000003 d:000003 FINISH
c:0001 p:0000 s:0002 b:0002 l:001aec d:001aec TOP
-- Ruby level backtrace information ----------------------------------------
./main.rb:41:in `<main>'
C:/Ruby193/lib/ruby/gems/1.9.1/gems/qtbindings-4.8.3.0-x86-mingw32/lib/Qt/qtruby4.rb:469:in `exec'
C:/Ruby193/lib/ruby/gems/1.9.1/gems/qtbindings-4.8.3.0-x86-mingw32/lib/Qt/qtruby4.rb:469:in `method_missing'
./main.rb:27:in `paintEvent'
./main.rb:27:in `method_missing'
-- C level backtrace information -------------------------------------------
C:\Windows\SysWOW64\ntdll.dll(ZwWaitForSingleObject+0x15) [0x77d5f8b1]
C:\Windows\syswow64\kernel32.dll(WaitForSingleObjectEx+0x43) [0x76c01194]
C:\Windows\syswow64\kernel32.dll(WaitForSingleObject+0x12) [0x76c01148]
C:\Ruby193\bin\msvcrt-ruby191.dll(rb_vm_bugreport+0xf9) [0x62e5c61d]
C:\Ruby193\bin\msvcrt-ruby191.dll(rb_name_err_mesg_new+0x17a) [0x62d3a6fa]
C:\Ruby193\bin\msvcrt-ruby191.dll(rb_bug+0x2f) [0x62d3b45b]
C:\Ruby193\bin\msvcrt-ruby191.dll(rb_check_safe_str+0x1a4) [0x62dee1a0]
[0x004011e6]
C:\Windows\syswow64\kernel32.dll(GetProfileStringW+0x12aa3) [0x76c4003f]
C:\Windows\SysWOW64\ntdll.dll(RtlKnownExceptionFilter+0xb7) [0x77db74df]
-- Other runtime information -----------------------------------------------
* Loaded script: ./main.rb
* Loaded features:
0 enumerator.so
1 C:/Ruby193/lib/ruby/1.9.1/i386-mingw32/enc/encdb.so
2 C:/Ruby193/lib/ruby/1.9.1/i386-mingw32/enc/iso_8859_1.so
3 C:/Ruby193/lib/ruby/1.9.1/i386-mingw32/enc/trans/transdb.so
4 C:/Ruby193/lib/ruby/site_ruby/1.9.1/rubygems/defaults.rb
5 C:/Ruby193/lib/ruby/1.9.1/i386-mingw32/rbconfig.rb
6 C:/Ruby193/lib/ruby/site_ruby/1.9.1/rubygems/deprecate.rb
7 C:/Ruby193/lib/ruby/site_ruby/1.9.1/rubygems/exceptions.rb
8 C:/Ruby193/lib/ruby/site_ruby/1.9.1/rubygems/defaults/operating_system.rb
9 C:/Ruby193/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb
10 C:/Ruby193/lib/ruby/site_ruby/1.9.1/rubygems.rb
11 C:/Ruby193/lib/ruby/site_ruby/1.9.1/rubygems/version.rb
12 C:/Ruby193/lib/ruby/site_ruby/1.9.1/rubygems/requirement.rb
13 C:/Ruby193/lib/ruby/site_ruby/1.9.1/rubygems/platform.rb
14 C:/Ruby193/lib/ruby/site_ruby/1.9.1/rubygems/specification.rb
15 C:/Ruby193/lib/ruby/site_ruby/1.9.1/rubygems/path_support.rb
16 C:/Ruby193/lib/ruby/gems/1.9.1/gems/qtbindings-4.8.3.0-x86-mingw32/lib/Qt/qtruby4.rb
17 C:/Ruby193/lib/ruby/gems/1.9.1/gems/qtbindings-4.8.3.0-x86-mingw32/lib/1.9/qtruby4.so
18 C:/Ruby193/lib/ruby/gems/1.9.1/gems/qtbindings-4.8.3.0-x86-mingw32/lib/Qt4.rb
19 C:/Ruby193/lib/ruby/gems/1.9.1/gems/qtbindings-4.8.3.0-x86-mingw32/lib/Qt.rb
20 C:/Ruby193/lib/ruby/1.9.1/i386-mingw32/enc/utf_16le.so
21 C:/Ruby193/lib/ruby/1.9.1/i386-mingw32/enc/trans/single_byte.so
22 C:/Ruby193/lib/ruby/1.9.1/i386-mingw32/enc/trans/utf_16_32.so
編集:: あなた自身の質問に答えるようなものはありません...
paintEventクラスには、「painter.end」ステートメントを含める必要があります。これに関するドキュメントは見つかりませんが、qtbindingsに含まれている例に含まれているため、見逃してしまいました。間違いなく、これはQPainterオブジェクトデストラクタを呼び出して、メモリリークによるプログラムのクラッシュを防ぎます。
修正されたコードは次のとおりです。
def paintEvent(event)
puts "DEBUG: paintEvent #{@counter += 1} #{event.inspect}"
painter = Qt::Painter.new(self)
painter.setPen(palette.foreground.color)
painter.drawLine(0, 0, 200, 200)
painter.end
end