3

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
4

0 に答える 0