【问题标题】:PySide (or PyQt) signals and slots basicsPySide(或 PyQt)信号和槽基础知识
【发布时间】:2012-06-08 05:59:35
【问题描述】:

考虑一个像这样的简单示例,它使用信号和插槽链接两个滑块:

from PySide.QtCore import *
from PySide.QtGui import *
import sys

class MyMainWindow(QWidget):
 def __init__(self):
  QWidget.__init__(self, None)

  vbox = QVBoxLayout()

  sone = QSlider(Qt.Horizontal)
  vbox.addWidget(sone)

  stwo = QSlider(Qt.Horizontal)
  vbox.addWidget(stwo)

  sone.valueChanged.connect(stwo.setValue)

if __name__ == '__main__':
 app = QApplication(sys.argv)
 w = MyMainWindow()
 w.show()
 sys.exit(app.exec_())

您将如何更改此设置,以使第二个滑块与第一个滑块的移动方向相反?滑块一将使用这些值进行初始化:

  sone.setRange(0,99)
  sone.setValue(0)

滑块 2 将使用这些值进行初始化:

  stwo.setRange(0,99)
  stwo.setValue(99)

那么 stwo 的值就是99 - sone.sliderPosition

您将如何实现信号和槽来完成这项工作?我希望有一个基于上述简单示例的工作示例。

【问题讨论】:

    标签: python pyqt signals-slots pyside


    【解决方案1】:

    您的示例有点损坏,因为您忘记设置布局的父级,并将滑块小部件保存为成员属性以供以后访问...但是要回答您的问题,它真的很简单将您的连接指向您自己的功能:

    class MyMainWindow(QWidget):
        def __init__(self):
            QWidget.__init__(self, None)
    
            vbox = QVBoxLayout(self)
    
            self.sone = QSlider(Qt.Horizontal)
            self.sone.setRange(0,99)
            self.sone.setValue(0)
            vbox.addWidget(self.sone)
    
            self.stwo = QSlider(Qt.Horizontal)
            self.stwo.setRange(0,99)
            self.stwo.setValue(99)
            vbox.addWidget(self.stwo)
    
            self.sone.valueChanged.connect(self.sliderChanged)
    
        def sliderChanged(self, val):
            self.stwo.setValue(self.stwo.maximum() - val)
    

    注意sliderChanged() 与原始setValue() 插槽的签名如何相同。您无需将一个小部件直接连接到另一个小部件,而是将其连接到自定义方法,然后将值转换为您想要的值,然后按照您的意愿行事(在 stwo 上设置自定义值)

    【讨论】:

    • 抱歉这个不好的例子。我只是在学习。我尝试运行您的示例,但我得到了一个没有滑块(也没有错误)的空窗口。然后我注意到你编辑了你的答案。现在,当我尝试运行您的代码时,出现错误“NameError: name 'QWidget' is not defined”。我看看我能不能弄明白。顺便说一句,感谢有关如何以正确方式处理此问题的建议。
    • @MountainX:无需为您的示例道歉。你有一个组织良好的问题。很高兴你成功了!
    【解决方案2】:

    您可以将信号连接到执行操作的函数。您的代码的结构并不容易做到这一点并且需要重构,因此您可以通过简单的方式来做到这一点:

    stwo.setInvertedAppearance(True)
    sone.valueChanged.connect(stwo.setValue)
    

    【讨论】:

      【解决方案3】:

      这就是我的做法。我添加了这个重新实现 setValue 的类。 (我的想法来自http://zetcode.com/tutorials/pyqt4/eventsandsignals/

      class MySlider(QSlider):
          def __init__(self):
              QSlider.__init__(self, Qt.Horizontal)
      
          def setValue(self, int):
              QSlider.setValue(self, 99-int)
      

      这是完整的代码。这是一个好方法吗?

      from PySide.QtCore import *
      from PySide.QtGui import *
      import sys
      
      class MySlider(QSlider):
          def __init__(self):
              QSlider.__init__(self, Qt.Horizontal)
      
          def setValue(self, int):
              QSlider.setValue(self, 99-int)
      
      class MyMainWindow(QWidget):
       def __init__(self):
        QWidget.__init__(self, None)
      
        vbox = QVBoxLayout()
      
        sone = QSlider(Qt.Horizontal)
        sone.setRange(0,99)
        sone.setValue(0)
        vbox.addWidget(sone)
      
        stwo = MySlider()
        stwo.setRange(0,99)
        stwo.setValue(0)
        vbox.addWidget(stwo)
      
        sone.valueChanged.connect(stwo.setValue)
      
        self.setLayout(vbox)
      
      if __name__ == '__main__':
          app = QApplication(sys.argv)
          w = MyMainWindow()
          w.show()
          sys.exit(app.exec_())
      

      【讨论】:

      • 你不需要子类化。只需连接到另一个插槽。利用您可以将信号连接到任何方法的事实。我认为这种方法的问题是,您避免了使用 Qt 类中已经可用的功能的更简单途径,并在不需要时进行子类化。将您的小部件保存为实例属性并使用它们。
      • 另外,现在你有一个 MySlider 类,它被简单地硬编码为将其值设置为99-int(int btw 隐藏了内置的int
      • @jdi:我很欣赏有关 int 遮蔽内置 int 的反馈。代码应该是 `def setValue(self, val): QSlider.setValue(self, 99-val)'。但无论如何,你的方法更好。这对我来说是一个学习练习,所以现在我知道了几种方法。
      猜你喜欢
      • 2013-10-22
      • 2011-08-08
      • 2012-07-13
      • 1970-01-01
      • 2015-05-29
      • 1970-01-01
      • 1970-01-01
      • 2015-02-09
      • 2011-04-23
      相关资源
      最近更新 更多