python GUI库图形界面开发之PyQt5信号与槽事件处理机制详细介绍与实例解析


Posted in Python onMarch 08, 2020

PyQt5中信号与槽可以说是对事件处理机制的高级封装,如果说事件是用来创建窗口控件的,那么信号与槽就是用来对这个控件进行使用的,比如一个按钮,当我们使用按钮时,只关心clicked信号,至于这个按钮如何接受并处里鼠标点击事件,然后在发射这个信号,则不关心,但是如果要重载一个按钮,这时候就要关心了,比如可以改变它的行为:在鼠标按下时触发clicked信号,而不是释放时

PyQt5常见事件类型

pyqt是对Qt的封装,qt程序是事件驱动的,它的每个动作都有幕后某个事件所触发,Qt事件类型有很多,常见的如下

  • 键盘事件:按键的按下与松开
  • 鼠标事件:鼠标指针的移动,鼠标按键的按下与松开
  • 拖放事件:用鼠标进行拖放
  • 滚轮事件:鼠标滚轮滚动
  • 绘屏事件:重绘制屏幕的某些部分
  • 定时事件:定时器到时
  • 焦点事件:键盘焦点移动
  • 进入和离开事件:鼠标指针移入Widget内,或者移出
  • 移动事件:Widget的位置改变
  • 大小改变事件:widget的大小改变
  • 显示和隐藏事件:widget显示与隐藏
  • 窗口事件:窗口是否为当前窗口

还有一些常见的qt事件,比如Socket事件,剪切板事件,字体改变事件,布局改变事件

使用事件处理的方法

pyqt提供如下5中事件处理和过滤的方法(有弱到强),其中只有前两种方法使用最频繁

1 、重新实现事件函数

比如mousePressEvent(),keyPressEvent(),paintEvent(),这是最常规的事件处理方法

2 、重新实现QObject.event()

一般用在pyqt没有提供该事件的处理函数的情况下,即增加新事件时

3 、安装事件过滤器

如果对QObject调用installEventFilter,则相当于为这个QObject安装了一个事件过滤器,对于QObject的全部事件来说,它们都会先传递到事件过滤函数eventFilter中,在这个函数中,我们可以抛弃或者修改这些事件,比如对自己感兴趣的事件使用自定义的处理机制,对其他事件采用默认的事件处理机制,由于这中方法会调用installEventFilter的所有QObject的事件进行过滤,因此如果要过滤的事件比较多,则会降低程序的性能

4 、在QApplication中安装事件过滤器

这种方法比上一种更强大,QApplication的事件过滤器将捕获所有的QObject事件,而且第一个获得该事件,也就是说,在将事件发送给其他任何一个事件过滤器之前,都会发送给QApplication的事件过滤器

5 、重新实现QApplication的notify()方法

pyqt使用notify来分发事件,要想在任何事件处理器之前捕获事件,唯一的方法就是重新实现QApplication的notify(),在实践中,在调试才会用这中方法

PyQt5信号与槽事件处理经典案例

