2012-06-04 5 views
3

Рассмотрим простой пример, как это, который связывает два слайдера с использованием сигналов и слотов:PySide (или PyQt) сигналы и слоты Основы

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_()) 

Как бы вы изменить это так, что второй ползун движется в противоположном направлении, как первый? Slider один будет инициализирован с этими значениями:

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

и ползунок два будет инициализирован с этими значениями:

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

И тогда значение stwo будет 99 - sone.sliderPosition.

Как бы вы реализовали сигнал и слот, чтобы сделать эту работу? Я был бы признателен за рабочий пример, который опирается на простой пример выше.

ответ

3

Ваш пример немного сломанный, потому что вы забыли установить родительский макете, а также для сохранения ползунков виджетов, атрибутов члена будет доступен позже ... Но чтобы ответить на ваш вопрос, его действительно так просто, как просто указав подключение к вашей собственной функции:

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)

+0

Извините за плохой пример. Я просто учился. Я попробовал запустить ваш пример, и я получил пустое окно без ползунков (и никаких ошибок). Тогда я заметил, что вы отредактировали свой ответ. Теперь я получаю сообщение об ошибке «NameError: name« QWidget »не определен», когда я пытаюсь запустить ваш код. Я посмотрю, смогу ли я это понять. Кстати, спасибо за предложения о том, как правильно подойти к этому. – MountainX

+0

Получил работу. Благодарю. – MountainX

+0

@MountainX: не нужно извиняться за ваши примеры. У вас был хорошо организованный вопрос. Рад, что ты заработал! – jdi

3

Вы можете подключать сигналы к функциям, которые делают что-то. Ваш код не структурирован так легко и требует рефакторинга, поэтому вы можете сделать это простым способом:

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

Вот как я это сделал. Я добавил этот класс, который повторяет 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_()) 
+0

Вам не нужно было подкласса. Просто подключитесь к другому слоту. Используйте тот факт, что вы можете подключить сигнал к любому методу. Проблема, я думаю, с этим подходом заключается в том, что вы избегаете более простой путь использования функциональных возможностей, которые уже доступны в классе Qt, и подклассы, когда это не нужно. Сохраните свои виджеты в качестве атрибутов экземпляра и используйте их. – jdi

+0

Кроме того, теперь у вас есть класс MySlider, который просто жестко закодирован для установки его значения как '99-int' (int btw тени встроенного' int') – jdi

+0

@jdi: ОК, спасибо за ваш ответ. – MountainX

Смежные вопросы