如何在PyQt5上使用Vars,就像在tkinter上使用IntVar()或StringVar()一样?
问题描述
创建变量
region = {'top': tk.IntVar(), 'left': tk.IntVar(), 'right': tk.IntVar(), 'bottom': tk.IntVar()}
创建条目并连接到无变量
tk.Entry(master, textvariable=region['top']).place(x=60, y=100)
tk.Entry(master, textvariable=region['left']).place(x=60, y=120)
tk.Entry(master, textvariable=region['right']).place(x=60, y=140)
tk.Entry(master, textvariable=region['bottom']).place(x=60, y=160)
我在某些函数上使用变量
def get_region():
np.array(ImageGrab.grab(bbox=(region['top'].get(), region['left'].get(), region['right'].get(), region['bottom'].get())))
并使用变量在应用程序上保存和打开配置文件
def open_file(self):
with open('{}'.format(filedialog.askopenfilename(initialdir="/", title="Select file",
filetypes=(("json files", "*.json"),
("all files", "*.*")))), 'r') as config:
data = json.load(config)
region['top'].set(data['region']['top'])
region['left'].set(data['region']['left'])
region['right'].set(data['region']['right'])
region['bottom'].set(data['region']['bottom'])
def save_as(self):
json.decoder = {
'region': {
'top': region['top'].get(),
'left': region['left'].get(),
'right': region['right'].get(),
'bottom': region['bottom'].get(),
},
}
with open('{}'.format(filedialog.asksaveasfilename(initialdir="/", title="Save file",
filetypes=(("json files", "*.json"),
("all files", "*.*")))), 'w',
encoding='utf-8') as config:
json.dump(json.decoder, config, ensure_ascii=False, indent=2)
config.close()
我在PyQt5中使用什么而不是IntVar()来构建这样的结构?
解决方案
Qt中没有相似的元素(有两个不同的库,方法不同),一种可能的解决方案是创建一个映射qproperties的对象:
from dataclasses import dataclass
import json
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
import sip
@dataclass
class Property:
qobject: QtCore.QObject = None
qproperty: str = ""
@property
def value(self):
if self.qobject and not sip.isdeleted(self.qobject):
return self.qobject.property(self.qproperty)
@value.setter
def value(self, value):
if self.qobject and not sip.isdeleted(self.qobject):
self.qobject.setProperty(self.qproperty, value)
class Widget(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
top_spinbox = QtWidgets.QSpinBox(maximum=2147483647)
left_spinbox = QtWidgets.QSpinBox(maximum=2147483647)
right_spinbox = QtWidgets.QSpinBox(maximum=2147483647)
bottom_spinbox = QtWidgets.QSpinBox(maximum=2147483647)
button = QtWidgets.QPushButton(self.tr("grab"), clicked=self.grab_screen)
file_menu = self.menuBar().addMenu(self.tr("&File"))
open_action = file_menu.addAction(self.tr("Open File..."))
open_action.triggered.connect(self.load_config)
save_action = file_menu.addAction(self.tr("Save"))
save_action.triggered.connect(self.save_config)
central_widget = QtWidgets.QWidget()
self.setCentralWidget(central_widget)
flay = QtWidgets.QFormLayout(central_widget)
flay.addRow(button)
flay.addRow("Top:", top_spinbox)
flay.addRow("Left:", left_spinbox)
flay.addRow("Right:", right_spinbox)
flay.addRow("Bottom:", bottom_spinbox)
self.resize(640, 480)
self.region = {
"top": Property(qobject=top_spinbox, qproperty="value"),
"left": Property(qobject=left_spinbox, qproperty="value"),
"right": Property(qobject=right_spinbox, qproperty="value"),
"bottom": Property(qobject=bottom_spinbox, qproperty="value"),
}
@QtCore.pyqtSlot()
def grab_screen(self):
top = self.region["top"].value
left = self.region["left"].value
right = self.region["right"].value
bottom = self.region["bottom"].value
print(top, left, right, bottom)
@QtCore.pyqtSlot()
def load_config(self):
filename, _ = QtWidgets.QFileDialog.getOpenFileName(
self,
self.tr("Select file"),
"/",
self.tr("JSON files (*.json);;All files (*.*)"),
)
if filename:
with open(filename, "r") as f:
data = json.load(f)
if "region" in data:
self.region["top"].value = data["region"].get("top", 0)
self.region["left"].value = data["region"].get("left", 0)
self.region["right"].value = data["region"].get("right", 0)
self.region["bottom"].value = data["region"].get("bottom", 0)
@QtCore.pyqtSlot()
def save_config(self):
filename, _ = QtWidgets.QFileDialog.getSaveFileName(
self,
self.tr("Save file"),
"/",
self.tr("JSON files (*.json);;All files (*.*)"),
)
if filename:
with open(filename, "w", encoding="utf-8") as f:
data = {
"region": {
"top": self.region["top"].value,
"left": self.region["left"].value,
"right": self.region["right"].value,
"bottom": self.region["bottom"].value,
},
}
json.dump(data, f, ensure_ascii=False, indent=2)
def main():
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
QLineEdit示例:
from dataclasses import dataclass
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
import sip
@dataclass
class Property:
qobject: QtCore.QObject = None
qproperty: str = ""
@property
def value(self):
if self.qobject and not sip.isdeleted(self.qobject):
return self.qobject.property(self.qproperty)
@value.setter
def value(self, value):
if self.qobject and not sip.isdeleted(self.qobject):
self.qobject.setProperty(self.qproperty, value)
def main():
app = QtWidgets.QApplication(sys.argv)
w = QtWidgets.QLineEdit()
prop = Property(w, "text")
# variable for test
counter = 0
def on_timeout():
nonlocal counter
print("text:", prop.value)
counter += 1
prop.value = counter
timer = QtCore.QTimer(interval=1000, timeout=on_timeout)
timer.start()
w.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
相关文章