import sys
from PyQt5.QtCore import (QEvent, QTimer, Qt)
from PyQt5.QtWidgets import (QApplication, QMenu, QWidget)
from PyQt5.QtGui import QPainter
class Widget(QWidget):
  def __init__(self, parent=None):
    super(Widget, self).__init__(parent)
    #初始化数据
    #鼠标双击False
    self.justDoubleClicked = False
    #按键,输出文本,提示消息为空
    self.key = ""
    self.text = ""
    self.message = ""
    #设置窗口初始大小与位置
    self.resize(400, 300)
    self.move(100, 100)
    #设置标题
    self.setWindowTitle("Events")
    #定时器1秒后执行槽函数
    QTimer.singleShot(1000, self.giveHelp)
    # 避免窗口大小重绘事件的影响,可以把参数0改变成3000(3秒),然后在运行,就可以明白这行代码的意思。
  def giveHelp(self):
    self.text = "请点击这里触发追踪鼠标功能"
    # 重绘事件,也就是触发paintEvent函数。
    self.update()
  '''重新实现关闭事件'''
  def closeEvent(self, event):
    print("Closed")
  '''重新实现上下文菜单事件'''
  def contextMenuEvent(self, event):
    #实例化菜单,添加子菜单one two并附加快捷键功能,关联槽函数
    menu = QMenu(self)
    oneAction = menu.addAction("&One")
    twoAction = menu.addAction("&Two")
    oneAction.triggered.connect(self.one)
    twoAction.triggered.connect(self.two)
    #如果message为空,执行
    if not self.message:
      #在菜单中添加一条分割线
      menu.addSeparator()
      #添加自菜单three,关联槽函数
      threeAction = menu.addAction("Thre&e")
      threeAction.triggered.connect(self.three)
    #菜单栏出现在鼠标的位置
    menu.exec_(event.globalPos())
  '''上下文菜单槽函数'''
  def one(self):
    self.message = "Menu option One"
    self.update()
  def two(self):
    self.message = "Menu option Two"
    self.update()
  def three(self):
    self.message = "Menu option Three"
    self.update()
  '''重新实现绘制事件'''
  def paintEvent(self, event):
    text = self.text
    i = text.find("\n\n")
    if i >= 0:
      text = text[0:i]
    # 若触发了键盘按钮,则在文本信息中记录这个按钮信息。
    if self.key:
      text += "\n\n你按下了: {0}".format(self.key)
    painter = QPainter(self)
    painter.setRenderHint(QPainter.TextAntialiasing)
    # 绘制信息文本的内容
    painter.drawText(self.rect(), Qt.AlignCenter, text)
    # 若消息文本存在则在底部居中绘制消息,5秒钟后清空消息文本并重绘。
    if self.message:
      #显示给定坐标处的文本,坐标,对齐方式。文本内容
      painter.drawText(self.rect(), Qt.AlignBottom | Qt.AlignHCenter,
               self.message)
      #5秒钟后触发清空信息的函数,并重新绘制事件
      QTimer.singleShot(5000, self.clearMessage)
      QTimer.singleShot(5000, self.update)
  '''清空消息文本的槽函数'''
  def clearMessage(self):
    self.message = ""
  '''重新实现调整窗口大小事件'''
  def resizeEvent(self, event):
    self.text = "调整窗口大小为: QSize({0}, {1})".format(
      event.size().width(), event.size().height())
    self.update()
  '''重新实现鼠标释放事件'''
  def mouseReleaseEvent(self, event):
    # 若鼠标释放为双击释放,则不跟踪鼠标移动
    if self.justDoubleClicked:
      self.justDoubleClicked = False
    # 若鼠标释放为单击释放,则需要改变跟踪功能的状态,如果开启跟踪功能的话就跟踪,不开启跟踪功能就不跟踪
    else:
      # 单击鼠标
      self.setMouseTracking(not self.hasMouseTracking())
      if self.hasMouseTracking():
        self.text = "开启鼠标跟踪功能.\n" + \
              "请移动一下鼠标!\n" + \
              "单击鼠标可以关闭这个功能"
      else:
        self.text = "关闭鼠标跟踪功能.\n" + \
              "单击鼠标可以开启这个功能"
      self.update()
  '''重新实现鼠标移动事件'''
  def mouseMoveEvent(self, event):
    #如果没有鼠标双击,执行
    if not self.justDoubleClicked:
      # 窗口坐标转换为屏幕坐标
      globalPos = self.mapToGlobal(event.pos())
      self.text = """鼠标位置:
      窗口坐标为:QPoint({0}, {1}) 
      屏幕坐标为:QPoint({2}, {3}) """.format(event.pos().x(), event.pos().y(), globalPos.x(), globalPos.y())
      self.update()
  '''重新实现鼠标双击事件'''
  def mouseDoubleClickEvent(self, event):
    self.justDoubleClicked = True
    self.text = "你双击了鼠标"
    self.update()
  '''重新实现键盘按下事件'''
  def keyPressEvent(self, event):
    self.key = ""
    if event.key() == Qt.Key_Home:
      self.key = "Home"
    elif event.key() == Qt.Key_End:
      self.key = "End"
    elif event.key() == Qt.Key_PageUp:
      if event.modifiers() & Qt.ControlModifier:
        self.key = "Ctrl+PageUp"
      else:
        self.key = "PageUp"
    elif event.key() == Qt.Key_PageDown:
      if event.modifiers() & Qt.ControlModifier:
        self.key = "Ctrl+PageDown"
      else:
        self.key = "PageDown"
    elif Qt.Key_A <= event.key() <= Qt.Key_Z:
      if event.modifiers() & Qt.ShiftModifier:
        self.key = "Shift+"
      self.key += event.text()
    #如果key有字符,不为空,则绘制字符
    if self.key:
      self.key = self.key
      self.update()
    #否则就继续监视这个事件
    else:
      QWidget.keyPressEvent(self, event)
  '''重新实现其他事件,适用于PyQt没有提供该事件的处理函数的情况,Tab键由于涉及焦点切换,不会传递给keyPressEvent,因此,需要在这里重新定义。'''
  def event(self, event):
    #如果有按键按下,并且按键是tab键
    if (event.type() == QEvent.KeyPress and
          event.key() == Qt.Key_Tab):
      self.key = "在event()中捕获Tab键"
      self.update()
      return True
    return QWidget.event(self, event)
