跳转至

Ruby Qt 中的自定义小部件

原文: http://zetcode.com/gui/rubyqt/customwidget/

在 Ruby Qt 编程教程的这一部分中,我们将创建一个自定义窗口小部件。

工具箱通常仅提供最常见的窗口小部件,例如按钮,文本窗口小部件,滑块等。没有工具箱可以提供所有可能的窗口小部件。 程序员必须自己创建此类小部件。 他们使用工具箱提供的绘图工具来完成此任务。 有两种可能性。 程序员可以修改或增强现有的小部件。 或者,他可以从头开始创建自定义窗口小部件。

刻录小部件

在下一个示例中,我们将创建一个自定义刻录小部件。 可以在 Nero 或 K3B 之类的应用中看到此小部件。 该小部件将从头开始创建。

#!/usr/bin/ruby

# ZetCode Ruby Qt tutorial

# In this program, we create
# a custom widget
#
# @author jan bodnar
# website zetcode.com
# last modified July 2009

require 'Qt'

PANEL_HEIGHT = 30
DISTANCE = 19
LINE_WIDTH = 5
DIVISIONS = 10
FULL_CAPACITY = 700
MAX_CAPACITY = 750

class Burning < Qt::Widget 

    def initialize(parent) 
        super(parent)

        @num = [ "75", "150", "225", "300", 
            "375", "450", "525", "600", "675" ]

        @redColor = Qt::Color.new 255, 175, 175
        @yellowColor = Qt::Color.new 255, 255, 184

        @parent = parent
        setMinimumHeight PANEL_HEIGHT
    end

    def paintEvent event

        painter = Qt::Painter.new self

        drawWidget painter
        painter.end
    end

    def drawWidget painter

        w = width.to_f

        slid_width = @parent.getCurrentWidth

        step = (w / DIVISIONS).round.to_f

        till = ((w / MAX_CAPACITY) * slid_width).to_f
        full = ((w / MAX_CAPACITY) * FULL_CAPACITY).to_f

        if slid_width > FULL_CAPACITY
            painter.setPen @yellowColor
            painter.setBrush Qt::Brush.new @yellowColor
            painter.drawRect Qt::RectF.new 0, 0, full, PANEL_HEIGHT
            painter.setPen @redColor
            painter.setBrush Qt::Brush.new @redColor
            painter.drawRect Qt::RectF.new full+1, 0, till-full, PANEL_HEIGHT
        else 
            if slid_width > 0
               painter.setPen @yellowColor
               painter.setBrush Qt::Brush.new @yellowColor
               painter.drawRect Qt::RectF.new 0, 0, till, PANEL_HEIGHT
            end
        end

        painter.setPen Qt::Color.new 90, 90, 90
        painter.setBrush Qt::NoBrush
        painter.drawRect 0, 0, w-1, PANEL_HEIGHT-1

        newFont = font
        newFont.setPointSize 7
        painter.setFont newFont

        for i in (1..@num.length)
            painter.drawLine Qt::LineF.new i*step, 1, i*step, LINE_WIDTH

            metrics = Qt::FontMetrics.new newFont

            w = metrics.width @num[i-1]
            painter.drawText(Qt::PointF.new(i*step-w/2, DISTANCE), @num[i-1])

        end
    end
end

class QtApp < Qt::Widget 

    slots 'onChanged(int)'

    def initialize
        super
        setWindowTitle "The Burning Widget"

        initUI

        resize 370, 200
        move 300, 300
        show
    end

    def initUI

       @cur_width = 0

       @slider = Qt::Slider.new Qt::Horizontal , self
       @slider.setMaximum MAX_CAPACITY
       @slider.setGeometry 50, 50, 130, 30 

       connect(@slider, SIGNAL("valueChanged(int)"), self, SLOT("onChanged(int)"))

       vbox = Qt::VBoxLayout.new self
       hbox = Qt::HBoxLayout.new

       vbox.addStretch 1

       @widget = Burning.new self
       hbox.addWidget @widget, 0

       vbox.addLayout hbox

       setLayout vbox
    end

    def onChanged val
        @cur_width = val
        @widget.repaint
    end

    def getCurrentWidth
      return @cur_width
    end
end

app = Qt::Application.new ARGV
QtApp.new
app.exec

在这个文件中,我们创建了刻录小部件。

class Burning < Qt::Widget 

自定义窗口小部件基于Widget小部件。

PANEL_HEIGHT = 30
DISTANCE = 19
LINE_WIDTH = 5
DIVISIONS = 10
FULL_CAPACITY = 700
MAX_CAPACITY = 750

这些是重要的常数。 PANEL_HEIGHT定义自定义窗口小部件的高度。 DISTANCE是比例尺上的数字与其父边框顶部之间的距离。 LINE_WIDTH是垂直线的宽度。 DIVISIONS是秤的数量。 FULL_CAPACITY是媒体的最大容量。 达到目标后,就会发生过度刻录。 这通过红色可视化。 MAX_CAPACITY是介质的最大容量。

@num = [ "75", "150", "225", "300", 
    "375", "450", "525", "600", "675" ]

我们使用这些数字来构建Burning小部件的比例。

def paintEvent event

    painter = Qt::Painter.new self

    drawWidget painter
    painter.end
end

自定义窗口小部件的图形委托给drawWidget方法。

slid_width = @parent.getCurrentWidth

我们使用它来获取当前选定的滑块值。

w = width.to_f

我们得到小部件的宽度。 自定义窗口小部件的宽度是动态的。 用户可以调整大小。

till = ((w / MAX_CAPACITY) * slid_width).to_f
full = ((w / MAX_CAPACITY) * FULL_CAPACITY).to_f

我们使用w变量进行转换。 在比例尺值和自定义小部件的度量之间。 请注意,我们使用浮点值。 我们在绘图中获得了更高的精度。

painter.setPen @redColor
painter.setBrush Qt::Brush.new @redColor
painter.drawRect Qt::RectF.new full+1, 0, till-full, PANEL_HEIGHT

这三行画出红色矩形,表示过度燃烧。

painter.drawRect 0, 0, w-1, PANEL_HEIGHT-1

这是小部件的外围,即外部矩形。

painter.drawLine Qt::LineF.new i*step, 1, i*step, LINE_WIDTH

在这里,我们画出小的垂直线。

w = metrics.width @num[i-1]
painter.drawText(Qt::PointF.new(i*step-w/2, DISTANCE), @num[i-1])

在这里,我们绘制刻度的数字。 为了精确定位数字,我们必须获得字符串的宽度。

@widget = Burning.new self
hbox.addWidget @widget, 0

我们创建Burning小部件的实例并将其添加到水平框中。

def onChanged val
    @cur_width = val
    @widget.repaint
end

当滑块的值更改时,我们将其存储在@cur_width变量中,然后重新绘制自定义窗口小部件。

def getCurrentWidth
return @cur_width
end

定制小部件调用此方法以获取实际的滑块值。

The Burning widget

图:刻录小部件

在 Ruby Qt 教程的这一部分中,我们已经演示了如何创建自定义窗口小部件。



回到顶部