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


文章由安静原创,发表于www.ajnote.com。转载请注明出处

发表 2020年7月22日 自 anjing 类别 "Pyside2学习笔记

发表评论

电子邮件地址不会被公开。 必填项已用*标注