if __name__ == "__main__":
  app = QApplication(sys.argv)
  form = Widget()
  form.show()
  app.exec_()

代码解析

首先是类的建立,建立text和message两个变量,使用painEvent函数把他们输出到窗口中

update函数的作用是更新窗口,由于窗口更新过程中会触发一次paineEvent函数(paintEvent是窗口基类QWidget的内部函数),因此在本例中,update函数的作用等同于paintEvent函数

import sys
from PyQt5.QtCore import (QEvent, QTimer, Qt)
from PyQt5.QtWidgets import (QApplication, QMenu, QWidget)
from PyQt5.QtGui import QPainter
class Widget(QWidget):
  def __init__(self, parent=None):
    super(Widget, self).__init__(parent)
    #初始化数据
    #鼠标双击False
    self.justDoubleClicked = False
    #按键,输出文本,提示消息为空
    self.key = ""
    self.text = ""
    self.message = ""
    #设置窗口初始大小与位置
    self.resize(400, 300)
    self.move(100, 100)
    #设置标题
    self.setWindowTitle("Events")
    #定时器1秒后执行槽函数
    QTimer.singleShot(1000, self.giveHelp)
    # 避免窗口大小重绘事件的影响,可以把参数0改变成3000(3秒),然后在运行,就可以明白这行代码的意思。
  def giveHelp(self):
    self.text = "请点击这里触发追踪鼠标功能"
    # 重绘事件,也就是触发paintEvent函数。
    self.update()

初始化运行结果如下

python GUI库图形界面开发之PyQt5信号与槽事件处理机制详细介绍与实例解析

然后是重新实现窗口关闭事件与上下文菜单事件,主要影响message标量的结果,paintEvent负责把这个变量在窗口底部输出

'''重新实现关闭事件'''
  def closeEvent(self, event):
    print("Closed")
  '''重新实现上下文菜单事件'''
  def contextMenuEvent(self, event):
    #实例化菜单,添加子菜单one two并附加快捷键功能,关联槽函数
    menu = QMenu(self)
    oneAction = menu.addAction("&One")
    twoAction = menu.addAction("&Two")
    oneAction.triggered.connect(self.one)
    twoAction.triggered.connect(self.two)
    #如果message为空,执行
    if not self.message:
      #在菜单中添加一条分割线
      menu.addSeparator()
      #添加自菜单three,关联槽函数
      threeAction = menu.addAction("Thre&e")
      threeAction.triggered.connect(self.three)
    #菜单栏出现在鼠标的位置
    menu.exec_(event.globalPos())
  '''上下文菜单槽函数'''
  def one(self):
    self.message = "Menu option One"
    self.update()
  def two(self):
    self.message = "Menu option Two"
    self.update()
  def three(self):
    self.message = "Menu option Three"
    self.update()

python GUI库图形界面开发之PyQt5信号与槽事件处理机制详细介绍与实例解析

绘制事件是代码的核心事件,它的作用是时刻跟随text和message这两个变量的信息,并把text内容绘制到窗口的中部,把message的内容绘制到窗口的底部

'''重新实现绘制事件'''
  def paintEvent(self, event):
    text = self.text
    i = text.find("\n\n")
    if i >= 0:
      text = text[0:i]
    # 若触发了键盘按钮,则在文本信息中记录这个按钮信息。
    if self.key:
      text += "\n\n你按下了: {0}".format(self.key)
    painter = QPainter(self)
    painter.setRenderHint(QPainter.TextAntialiasing)
    # 绘制信息文本的内容
    painter.drawText(self.rect(), Qt.AlignCenter, text)
    # 若消息文本存在则在底部居中绘制消息,5秒钟后清空消息文本并重绘。
    if self.message:
      #显示给定坐标处的文本,坐标,对齐方式。文本内容
      painter.drawText(self.rect(), Qt.AlignBottom | Qt.AlignHCenter,
               self.message)
      #5秒钟后触发清空信息的函数,并重新绘制事件
      QTimer.singleShot(5000, self.clearMessage)
      QTimer.singleShot(5000, self.update)
  '''清空消息文本的槽函数'''
  def clearMessage(self):
    self.message = ""

