文档章节

PyQt5教程(十)——自定义控件

pseudo
 pseudo
发布于 2016/02/16 16:08
字数 1016
阅读 1186
收藏 5

原文:http://zetcode.com/gui/pyqt5/customwidgets/

PyQt5包含种类丰富的控件。但能满足所有需求的控件库是不存在的。通常控件库只提供了像按钮、文本控件、滑块等最常用的控件。但如果需要某种特殊的控件,我们只能自己动手来实现。 自定义控件需要使用工具库提供的绘图工具,可能有两种方式:在已有的控件上进行拓展或从头开始创建自定义控件。

Burning widget(烧录控件)

这个控件可能会在Nero,K3B或其他CD/DVD烧录软件中见到。

#!/usr/bin/python3
# -*- coding: utf-8 -*-

"""
ZetCode PyQt5 tutorial 

In this example, we create a custom widget.

author: Jan Bodnar
website: zetcode.com 
last edited: January 2015
"""

import sys
from PyQt5.QtWidgets import (QWidget, QSlider, QApplication, 
    QHBoxLayout, QVBoxLayout)
from PyQt5.QtCore import QObject, Qt, pyqtSignal
from PyQt5.QtGui import QPainter, QFont, QColor, QPen


class Communicate(QObject):
    
    updateBW = pyqtSignal(int)


class BurningWidget(QWidget):
  
    def __init__(self):      
        super().__init__()
        
        self.initUI()
        
        
    def initUI(self):
        
        self.setMinimumSize(1, 30)
        self.value = 75
        self.num = [75, 150, 225, 300, 375, 450, 525, 600, 675]


    def setValue(self, value):

        self.value = value


    def paintEvent(self, e):
      
        qp = QPainter()
        qp.begin(self)
        self.drawWidget(qp)
        qp.end()
      
      
    def drawWidget(self, qp):
      
        font = QFont('Serif', 7, QFont.Light)
        qp.setFont(font)

        size = self.size()
        w = size.width()
        h = size.height()

        step = int(round(w / 10.0))


        till = int(((w / 750.0) * self.value))
        full = int(((w / 750.0) * 700))

        if self.value >= 700:
            
            qp.setPen(QColor(255, 255, 255))
            qp.setBrush(QColor(255, 255, 184))
            qp.drawRect(0, 0, full, h)
            qp.setPen(QColor(255, 175, 175))
            qp.setBrush(QColor(255, 175, 175))
            qp.drawRect(full, 0, till-full, h)
            
        else:
            
            qp.setPen(QColor(255, 255, 255))
            qp.setBrush(QColor(255, 255, 184))
            qp.drawRect(0, 0, till, h)


        pen = QPen(QColor(20, 20, 20), 1, 
            Qt.SolidLine)
            
        qp.setPen(pen)
        qp.setBrush(Qt.NoBrush)
        qp.drawRect(0, 0, w-1, h-1)

        j = 0

        for i in range(step, 10*step, step):
          
            qp.drawLine(i, 0, i, 5)
            metrics = qp.fontMetrics()
            fw = metrics.width(str(self.num[j]))
            qp.drawText(i-fw/2, h/2, str(self.num[j]))
            j = j + 1
            

class Example(QWidget):
    
    def __init__(self):
        super().__init__()
        
        self.initUI()
        
        
    def initUI(self):      

        sld = QSlider(Qt.Horizontal, self)
        sld.setFocusPolicy(Qt.NoFocus)
        sld.setRange(1, 750)
        sld.setValue(75)
        sld.setGeometry(30, 40, 150, 30)

        self.c = Communicate()        
        self.wid = BurningWidget()
        self.c.updateBW[int].connect(self.wid.setValue)

        sld.valueChanged[int].connect(self.changeValue)
        hbox = QHBoxLayout()
        hbox.addWidget(self.wid)
        vbox = QVBoxLayout()
        vbox.addStretch(1)
        vbox.addLayout(hbox)
        self.setLayout(vbox)
        
        self.setGeometry(300, 300, 390, 210)
        self.setWindowTitle('Burning widget')
        self.show()
        
        
    def changeValue(self, value):
             
        self.c.updateBW.emit(value)        
        self.wid.repaint()
        
        
if __name__ == '__main__':
    
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

在示例中我们使用了滑块与一个自定义控件。自定义控件受滑块控制。控件显示了媒体介质的容量和剩余空间。该控件的最小值为1,最大值为750。在值超过700时颜色变为红色。这通常意味着超刻(即实际写入光盘的容量超过刻录盘片官方标称容量的一种操作)。

BurningWidget控件通过QHBoxLayout与QVBoxLayout置于窗体的底部。

class BurningWidget(QWidget):
  
    def __init__(self):      
        super().__init__()   

BurningWidget控件拓展自QWidget控件。

self.setMinimumSize(1, 30)

