7月
22
Pyside2教程:日历小程序
import sys
from PySide2 import QtWidgets as qtw
from PySide2 import QtGui as qtg
from PySide2 import QtCore as qtc
class CategoryWindow(qtw.QWidget):
submitted = qtc.Signal(str)
def __init__(self):
super().__init__()
self.setLayout(qtw.QVBoxLayout())
self.layout().addWidget(qtw.QLabel('请输入类型名称:'))
self.category_entry = qtw.QLineEdit()
self.layout().addWidget(self.category_entry)
self.submit_btn = qtw.QPushButton('提交', clicked=self.onSubmit)
self.layout().addWidget(self.submit_btn)
self.cancel_btn = qtw.QPushButton('取消', clicked=self.close)
self.layout().addWidget(self.cancel_btn)
self.show()
@qtc.Slot()
def onSubmit(self):
if self.category_entry.text():
try:
self.submitted.emit(self.category_entry.text())
except AttributeError:
pass
self.close()
# 将主程序封装成类
class MainWindow(qtw.QWidget):
# 注意这里应该是一个类变量而不是实例变量。只有这样,通过实例改变的数值才能全局性的改变。
events = {}
def __init__(self):
# 引入父类的__init__方法
super().__init__(parent=None)
# Main UI code goes here
self.setWindowTitle('日历')
self.resize(800, 600)
# 创建widgets
self.calendar = qtw.QCalendarWidget()
self.event_list = qtw.QListWidget()
self.event_title = qtw.QLineEdit()
self.event_category = qtw.QComboBox()
self.event_time = qtw.QTimeEdit(qtc.QTime(8, 0))
self.allday_check =qtw.QCheckBox('全天')
self.event_detail =qtw.QTextEdit()
self.add_button = qtw.QPushButton('新建/更新')
self.del_button = qtw.QPushButton('删除')
# 配置QComboBox
self.event_category.addItems(['选择类型', '新建...', '工作', '会议', '就医', '家庭'])
self.event_category.model().item(0).setEnabled(False)
# 配置layout
main_layout = qtw.QHBoxLayout()
self.setLayout(main_layout)
main_layout.addWidget(self.calendar)
self.calendar.setSizePolicy(qtw.QSizePolicy.Expanding, qtw.QSizePolicy.Expanding)
right_layout = qtw.QVBoxLayout()
main_layout.addLayout(right_layout)
right_layout.addWidget(qtw.QLabel('事件列表'))
right_layout.addWidget(self.event_list)
self.event_list.setSizePolicy(qtw.QSizePolicy.Expanding, qtw.QSizePolicy.Expanding)
event_form = qtw.QGroupBox('事件管理')
right_layout.addWidget(event_form)
event_form_layout = qtw.QGridLayout()
event_form.setLayout(event_form_layout)
# 设置表单
event_form_layout.addWidget(self.event_title, 1, 1, 1, 3)
event_form_layout.addWidget(self.event_category, 2, 1)
event_form_layout.addWidget(self.event_time, 2, 2)
event_form_layout.addWidget(self.allday_check, 2, 3)
event_form_layout.addWidget(self.event_detail, 3, 1, 1, 3)
event_form_layout.addWidget(self.add_button, 4, 2)
event_form_layout.addWidget(self.del_button, 4, 3)
# 在选择全天时,disable时间选择控件
self.allday_check.toggled.connect(self.event_time.setDisabled)
# selectionChanged信号不传送数据
self.calendar.selectionChanged.connect(self.populate_list)
self.event_list.itemSelectionChanged.connect(self.populate_form)
self.add_button.clicked.connect(self.save_event)
self.del_button.clicked.connect(self.delete_event)
self.event_list.itemSelectionChanged.connect(self.check_delete_btn)
# 单独调用是为了保证删除按钮在启动时就处于禁用状态
self.check_delete_btn()
self.event_category.currentTextChanged.connect(self.on_category_change)
# End main UI code
# 显示主窗口
self.show()
# 工具方法,用于清除表单中的所有状态
def clear_form(self):
self.event_title.clear()
self.event_category.setCurrentIndex(0)
self.event_time.setTime(qtc.QTime(8, 0))
self.allday_check.setChecked(False)
self.event_detail.setPlainText('')
def populate_list(self):
self.event_list.clear()
self.clear_form()
date = self.calendar.selectedDate()
# dict的get方法,第一个参数:键,第二个参数:如果指定键的值不存在时,返回该默认值
for event in self.events.get(date, []):
time = (event['time'].toString('hh:mm') if event['time'] else '全天')
self.event_list.addItem("{}: {}".format(time, event['title']))
def populate_form(self):
self.clear_form()
date = self.calendar.selectedDate()
event_number = self.event_list.currentRow()
if event_number == -1:
return
event_data = self.events.get(date)[event_number]
self.event_category.setCurrentText(event_data['category'])
if event_data['time'] is None:
self.allday_check.setChecked(True)
else:
self.event_time.setTime(event_data['time'])
self.event_title.setText(event_data['title'])
self.event_detail.setPlainText(event_data['detail'])
def save_event(self):
event = {
'category': self.event_category.currentText(),
'time': (None if self.allday_check.isChecked() else self.event_time.time()),
'title': self.event_title.text(),
'detail': self.event_detail.toPlainText()
}
date = self.calendar.selectedDate()
event_list = self.events.get(date, [])
event_number = self.event_list.currentRow()
if event_number == -1:
event_list.append(event)
else:
event_list[event_number] = event
event_list.sort(key=lambda x: x['time'] or qtc.QTime(0, 0))
self.events[date] = event_list
self.populate_list()
def delete_event(self):
date = self.calendar.selectedDate()
row = self.event_list.currentRow()
del(self.events[date][row])
# 将currentRow设置成-1,表示没有选择
self.event_list.setCurrentRow(-1)
self.clear_form()
self.populate_list()
def check_delete_btn(self):
self.del_button.setDisabled(self.event_list.currentRow() == -1)
def add_category(self, category):
self.event_category.addItem(category)
self.event_category.setCurrentText(category)
def on_category_change(self, text):
if text == '新建...':
self.dialog = CategoryWindow()
self.dialog.submitted.connect(self.add_category)
self.event_category.setCurrentIndex(0)
if __name__ == '__main__':
app = qtw.QApplication()
main_window = MainWindow()
sys.exit(app.exec_())