接下来是调整窗口大小事件

'''重新实现调整窗口大小事件'''
  def resizeEvent(self, event):
    self.text = "调整窗口大小为: QSize({0}, {1})".format(
      event.size().width(), event.size().height())
    self.update()

python GUI库图形界面开发之PyQt5信号与槽事件处理机制详细介绍与实例解析

实现鼠标释放事件,若为双击释放,则不跟随鼠标移动,若为单击释放,则需要跟随鼠标移动状态进行更改,如果开启跟踪功能就跟踪,否则就不跟综

'''重新实现鼠标释放事件'''
  def mouseReleaseEvent(self, event):
    # 若鼠标释放为双击释放,则不跟踪鼠标移动
    if self.justDoubleClicked:
      self.justDoubleClicked = False
    # 若鼠标释放为单击释放,则需要改变跟踪功能的状态,如果开启跟踪功能的话就跟踪,不开启跟踪功能就不跟踪
    else:
      # 单击鼠标
      self.setMouseTracking(not self.hasMouseTracking())
      if self.hasMouseTracking():
        self.text = "开启鼠标跟踪功能.\n" + \
              "请移动一下鼠标!\n" + \
              "单击鼠标可以关闭这个功能"
      else:
        self.text = "关闭鼠标跟踪功能.\n" + \
              "单击鼠标可以开启这个功能"
      self.update()

python GUI库图形界面开发之PyQt5信号与槽事件处理机制详细介绍与实例解析

python GUI库图形界面开发之PyQt5信号与槽事件处理机制详细介绍与实例解析

python GUI库图形界面开发之PyQt5信号与槽事件处理机制详细介绍与实例解析

实现鼠标移动事件

'''重新实现鼠标移动事件'''
  def mouseMoveEvent(self, event):
    #如果没有鼠标双击,执行
    if not self.justDoubleClicked:
      # 窗口坐标转换为屏幕坐标
      globalPos = self.mapToGlobal(event.pos())
      self.text = """鼠标位置:
      窗口坐标为:QPoint({0}, {1}) 
      屏幕坐标为:QPoint({2}, {3}) """.format(event.pos().x(), event.pos().y(), globalPos.x(), globalPos.y())
      self.update()
  '''重新实现鼠标双击事件'''
  def mouseDoubleClickEvent(self, event):
    self.justDoubleClicked = True
    self.text = "你双击了鼠标"
    self.update()

python GUI库图形界面开发之PyQt5信号与槽事件处理机制详细介绍与实例解析

实现键盘按下事件

'''重新实现键盘按下事件'''
  def keyPressEvent(self, event):
    self.key = ""
    if event.key() == Qt.Key_Home:
      self.key = "Home"
    elif event.key() == Qt.Key_End:
      self.key = "End"
    elif event.key() == Qt.Key_PageUp:
      if event.modifiers() & Qt.ControlModifier:
        self.key = "Ctrl+PageUp"
      else:
        self.key = "PageUp"
    elif event.key() == Qt.Key_PageDown:
      if event.modifiers() & Qt.ControlModifier:
        self.key = "Ctrl+PageDown"
      else:
        self.key = "PageDown"
    elif Qt.Key_A <= event.key() <= Qt.Key_Z:
      if event.modifiers() & Qt.ShiftModifier:
        self.key = "Shift+"
      self.key += event.text()
    #如果key有字符,不为空,则绘制字符
    if self.key:
      self.key = self.key
      self.update()
    #否则就继续监视这个事件
    else:
      QWidget.keyPressEvent(self, event)

python GUI库图形界面开发之PyQt5信号与槽事件处理机制详细介绍与实例解析

重载tab键

'''重新实现其他事件,适用于PyQt没有提供该事件的处理函数的情况,Tab键由于涉及焦点切换,不会传递给keyPressEvent,因此,需要在这里重新定义。'''
  def event(self, event):
    #如果有按键按下,并且按键是tab键
    if (event.type() == QEvent.KeyPress and
          event.key() == Qt.Key_Tab):
      self.key = "在event()中捕获Tab键"
      self.update()
      return True
    return QWidget.event(self, event)