我们修改了它的最小尺寸(高)。默认的最小尺寸对我们来说有点小。

font = QFont('Serif', 7, QFont.Light)
qp.setFont(font)

我们使用了一种更小的字体,它比较适于我们的需求。

size = self.size()
w = size.width()
h = size.height()

step = int(round(w / 10.0))


till = int(((w / 750.0) * self.value))
full = int(((w / 750.0) * 700))

控件采用了动态绘制技术。窗体越大,控件也随之变大;反之亦然。这也是我们需要计算自定义控件的载体控件(即窗体)尺寸的原因。till参数定义了需要绘制的总尺寸,它根据slider控件计算得出,是整体区域的比例值。full参数定义了红色区域的绘制起点。注意在绘制时为取得较大精度而使用的浮点数运算。

实际的绘制分三个步骤。黄色或红黄矩形的绘制,然后是刻度线的绘制,最后是刻度值的绘制。

metrics = qp.fontMetrics()
fw = metrics.width(str(self.num[j]))
qp.drawText(i-fw/2, h/2, str(self.num[j]))

我们采用fondMetris绘制刻度值。为了使刻度值居中于刻度线,我们需要计算刻度值文本的宽度。

def changeValue(self, value):
          
    self.c.updateBW.emit(value)        
    self.wid.repaint()

当滑块发生移动时,changeValue()方法会被调用。在方法内我们触发了一个自定义的updateBW信号,其参数是当前滚动条的值。该值被用于计算Burning widget的容量值。然后对控件进行重绘。

Burning widget

在本教程中我们创建了一个自定义控件。

© 著作权归作者所有

共有 人打赏支持
上一篇: 消息摘要算法
下一篇: Java代码简化
pseudo

pseudo

粉丝 85
博文 37
码字总数 35469
作品 3
朝阳
程序员
私信 提问
PyQt5教程(六)——控件

原文:http://zetcode.com/gui/pyqt5/widgets/ 控件是应用程序的基础构件。PyQt5具有类目广泛的各种控件,包括按钮、复选框、滑动条、列表框等。在本节教程中,我们将学习几个很有用的控件:...

pseudo
2015/12/15
1K
0
PyQt5教程(七)——控件(II)

原文:http://zetcode.com/gui/pyqt5/widgets2/ 下面我们继续介绍PyQt5控件。我们将学习QPixmap, QLineEdit, QSplitter与QComboBox。 QPixmap 是一种用于处理图像的控件。它为图片的显示做过...

pseudo
2015/12/16
632
0
PyQt5教程(一)——第一个PyQt5程序

原文: http://zetcode.com/gui/pyqt5/firstprograms/ 在这部分教程中我们将学习PyQt5的一些基本功能 一个简单的例子 这是一个只显示一个小窗口的简单示例。但我们可以对这个窗口进行一些操作...

pseudo
2015/11/26
3.1K
2
PyQt5教程(二)——菜单与工具栏

原文:http://zetcode.com/gui/pyqt5/menustoolbars/ 我们将在这部分教程中创建菜单与工具栏。一个菜单就是位于菜单栏中的一组命令。应用的工具栏放置了带有按钮的常用命令。 主窗体 类提供了...

pseudo
2015/11/29
1K
0
PyQt5教程(三)——布局管理

原文:http://zetcode.com/gui/pyqt5/layout/ 布局管理是GUI编程中的重要部分。布局管理是如何将控件放置于窗体上的技术,它的实现有两种基本方式:绝对布局与layout类。 绝对布局 程序员要指...

pseudo
2015/12/01
1K
0

没有更多内容

加载失败,请刷新页面

加载更多

rabbitmq

灰暗
23分钟前
0
0
Flink

flink HA部署 flink搭建,采用分布式部署方式,分别为A,B,C三个节点。其中A为master;A,B,C为worker。 本文使用的用户是hadoop用户(自己新建) 先决条件 Java 1.8.x or higher scala 自己使用...

-九天-
50分钟前
1
0
数据中台和传统数仓的区别

中台系统把业务层同性的算法能力,服务能力,业务能力高度集成,有效组织 ,动态规划。更好的帮助上层业务。 今天就让我们看看关于数据中台的问答吧。 1 Q : 什么是数据中台? A : 数据中台是...

hblt-j
51分钟前
4
0
Java在什么时候会出现内存泄漏

在Java中,内存泄漏就是存在一些被分配的对象,这些对象有下面两个特点,首先,这些对象是可达的,即在有向图中,存在通路可以与其相连;其次,这些对象是无用的,即程序以后不会再使用这些对...

群星纪元
54分钟前
2
0
android 打开摄像头

private SurfaceHolder mHolder; private SurfaceView mSurfaceView; private Camera mCamera; mSurfaceView = (SurfaceView) this.findViewById(R.id.camsurfaceView1); mHolder = mSurface......

jingshishengxu
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部