如何将输入行中的值传递到按钮调用的 python 函数中
How pass values from Entry lines into a python function called by a button
我正在尝试为 SRS DG645 制作用户界面。我是 PyQt5 的新手(让我们面对现实 - 我对 Python 也很陌生),我试图做一个小的测试菜单来尝试获得一些功能 - 并了解它是如何工作的。
我能够通过 'Initialize' 和 'Close' 按钮成功启动和关闭与仪器的连接。
接下来我想做的是能够设置延迟。为此,我创建了两个条目 - entry1 和 entry2 - 它们将提供 'channel'(整数)和 'timing'(浮点数)。
为了使脚本正常工作,我需要将 'Write Values' 按钮与先前在文件中描述的函数相关联 - set_delay() - 这需要一个元组(通道,时序)才能成功执行。
我完全不知道如何实现此按钮的代码,因为我不明白如何获取输入框传递的参数并将它们插入所需的 dg.set_value() 函数.
我知道这个答案:How to pass arguments to functions by the click of button in PyQt? 我认为它没有完全回答我现在的问题
如有任何帮助,我们将不胜感激!
PS:非常感谢 Trappisch 和 Casagrande 在 Git 中编写代码 public!
请在下面找到我的实施的 MWE
# -*- coding: utf-8 -*-
"""
Driver for devices from Stanford Research Systems
contains:
- DG645
File name: stanford_research_systems.py
Python version: 3.7
This script reuses code from
https://github.com/Galvant/InstrumentKit/blob/master/instruments/srs/srsdg645.py
by Reto Trappisch and Steven Casagrande
"""
from typing import Tuple, Union
import socket
import time
from termcolor import colored, cprint
import sys
from PyQt5 import QtWidgets as qtw
from PyQt5 import QtGui as qtg
from PyQt5 import QtCore as qtc
class DG645:
""" Driver for delay generators """
DEFAULTS = {
'outputBNC': {
"T0":0,
"AB":1,
"CD":2,
"EF":3,
"GH":4
},
'channel': {
"T0":0,
"T1":1,
"A":2,
"B":3,
"C":4,
"D":5,
"E":6,
"F":7 ,
"G":8,
"H":9
},
'write_termination': '\n',
'read_termination': '\r\n',
}
def __init__(self, tcp: str, port: int, timeout: float = 0.010):
"""
Arguments:
tcp - IP address of device
port - port of device
timeout - time in seconds before recv() gives a timeout error
"""
self.tcp = tcp
self.port = port
self._device = None
self.timeout = timeout
def initialize(self):
"""Connect to the device."""
self._device = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self._device.settimeout(self.timeout)
self._device.connect((self.tcp, self.port))
time.sleep(0.2)
print_blue_on_white = lambda x: cprint(x, 'blue', 'on_white')
print_blue_on_white(f'=======================\n Connection Sucessful! \n=======================\n{self.idn}')
# time.sleep(0.3)
# print_blue_on_white(f'MAC Address is \n{self.emac}')
def close(self):
"""Closing connection with the device"""
print_red_on_white = lambda x: cprint(x, 'red', 'on_white')
print_red_on_white(f'{self.idn}\n===================\n Connection closed \n===================')
self._device.close()
def write(self, cmd: str) -> None:
"""Send command to device"""
# Add write termination character and encode
termination_char = self.DEFAULTS['write_termination']
cmd += termination_char
cmd = cmd.encode()
# Send command
self._device.send(cmd)
def query(self, cmd: str) -> str:
"""Send a request to the device and return its respons."""
self.write(cmd)
respons = self._device.recv(256)
respons = respons.decode()
# Strip off read termination character
return respons.rstrip()
@property
def idn(self) -> str:
""" Get identification of device. """
idn = self.query('*IDN?')
return idn
def set_delay(self, channel: Union[int, str], delay: float, reference: Union[int, str] = "T0"):
"""Set the delay of a certain channel with respect to a reference.
Arguments:
channel -- str/int corresponding to a channel (see self.DEFAULTS)
delay -- float, with time in seconds
reference -- defaults to 'T0'
"""
if isinstance(channel, str):
channel = self.DEFAULTS['channel'][channel]
if isinstance(reference, str):
reference = self.DEFAULTS['channel'][reference]
cmd = f'DLAY {channel}, {reference}, {delay}'
self.write(cmd)
#wait for 100 ms, this is the time it will take to write the command
time.sleep(0.1)
def get_delay(self, channel: Union[int, str]) -> Tuple[int, float]:
"""Request the delay of a certain channel
Arguments:
channel -- str/int corresponding to a channel (see self.DEFAULTS)
Returns -- (int, float) | reference channel, delay in seconds.
"""
if isinstance(channel, str):
channel = self.DEFAULTS['channel'][channel]
cmd = f'DLAY? {channel}'
respons = self.query(cmd).split(',')
reference = int(respons[0])
delay = float(respons[1])
return reference, delay
def get_output_level(self, channel: Union[int, str]) -> float:
"""Request output amplitude of a channel
Arguments:
channel -- str/int corresponding to a channel (see self.DEFAULTS)
Returns --float, the amplitude in Volts
"""
if isinstance(channel, str):
channel = self.DEFAULTS['outputBNC'][channel]
cmd = f'LAMP? {channel}'
respons = self.query(cmd)
return float(respons)
def emac(self) -> str:
"Get MAC address of device"
emac = self.query('*EMAC?')
return emac
class MainWindow(qtw.QWidget) :
def __init__(self) :
"""MainWindow constructor"""
super().__init__()
##########################
# Main UI code goes here #
##########################
layout = qtw.QVBoxLayout()
self.setLayout(layout)
self.quitbutton = qtw.QPushButton('Quit',clicked=self.close)
self.initializebutton = qtw.QPushButton('initialize', clicked=dg.initialize)
self.closebutton = qtw.QPushButton('Close', clicked=dg.close)
self.layout().addWidget(self.quitbutton)
self.layout().addWidget(self.initializebutton)
self.layout().addWidget(self.closebutton)
self.label1 = qtw.QLabel('Channel')
self.entry1 = qtw.QLineEdit()
self.label2 = qtw.QLabel('Timing')
self.entry2 = qtw.QLineEdit()
self.layout().addWidget(self.label1)
self.layout().addWidget(self.entry1)
self.layout().addWidget(self.label2)
self.layout().addWidget(self.entry2)
self.wtrigbutton = qtw.QPushButton('Write Values', clicked=dg.set_delay)
##########################
# End of UI code Section #
##########################
self.show()
if __name__ == '__main__':
dg = DG645('169.254.74.114', 5025)
app = qtw.QApplication(sys.argv)
mw = MainWindow()
sys.exit(app.exec())
#################################################
## Commented code for DDG setup via script run ##
#################################################
# dg = DG645('169.254.74.114', 5025)
# dg.initialize()
# for i in range (0,8):
# delay = dg.get_delay(i)
# print(f"Delay {i} is set to ", delay)
# dg.set_delay(0, 0.000000000)
# print("Delay 1 is now set to", delay1)
# delay2 = dg.get_delay(2)
# print("Delay 2 is set to", delay2)
# dg.emac()
# dg.close()
################################################
################################################
Qt 信号不需要直接连接到必须调用的“最终”函数。
对于简单的情况,您仍然可以使用 lambda 作为链接的答案 post 建议:
class MainWindow(qtw.QWidget):
def __init__(self) :
super().__init__()
# ...
self.wtrigbutton = qtw.QPushButton('Write Values')
self.wtrigbutton.clicked.connect(lambda:
dg.set_delay(self.entry1.text(), self.entry2.text()))
但在大多数情况下,最好有一个显式函数,这样也更安全,更便于调试。
如果您必须调用需要参数的函数,请创建一个函数,该函数 获取 这些参数并最终调用实际函数进行处理,然后将该函数用于信号连接:
class MainWindow(qtw.QWidget):
def __init__(self) :
super().__init__()
# ...
self.wtrigbutton = qtw.QPushButton('Write Values', clicked=self.setDelay)
def setDelay(self):
channel = self.entry1.text()
timing = self.entry2.text()
if channel and timing:
dg.set_delay(channel, timing)
请注意,您应该 永远不要 使用 time.sleep()
之类的阻塞函数(或阻塞 while 循环),因为这可能会冻结 UI 阻止正确的用户交互和 UI 更新;如果你需要延迟一个函数调用,使用QTimer,如果你需要延迟处理(比如等待IO),使用QThread。
我正在尝试为 SRS DG645 制作用户界面。我是 PyQt5 的新手(让我们面对现实 - 我对 Python 也很陌生),我试图做一个小的测试菜单来尝试获得一些功能 - 并了解它是如何工作的。
我能够通过 'Initialize' 和 'Close' 按钮成功启动和关闭与仪器的连接。
接下来我想做的是能够设置延迟。为此,我创建了两个条目 - entry1 和 entry2 - 它们将提供 'channel'(整数)和 'timing'(浮点数)。
为了使脚本正常工作,我需要将 'Write Values' 按钮与先前在文件中描述的函数相关联 - set_delay() - 这需要一个元组(通道,时序)才能成功执行。
我完全不知道如何实现此按钮的代码,因为我不明白如何获取输入框传递的参数并将它们插入所需的 dg.set_value() 函数.
我知道这个答案:How to pass arguments to functions by the click of button in PyQt? 我认为它没有完全回答我现在的问题
如有任何帮助,我们将不胜感激!
PS:非常感谢 Trappisch 和 Casagrande 在 Git 中编写代码 public!
请在下面找到我的实施的 MWE
# -*- coding: utf-8 -*-
"""
Driver for devices from Stanford Research Systems
contains:
- DG645
File name: stanford_research_systems.py
Python version: 3.7
This script reuses code from
https://github.com/Galvant/InstrumentKit/blob/master/instruments/srs/srsdg645.py
by Reto Trappisch and Steven Casagrande
"""
from typing import Tuple, Union
import socket
import time
from termcolor import colored, cprint
import sys
from PyQt5 import QtWidgets as qtw
from PyQt5 import QtGui as qtg
from PyQt5 import QtCore as qtc
class DG645:
""" Driver for delay generators """
DEFAULTS = {
'outputBNC': {
"T0":0,
"AB":1,
"CD":2,
"EF":3,
"GH":4
},
'channel': {
"T0":0,
"T1":1,
"A":2,
"B":3,
"C":4,
"D":5,
"E":6,
"F":7 ,
"G":8,
"H":9
},
'write_termination': '\n',
'read_termination': '\r\n',
}
def __init__(self, tcp: str, port: int, timeout: float = 0.010):
"""
Arguments:
tcp - IP address of device
port - port of device
timeout - time in seconds before recv() gives a timeout error
"""
self.tcp = tcp
self.port = port
self._device = None
self.timeout = timeout
def initialize(self):
"""Connect to the device."""
self._device = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self._device.settimeout(self.timeout)
self._device.connect((self.tcp, self.port))
time.sleep(0.2)
print_blue_on_white = lambda x: cprint(x, 'blue', 'on_white')
print_blue_on_white(f'=======================\n Connection Sucessful! \n=======================\n{self.idn}')
# time.sleep(0.3)
# print_blue_on_white(f'MAC Address is \n{self.emac}')
def close(self):
"""Closing connection with the device"""
print_red_on_white = lambda x: cprint(x, 'red', 'on_white')
print_red_on_white(f'{self.idn}\n===================\n Connection closed \n===================')
self._device.close()
def write(self, cmd: str) -> None:
"""Send command to device"""
# Add write termination character and encode
termination_char = self.DEFAULTS['write_termination']
cmd += termination_char
cmd = cmd.encode()
# Send command
self._device.send(cmd)
def query(self, cmd: str) -> str:
"""Send a request to the device and return its respons."""
self.write(cmd)
respons = self._device.recv(256)
respons = respons.decode()
# Strip off read termination character
return respons.rstrip()
@property
def idn(self) -> str:
""" Get identification of device. """
idn = self.query('*IDN?')
return idn
def set_delay(self, channel: Union[int, str], delay: float, reference: Union[int, str] = "T0"):
"""Set the delay of a certain channel with respect to a reference.
Arguments:
channel -- str/int corresponding to a channel (see self.DEFAULTS)
delay -- float, with time in seconds
reference -- defaults to 'T0'
"""
if isinstance(channel, str):
channel = self.DEFAULTS['channel'][channel]
if isinstance(reference, str):
reference = self.DEFAULTS['channel'][reference]
cmd = f'DLAY {channel}, {reference}, {delay}'
self.write(cmd)
#wait for 100 ms, this is the time it will take to write the command
time.sleep(0.1)
def get_delay(self, channel: Union[int, str]) -> Tuple[int, float]:
"""Request the delay of a certain channel
Arguments:
channel -- str/int corresponding to a channel (see self.DEFAULTS)
Returns -- (int, float) | reference channel, delay in seconds.
"""
if isinstance(channel, str):
channel = self.DEFAULTS['channel'][channel]
cmd = f'DLAY? {channel}'
respons = self.query(cmd).split(',')
reference = int(respons[0])
delay = float(respons[1])
return reference, delay
def get_output_level(self, channel: Union[int, str]) -> float:
"""Request output amplitude of a channel
Arguments:
channel -- str/int corresponding to a channel (see self.DEFAULTS)
Returns --float, the amplitude in Volts
"""
if isinstance(channel, str):
channel = self.DEFAULTS['outputBNC'][channel]
cmd = f'LAMP? {channel}'
respons = self.query(cmd)
return float(respons)
def emac(self) -> str:
"Get MAC address of device"
emac = self.query('*EMAC?')
return emac
class MainWindow(qtw.QWidget) :
def __init__(self) :
"""MainWindow constructor"""
super().__init__()
##########################
# Main UI code goes here #
##########################
layout = qtw.QVBoxLayout()
self.setLayout(layout)
self.quitbutton = qtw.QPushButton('Quit',clicked=self.close)
self.initializebutton = qtw.QPushButton('initialize', clicked=dg.initialize)
self.closebutton = qtw.QPushButton('Close', clicked=dg.close)
self.layout().addWidget(self.quitbutton)
self.layout().addWidget(self.initializebutton)
self.layout().addWidget(self.closebutton)
self.label1 = qtw.QLabel('Channel')
self.entry1 = qtw.QLineEdit()
self.label2 = qtw.QLabel('Timing')
self.entry2 = qtw.QLineEdit()
self.layout().addWidget(self.label1)
self.layout().addWidget(self.entry1)
self.layout().addWidget(self.label2)
self.layout().addWidget(self.entry2)
self.wtrigbutton = qtw.QPushButton('Write Values', clicked=dg.set_delay)
##########################
# End of UI code Section #
##########################
self.show()
if __name__ == '__main__':
dg = DG645('169.254.74.114', 5025)
app = qtw.QApplication(sys.argv)
mw = MainWindow()
sys.exit(app.exec())
#################################################
## Commented code for DDG setup via script run ##
#################################################
# dg = DG645('169.254.74.114', 5025)
# dg.initialize()
# for i in range (0,8):
# delay = dg.get_delay(i)
# print(f"Delay {i} is set to ", delay)
# dg.set_delay(0, 0.000000000)
# print("Delay 1 is now set to", delay1)
# delay2 = dg.get_delay(2)
# print("Delay 2 is set to", delay2)
# dg.emac()
# dg.close()
################################################
################################################
Qt 信号不需要直接连接到必须调用的“最终”函数。
对于简单的情况,您仍然可以使用 lambda 作为链接的答案 post 建议:
class MainWindow(qtw.QWidget):
def __init__(self) :
super().__init__()
# ...
self.wtrigbutton = qtw.QPushButton('Write Values')
self.wtrigbutton.clicked.connect(lambda:
dg.set_delay(self.entry1.text(), self.entry2.text()))
但在大多数情况下,最好有一个显式函数,这样也更安全,更便于调试。
如果您必须调用需要参数的函数,请创建一个函数,该函数 获取 这些参数并最终调用实际函数进行处理,然后将该函数用于信号连接:
class MainWindow(qtw.QWidget):
def __init__(self) :
super().__init__()
# ...
self.wtrigbutton = qtw.QPushButton('Write Values', clicked=self.setDelay)
def setDelay(self):
channel = self.entry1.text()
timing = self.entry2.text()
if channel and timing:
dg.set_delay(channel, timing)
请注意,您应该 永远不要 使用 time.sleep()
之类的阻塞函数(或阻塞 while 循环),因为这可能会冻结 UI 阻止正确的用户交互和 UI 更新;如果你需要延迟一个函数调用,使用QTimer,如果你需要延迟处理(比如等待IO),使用QThread。