python GUI库图形界面开发之PyQt5信号与槽事件处理机制详细介绍与实例解析

过滤器的使用

import sys
from PyQt5 import Qt
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
class EventFilter(QDialog):
  def __init__( self, parent=None ):
    super(EventFilter, self).__init__(parent)
    self.setWindowTitle('事件过滤器')
    #实例化并设置四个标签文本
    self.label1 = QLabel('请点击')
    self.label2 = QLabel('请点击')
    self.label3 = QLabel('请点击')
    self.labelState = QLabel('test')
    #加载三个图片
    self.image1 = QImage('images\cartoon1.ico')
    self.image2 = QImage('images\cartoon2.ico')
    self.image3 = QImage('images\cartoon3.ico')
    self.width = 600
    self.height = 300
    #设置初始大小
    self.resize(self.width, self.height)
    #使用事假过滤器
    self.label1.installEventFilter(self)
    self.label2.installEventFilter(self)
    self.label3.installEventFilter(self)
    #设置窗口布局方式并添加控件
    layoyt = QGridLayout(self)
    layoyt.addWidget(self.label1, 500, 0)
    layoyt.addWidget(self.label2, 500, 1)
    layoyt.addWidget(self.label3, 500, 2)
    layoyt.addWidget(self.labelState, 600, 1)
  def eventFilter( self, watched, event ):
    #对事件一的处理过滤机制
    if watched == self.label1:
      if event.type() == QEvent.MouseButtonPress:
        mouseEvent = QMouseEvent(event)
        if mouseEvent.buttons() == Qt.LeftButton:
          self.labelState.setText('按下鼠标左键')
        elif mouseEvent.buttons() == Qt.MidButton:
          self.labelState.setText('按下鼠标中间键')
        elif mouseEvent.buttons() == Qt.RightButton:
          self.labelState.setText('按下鼠标右键')
        #转换图片大小
        transform=QTransform()
        transform.scale(0.5,0.5)
        tmp=self.image1.transformed(transform)
        self.label1.setPixmap(QPixmap.fromImage(tmp))
      if event.type()==QEvent.MouseButtonRelease:
        self.labelState.setText('释放鼠标按键')
        self.label1.setPixmap(QPixmap.fromImage(self.image1))
    return QDialog.eventFilter(self,watched,event)
if __name__ == '__main__':
  app=QApplication(sys.argv)
  dialog=EventFilter()
  app.installEventFilter(dialog)
  dialog.show()
  app.exec_()

运行效果如图

python GUI库图形界面开发之PyQt5信号与槽事件处理机制详细介绍与实例解析

代码解析

下面的代码意思是这个过滤器只对label1的事件进行处理,并且只处理它的鼠标按下事件和鼠标释放事件

def eventFilter( self, watched, event ):
    #对事件一的处理过滤机制
    if watched == self.label1:
      if event.type() == QEvent.MouseButtonPress:
        mouseEvent = QMouseEvent(event)
        if mouseEvent.buttons() == Qt.LeftButton:
          self.labelState.setText('按下鼠标左键')
        elif mouseEvent.buttons() == Qt.MidButton:
          self.labelState.setText('按下鼠标中间键')
        elif mouseEvent.buttons() == Qt.RightButton:
          self.labelState.setText('按下鼠标右键')
        #转换图片大小
        transform=QTransform()
        transform.scale(0.5,0.5)
        tmp=self.image1.transformed(transform)
        self.label1.setPixmap(QPixmap.fromImage(tmp))
      if event.type()==QEvent.MouseButtonRelease:
        self.labelState.setText('释放鼠标按键')
        self.label1.setPixmap(QPixmap.fromImage(self.image1))
    #对于其他的情况会返回系统默认的处理方法
    return QDialog.eventFilter(self,watched,event)

一下四行代码的意思是如果按下这个鼠标键,就会对label1装载的图片进行缩放一半

#转换图片大小
        transform=QTransform()
        transform.scale(0.5,0.5)
        tmp=self.image1.transformed(transform)
        self.label1.setPixmap(QPixmap.fromImage(tmp))

在QApplication中安装事件过滤器的使用也非常简单,只需要修改俩个地方

        #使用事件过滤器

        # self.label1.installEventFilter(self)

        # self.label2.installEventFilter(self)

        # self.label3.installEventFilter(self)

if __name__ == '__main__':
  app=QApplication(sys.argv)
  dialog=EventFilter()
  app.installEventFilter(dialog)
  dialog.show()
  app.exec_()

