11、控件背景图片

Par @Martin dans le
Tags :

在我以前学习 Qt 的系列笔记 13、资源文件及Action 中提到过:

Qt 资源系统是一个跨平台的资源机制, 用于将程序运行时所需要的资源以二进制的形式存储于可执行文件内部. 如果你的程序需要加载特定的资源 (图标、文本翻译等), 那么, 将其放置在资源文件中, 就再也不需要担心这些文件的丢失. 也就是说, 如果你将资源以资源文件形式存储, 它是会编译到可执行文件内部.

在 Pyqt 中也是一样的, 我们要想在窗体上显示张图片, 就要先把它变成 Qt 的资源文件.

添加资源文件

打开 eric 后, 切换到下图中序号 1 的标签, 在下方空白处右键, 选择 “新建资源”, 新建一个以 qrc 结尾的文件, 我这里就叫 first_window.qrc 了.

接下来, 进入 Qt 设计师程序, 在资源浏览器组件点击 “编辑资源” (那个小笔图标)

然后找到我们刚才新建的 first_window.qrc 并新建一个前缀 (什么是前缀, 我们先不关心, 就把它类比成 Linux 的文件系统好了), 这里我们新建一个 ico 前缀, 最后把一张图片添加到该前缀下.

至此, Qt 资源图片添加完毕.

使用样式表

Label 就是一个普通的控件, 但我们可以通过改变它的样式表用来显示背景图片.

右键选择 “改变样式表” -> “添加资源”, 选择我们刚才添加的资源图片.

这里有三种图片样式:

  • background-image, 按图片的原尺寸来显示
  • border-image, 拉伸图片以适应控件大小, 说白了就是平铺
  • image, 也会拉伸图片以适应控件大小, 但不改变原图片的比例

确定后就能看到效果了…

最后回到 eric, 编译资源, 并重新编译窗体, 再运行程序就能看到修改后的窗口了.

注意, 编译资源后, 会多出一个 资源文件名_rc.py 的文件.

你也可以直接通过在代码中改变控件的样式表: self.label.setStyleSheet(_fromUtf8("border-image: url(:/jpg/图标.jpg);")).

很显然, 这种方式需要我们知道图片的路径, 即 :/jpg/图标.jpg, 我们可以在 Qt 设置师的资源面板上直接得到图片路径:

定义事件

现在我们想要为 Label 添加个功能, 即点击这图片弹出个对话框.

OK, 现在我们期望在 eric 中对 ui 文件生成 coe 时找到 Label 的鼠标点击信号, 然而遗憾的是 Label 并没有这个信号…这时就需要运用我大 Qt 的事件机制了…

关于事件, 参考我之前学 Qt 时的系列笔记:
18、Qt 中的事件
19、事件小结及自定义事件

按照这两篇参考文章, 我们可以先从 Label 继承一个我们自己的 Label, 并且重写我们自己的 Label 的 mousePressEvent(), 最后在 Qt 设计师上让 Label 控件从我们自己的 Label 上创建.

这当然是可以的, 但是也比较麻烦, 在 PyQt 中我们可以在 Dialog Code 的初始化方法中让 Label 的 mousePressEvent() 直接指向我们自己的方法, 就像下面这样:

class Dialog(QDialog, Ui_Dialog):
    """
    Class documentation goes here.
    """
    def __init__(self, parent=None):
        """
        Constructor

        @param parent reference to the parent widget
        @type QWidget
        """
        QDialog.__init__(self, parent)
        self.setupUi(self)
        self.label.mousePressEvent = self.handle_press

    def handle_press(self,  event):
        print 'clicked'


关键就是这行代码 self.label.mousePressEvent = self.handle_press, 这在 PyQt 中是初始允许的, 不知道在 C++ 是不是也可以这样, 没有测试过…