我是 QT 新手,在尝试创建自定义绘制事件时在 Windows 7 x64 上发生崩溃。我正在使用 Ruby 1.9.3p125 和 qtbindings-4.8.3.0-x86-mingw32。在我的工作机器 Redhat Linux 上使用 Ruby 1.9.2p180 和 qtbindings-4.6.3.4 时不会出现此崩溃
我最初在遵循“C++ Gui Programming with QT 4”(移植到 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