运行效果是一样的

好了,本文主要讲解了PyQt5信号与槽事件处理机制详细介绍与实例解析,更多关于PyQt5信号与槽的知识请查看下面的相关链接

Python 相关文章推荐
python中enumerate函数遍历元素用法分析
Mar 11 Python
Python2.X/Python3.X中urllib库区别讲解
Dec 19 Python
Python cookbook(数据结构与算法)找出序列中出现次数最多的元素算法示例
Mar 15 Python
对python创建及引用动态变量名的示例讲解
Nov 10 Python
Python用61行代码实现图片像素化的示例代码
Dec 10 Python
基于Python函数和变量名解析
Jul 19 Python
基于python二叉树的构造和打印例子
Aug 09 Python
Pytorch修改ResNet模型全连接层进行直接训练实例
Sep 10 Python
通过python 执行 nohup 不生效的解决
Apr 16 Python
浅谈Python中的函数(def)及参数传递操作
May 25 Python
PyTorch 实现L2正则化以及Dropout的操作
May 27 Python
Python中seaborn库之countplot的数据可视化使用
Jun 11 Python
python GUI库图形界面开发之PyQt5信号与槽多窗口数据传递详细使用方法与实例
Mar 08 #Python
python GUI库图形界面开发之PyQt5多线程中信号与槽的详细使用方法与实例
Mar 08 #Python
python GUI库图形界面开发之PyQt5结合Qt Designer创建信号与槽的详细方法与实例
Mar 08 #Python
python输出第n个默尼森数的实现示例
Mar 08 #Python
Tensorflow之梯度裁剪的实现示例
Mar 08 #Python
Django自定义全局403、404、500错误页面的示例代码
Mar 08 #Python
Django 自定义404 500等错误页面的实现
Mar 08 #Python
You might like
解决phpmyadmin中缺少mysqli扩展问题的方法
2013/05/06 PHP
PHP后台实现微信小程序登录
2018/08/03 PHP
thinkphp5+layui实现的分页样式示例
2019/10/08 PHP
IE9+已经不对document.createElement向下兼容的解决方法
2015/09/14 Javascript
AngularJS仿苹果滑屏删除控件
2016/01/18 Javascript
JS中innerHTML和pasteHTML的区别实例分析
2016/06/22 Javascript
js友好的时间返回函数
2016/08/24 Javascript
AngularJS实现页面定时刷新
2017/03/14 Javascript
微信小程序-滚动消息通知的实例代码
2017/08/03 Javascript
layui中layer前端组件实现图片显示功能的方法分析
2017/10/13 Javascript
webpack 打包压缩js和css的方法示例
2018/03/20 Javascript
React从react-router路由上做登陆验证控制的方法
2018/05/10 Javascript
使用Python的Flask框架构建大型Web应用程序的结构示例
2016/06/04 Python
深入浅析Python中join 和 split详解(推荐)
2016/06/30 Python
面向初学者的Python编辑器Mu
2018/10/08 Python
详解mac python+selenium+Chrome 简单案例
2019/11/08 Python
python实现布隆过滤器及原理解析
2019/12/08 Python
pytorch 中pad函数toch.nn.functional.pad()的用法
2020/01/08 Python
pip install 使用国内镜像的方法示例
2020/04/03 Python
python使用nibabel和sitk读取保存nii.gz文件实例
2020/07/01 Python
Python 日期与时间转换的方法
2020/08/01 Python
Python的3种运行方式:命令行窗口、Python解释器、IDLE的实现
2020/10/10 Python
YSL Beauty加拿大官方商城:圣罗兰美妆加拿大
2017/05/15 全球购物
毕业生造价工程师求职信
2013/10/17 职场文书
校园门卫岗位职责
2013/12/09 职场文书
护士自荐信范文
2013/12/15 职场文书
员工薪酬福利制度
2014/01/17 职场文书
安全生产检查通报
2014/01/29 职场文书
违反校纪校规检讨书
2014/02/15 职场文书
专业技术职务聘任书
2014/03/29 职场文书
新教师个人工作总结
2015/02/06 职场文书
秋收起义观后感
2015/06/11 职场文书
小学体育队列队形教学反思
2016/02/16 职场文书
行政后勤人员工作计划应该怎么写?
2019/08/16 职场文书
浅谈Python数学建模之整数规划
2021/06/23 Python
Nginx实现会话保持的两种方式
2022/03/18 Servers