当前位置: 代码网 > it编程>编程语言>C/C++ > 使用PyQt编写一个简单的待办程序

使用PyQt编写一个简单的待办程序

2025年02月18日 C/C++ 我要评论
框架选择一个简单的gui程序,可以使用pyqt完成。pyqt是qt的python实现版本。界面搭建设计一个美观简洁的界面class todoapp(qwidget): def __init__(

框架选择

一个简单的gui程序,可以使用pyqt完成。pyqt是qt的python实现版本。

界面搭建

设计一个美观

简洁的界面

class todoapp(qwidget):
    def __init__(self):
        super().__init__()

        # 设置窗口属性
        self.setwindowtitle("daily to do list")
        self.setgeometry(100, 100, 400, 400)

        # 初始化主布局
        self.main_layout = qvboxlayout()

        # 创建输入和添加按钮
        self.input_layout = qgridlayout()

        # 标题输入
        self.title_label = qlabel("标题:")
        self.title_input = qlineedit()
        self.input_layout.addwidget(self.title_label, 0, 0)
        self.input_layout.addwidget(self.title_input, 0, 1)

        # 描述输入
        self.description_label = qlabel("描述:")
        self.description_input = qlineedit()
        self.input_layout.addwidget(self.description_label, 1, 0)
        self.input_layout.addwidget(self.description_input, 1, 1)

        # 水平按钮布局
        self.add_layout = qhboxlayout()
        self.add_layout.setspacing(20)

        # 导入
        self.import_button = qpushbutton('批量导入')
        self.import_button.clicked.connect(self.import_item)
        self.add_layout.addwidget(self.import_button)
        
        self.add_button = qpushbutton("添加")
        self.add_button.clicked.connect(self.add_item)
        self.add_layout.addwidget(self.add_button)

        # 任务列表
        self.to_do_list = qlistwidget()
        self.to_do_list.setstylesheet("padding: 10px;")
        self.to_do_list.setverticalscrollmode(qlistwidget.scrollperpixel)

        # 创建操作按钮
        self.buttons_layout = qhboxlayout()
        self.mark_done_button = qpushbutton("标记完成")
        self.mark_done_button.clicked.connect(self.mark_item_done)
        self.delete_button = qpushbutton("删除")
        self.delete_button.clicked.connect(self.delete_item)
        self.buttons_layout.addwidget(self.mark_done_button)
        self.buttons_layout.addwidget(self.delete_button)

        # 将布局添加到主窗口
        self.main_layout.addlayout(self.input_layout)
        self.main_layout.addlayout(self.add_layout)
        self.main_layout.addwidget(self.to_do_list)
        self.main_layout.addlayout(self.buttons_layout)

        # 设置窗口布局
        self.setlayout(self.main_layout)

qgridlayout的使用

qgridlayout是网格布局,在添加子窗口时可以设定位置(行、列)和占据的大小(占几行几列)

import sys
from pyqt5.qtwidgets import qapplication, qwidget, qgridlayout, qlabel, qpushbutton

class gridexample(qwidget):
    def __init__(self):
        super().__init__()
        self.init_ui()

    def init_ui(self):
        self.setwindowtitle("pyqt qgridlayout example")
        self.setgeometry(100, 100, 400, 300)

        # 创建 qgridlayout
        layout = qgridlayout(self)

        # 创建一个标题标签
        title_label = qlabel("header label", self)
        title_label.setstylesheet("font-size: 18px; font-weight: bold; color: blue;")
        # 将标题设置为占据第一行的所有列
        layout.addwidget(title_label, 0, 0, 1, 3)  # 行, 列, 占据行数, 占据列数

        # 创建一个 3x3 的按钮网格
        for i in range(3):
            for j in range(3):
                button = qpushbutton(f"button {i*3 + j +1}", self)
                layout.addwidget(button, i + 1, j)  # 按钮从行1开始

        # 创建一个右侧按钮占据一列
        right_button = qpushbutton("right button", self)
        # 设置右侧按钮占据第3列的所有行
        layout.addwidget(right_button, 1, 3, 3, 1)  # 行1到3, 列3

        # 创建一个底部按钮占据一行
        bottom_button = qpushbutton("bottom button", self)
        # 设置底部按钮占据第4行的所有列
        layout.addwidget(bottom_button, 4, 0, 1, 4)  # 行4, 列0-3

        self.setlayout(layout)

if __name__ == "__main__":
    app = qapplication(sys.argv)
    window = gridexample()
    window.show()
    sys.exit(app.exec_())

强制子窗口独立

在 pyqt 中,当给窗口(qwidget 或子类)设置 parent 后窗口不显示,通常是因为 子窗口被嵌入到了父窗口的布局中,而非作为独立窗口显示。以下是常见原因和解决方案:

1. 根本原因:parent 的作用

parent 的作用:在 pyqt 中,parent 表示窗口的父控件。若设置 parent

  • 子窗口会嵌入到父窗口中,成为父窗口的一部分(类似按钮、文本框等控件)。
  • 子窗口的生命周期与父窗口绑定(父窗口销毁时,子窗口自动销毁)。
  • 子窗口默认不会作为独立窗口弹出,而是跟随父窗口的布局显示。

关键区别

# 独立窗口(无 parent)
child_window = qwidget()
child_window.show()

# 嵌入父窗口(设置 parent)
child_window = qwidget(parent=main_window)  # 不会独立显示,而是嵌入到 main_window 中

2. 常见场景和解决方法

场景 1:希望子窗口作为独立窗口弹出

错误写法

parent_window = qwidget()
child_window = qwidget(parent=parent_window)  # 设置 parent
child_window.show()  # ❌ 不会显示独立窗口!

原因child_window 已成为 parent_window 的子控件,必须通过父窗口的布局显示(例如将 child_window 添加到父窗口的 qvboxlayout 中)。

解决方法不要设置 parent,让子窗口独立:

parent_window = qwidget()
child_window = qwidget()  # 无 parent
child_window.show()       # ✅ 作为独立窗口显示

场景 2:希望子窗口作为模态对话框弹出

错误写法

parent_window = qwidget()
child_window = qwidget(parent=parent_window)
child_window.setwindowmodality(qt.applicationmodal)  # 设置为模态
child_window.show()  # ❌ 仍然不显示!

原因child_windowparent_window 的子控件,必须通过父窗口布局显示,或明确设置为独立窗口。

解决方法:使用 qt.window 标志强制子窗口成为独立窗口:

child_window = qwidget(parent=parent_window)
child_window.setwindowflags(qt.window)  # 关键:强制为独立窗口
child_window.setwindowmodality(qt.applicationmodal)
child_window.show()  # ✅ 作为模态对话框弹出

场景 3:子窗口被正确添加到父窗口布局但仍不显示

错误写法

parent_window = qwidget()
child_window = qwidget(parent=parent_window)
parent_window.show()  # ❌ 只显示 parent_window,但 child_window 未添加到布局中

原因child_window 需要被添加到父窗口的布局管理器(如 qvboxlayout),或手动设置其位置。

解决方法:将子窗口添加到父窗口布局:

parent_window = qwidget()
layout = qvboxlayout(parent_window)  # 父窗口设置布局
child_window = qwidget()
layout.addwidget(child_window)       # 添加到布局
parent_window.show()  # ✅ 父窗口和子控件均显示

3. 通用检查列表

如果子窗口不显示,按以下步骤排查:

.是否设置 parent

若设置 parent,子窗口需要添加到父窗口的布局中。

.父窗口是否已显示

父窗口调用 show() 后,子控件才会显示。

.窗口标志是否正确

使用 setwindowflags(qt.window) 强制子窗口独立。

.布局是否正确

确保子窗口被添加到父窗口的布局管理器(如 addwidget(child))。

.生命周期问题

确保父窗口未被提前销毁(例如在局部作用域中被垃圾回收)。

4. 完整示例对比

示例 1:子窗口嵌入父窗口(正确写法)

from pyqt5.qtwidgets import qwidget, qvboxlayout, qpushbutton, qapplication

app = qapplication([])

# 父窗口
parent = qwidget()
layout = qvboxlayout(parent)

# 子窗口(作为控件嵌入父窗口)
child = qpushbutton("我是子控件", parent=parent)
layout.addwidget(child)

parent.show()
app.exec_()

示例 2:子窗口作为独立窗口(正确写法)

from pyqt5.qtwidgets import qwidget, qapplication

app = qapplication([])

# 父窗口
parent = qwidget()
parent.show()

# 子窗口(独立窗口,无 parent)
child = qwidget()
child.setwindowtitle("我是独立子窗口")
child.show()

app.exec_()

5. 特殊场景:动态创建子窗口

若通过按钮点击动态创建子窗口,需确保子窗口的引用不被销毁:

from pyqt5.qtwidgets import qwidget, qpushbutton, qvboxlayout, qapplication

app = qapplication([])

class mainwindow(qwidget):
    def __init__(self):
        super().__init__()
        self.button = qpushbutton("打开子窗口", self)
        self.button.clicked.connect(self.open_child)
        self.setlayout(qvboxlayout())
        self.layout().addwidget(self.button)

    def open_child(self):
        self.child = qwidget()  # 必须保存为成员变量,否则会被垃圾回收!
        self.child.setwindowtitle("子窗口")
        self.child.show()

window = mainwindow()
window.show()
app.exec_()

通过理解 parent 的作用和布局机制,可以灵活控制窗口的显示方式。

模型设计

每一个待办事项有

  • 标题
  • 描述信息
  • 生成时间
  • 是否完成标识
  • 截止时间
class todoitem:
    def __init__(self, title, description,deadline_time=none,is_completed=false):
        self.title = title
        self.description = description
        self.deadline_time = deadline_time
        self.is_completed = false

自定义信号

from pyqt5.qtwidgets import qapplication, qwidget, qpushbutton, qvboxlayout, qmessagebox
from pyqt5.qtcore import pyqtsignal
import sys

class mywidget(qwidget):
    # 定义一个自定义信号
    custom_signal = pyqtsignal(str)

    def __init__(self):
        super().__init__()
        self.init_ui()

    def init_ui(self):
        self.setwindowtitle("pyqt custom signal example")
        self.setgeometry(100, 100, 300, 200)

        # 创建一个按钮
        self.button = qpushbutton("click me", self)
        self.button.clicked.connect(self.emit_custom_signal)

        # 设置布局
        layout = qvboxlayout()
        layout.addwidget(self.button)
        self.setlayout(layout)

        # 连接自定义信号到槽
        self.custom_signal.connect(self.handle_custom_signal)

    def emit_custom_signal(self):
        """发射自定义信号"""
        self.custom_signal.emit("hello from custom signal!")

    def handle_custom_signal(self, message):
        """处理自定义信号"""
        qmessagebox.information(self, "custom signal", message)

if __name__ == "__main__":
    app = qapplication(sys.argv)

    widget = mywidget()
    widget.show()

    sys.exit(app.exec_())

批量导入功能

使用json格式的字符串进行批量导入,大致格式如下

{
    "items": [
        {
            "title": "测试标题1",
            "description": "测试1",
            "deadline_time": "2024",
            "is_completed": false
        },
        {
            "title": "测试标题2",
            "description": "测试2",
            "deadline_time": "2025",
            "is_completed": true
        }
    ]
}

大致就是新开一个窗口,创建一个qtextedit输入对应的json数据,然后通过json.loads()方法解析对应数据,
逐个使用add_item()接口添加,这要求add_item()能够处理多种情况:按钮点击触发无需参数批量导入中需要传递参数

而在python中实现类似重载的效果可以给参数一个默认值none,再在函数内部分情况处理

class importwidget(qwidget):
    # 自定义信号
    import_finished = pyqtsignal(dict)
    def __init__(self,parent):
        super().__init__(parent)
        self.setfixedsize = (500,500)
        self.setwindowflags(qt.window)  # 关键:强制为独立窗口
        self.input_field = qtextedit()
        self.main_layout = qvboxlayout()
        self.btn_layout = qhboxlayout()
        self.confirm_button = qpushbutton("导入")
        self.cancel_button = qpushbutton("取消")
        self.btn_layout.addwidget(self.confirm_button)
        self.btn_layout.addwidget(self.cancel_button)

        self.confirm_button.clicked.connect(self.read_json_data)
        # 连接自定义信号到槽
        self.import_finished.connect(self.close)

        self.main_layout.addlayout(self.btn_layout)
        self.main_layout.addwidget(self.input_field)
        self.setlayout(self.main_layout)

    def read_json_data(self):
        text = self.input_field.toplaintext()  # 获取输入框的文本
        # print(f"原始文本内容: {text}")  # 调试:打印原始文本内容
        try:
            # 将输入的文本解析为 json 数据
            json_data = json.loads(text.strip())  # 使用 strip() 去除首尾空白字符
            # print(f"解析后的 json 数据: {json_data}")
            self.json_data = json_data   
            self.import_finished.emit(json_data)
        except json.jsondecodeerror as e:
            # 如果 json 格式不正确,打印错误信息
            print(f"json 解析失败: {e}")
            self.json_data =  none
class todoapp(qwidget):
    def batch_import(self,json_data):
        print(json_data['items'])
        items = json_data['items']
        for item in items:
            self.add_item(item['title'],item['description'])
        
    def add_item(self, checked,title=none, description=none):
        # 如果 title 和 description 是传入的参数
        if title is not none or description is not none:
            # 使用传入的参数
            title = title.strip() if title else ""
            description = description.strip() if description else ""
        else:
            # 获取输入框的文本
            title = self.title_input.text().strip()
            print(title, description)
            description = self.description_input.text().strip()
        # todo 优化时间显示居右
        current_time = datetime.datetime.now().strftime("%y-%m-%d %h:%m:%s")
        # 创建 todoitem 实例
        todo_item = todoitem(title, description, current_time)

        # 创建新的列表项  创建自定义widget
        item_widget = qwidget()
        layout = qhboxlayout()

        # 标题部分
        title_label = qlabel(todo_item.title)
        title_label.setstylesheet("qlabel{padding:0px}")
        title_label.setalignment(qt.alignmentflag.alignleft| qt.alignmentflag.alignvcenter)

        # 时间部分
        time_label = qlabel(todo_item.created_time)
        time_label.setstylesheet("qlabel{padding:0px}") # 添加padding设置,qlabel有默认padding,不设置话,会将文字截断
        time_label.setalignment(qt.alignmentflag.alignright | qt.alignmentflag.alignvcenter)

        # 添加控件到布局
        layout.addwidget(title_label)
        layout.addwidget(time_label)
        item_widget.setlayout(layout)

        # 创建listwidgetitem
        item = qlistwidgetitem()
        item.setsizehint(item_widget.sizehint())  # 设置每一项的宽高
        item.settooltip(todo_item.description) # 设置悬浮提示
        item.setdata(qt.userrole, todo_item)  # 保存任务对象
        item.setflags(item.flags() | qt.itemisselectable | qt.itemisenabled)  
        item.setcheckstate(qt.checkstate.unchecked)
        self.to_do_list.additem(item)
        self.to_do_list.setitemwidget(item, item_widget)
        
        # 清空输入框
        self.title_input.clear()
        self.description_input.clear()

bug解析

使用按钮连接点击信号至槽函数,发现槽函数add_item接收到的title参数不是预期的输入值none(因为点击事件的槽函数一般不带参数),而是false。

1.pyqt 的 clicked 信号默认会传递一个布尔值:

  • qpushbuttonclicked 信号默认会发送一个 checked 参数(表示按钮的选中状态)。
  • 如果你没有显式处理这个参数,它会传递到槽函数中,导致 title 参数被赋值为 false(因为默认未选中)。

2.槽函数定义与信号参数不匹配

你定义的 add_item 方法有两个可选参数:

def add_item(self, title=none, description=none):

当通过 self.add_button.clicked.connect(self.add_item) 连接信号时,clicked 信号的 checked 参数(布尔值)会传递给 title 参数。

因此,点击按钮时 title 实际接收到的是 false,而不是预期的 none

方法 1:显式接收并忽略 checked 参数

修改槽函数,增加一个参数接收 checked 值,但不在内部使用它:

def add_item(self, checked, title=none, description=none):  # 增加 checked 参数
    # 如果 title 和 description 是传入的参数
    if title is not none or description is not none:
        print("not null", title, description)
        title = title.strip() if title else ""
        description = description.strip() if description else ""
    else:
        # 获取输入框的文本
        title = self.title_input.text().strip()
        description = self.description_input.text().strip()
    # 其他逻辑...

方法 2:使用 lambda 阻止参数传递

在连接信号时,通过 lambda 屏蔽 clicked 信号的参数:

self.add_button.clicked.connect(lambda: self.add_item())  # 不传递任何参数

此时 titledescription 将保持 none,代码会从输入框中读取值。

关键点解释

信号参数传递机制

  • clicked 信号默认发送 checked(布尔值),而 qpushbutton 默认不可选中,因此总是发送 false
  • 如果槽函数参数数量不匹配,第一个参数会接收这个 false

参数优先级问题

  • 如果调用 add_item 时传递了参数(如 add_item(title="测试")),title 会被正确赋值。
  • 若未传递参数,title 会被错误地赋值为 false(来自 checked 参数)。 

导出

既然有批量导入功能,就有导出功能

剪切板 qclipboard

在 pyqt 中,可以使用 qapplication.clipboard() 来访问系统剪贴板,并通过 qclipboard 类的方法将数据复制到剪贴板

def export_to_clipboard(self):
        # 获取所有任务
        items = []
        for i in range(self.to_do_list.count()):
            item = self.to_do_list.item(i)
            if item:
                todo_item = item.data(qt.userrole)
                items.append({
                    "title": todo_item.title,
                    "description": todo_item.description,
                    "deadline_time": todo_item.deadline_time,
                    "is_completed": todo_item.is_completed
                })
        # 转换为 json 格式
        json_data = {
            "items": items
        }
        json_str = json.dumps(json_data, indent=4, ensure_ascii=false)  # 格式化 json 字符串
        # 复制到剪切板
        clipboard = qapplication.clipboard()
        clipboard.settext(json_str)
        # 弹出提示
        qmessagebox.information(self, "提示", "已复制到剪切板")

常用的 qclipboard 方法

  • settext(text): 将文本复制到剪贴板。
  • setpixmap(pixmap): 将图片复制到剪贴板。
  • setmimedata(mimedata): 将 mime 数据(如 html)复制到剪贴板。
  • clear(): 清除剪贴板内容。

持久化存储

  • 数据库sqlite
  • 文件保存

直接写入文件,不使用数据库了,重写关闭事件,保存代办到文件,并在初始化的时候读取文件

    def init_from_file(self, file_path=none):
        # 默认初始化文件为当前目录下的 to_do.json
        if file_path is none:
            file_path = "./to_do.json"
            # 读取文件内容
        with open(file_path, "r", encoding="utf-8") as f:
            text = f.read()
            self.batch_import(json.loads(text))

    def closeevent(self, event):
        # 关闭窗口时保存数据
        with open("./to_do.json", "w", encoding="utf-8") as f:
            self.export_to_clipboard(true)
            f.write(qapplication.clipboard().text())
            qapplication.clipboard().clear()
        event.accept()

排序功能

截止时间ddl排序

def sort_by_ddl(self):
        if self.sort_value == "asc":
            self.sort_value = "desc"
        else:
            self.sort_value = "asc"
        # 按 ddl 排序
        items = []
        for i in range(self.to_do_list.count()):
            item = self.to_do_list.item(i)
            if item:
                todo_item = item.data(qt.userrole)
                items.append(todo_item)
        # 根据self.sort_value决定排序方向
        if self.sort_value == "asc":
            items.sort(key=self.sort_key)
        else:
            items.sort(key=self.sort_key, reverse=true)
        # 清空列表
        self.to_do_list.clear()
        # 重新添加排序后的任务
        for item in items:
            self.add_item(item.title, item.description, item.deadline_time, item.is_completed)
    
    def sort_key(self, item):
        item.deadline_time.replace(":",":")
        if item.deadline_time == "未知":
            return datetime.datetime.max
        else:
            return datetime.datetime.strptime(item.deadline_time.replace(":",":"), "%y-%m-%d %h:%m")

自定义排序规则

在python中自定义排序规则,你可以使用内置的sorted()函数或者列表对象的sort()方法,并通过key参数指定一个函数来定义排序规则。这个函数会对每个元素进行处理,并返回一个值,排序将根据这个返回值进行。

按字符串长度排序:

strings = ["apple", "banana", "cherry", "date"]
sorted_strings = sorted(strings, key=len)
print(sorted_strings)  # 输出: ['date', 'apple', 'banana', 'cherry']

使用lambda函数按字符串的最后一个字符排序:

strings = ["apple", "banana", "cherry", "date"]
sorted_strings = sorted(strings, key=lambda x: x[-1])
print(sorted_strings)  # 输出: ['banana', 'apple', 'date', 'cherry']

复杂排序规则,先按字符串长度排序,再按字母顺序排序:

strings = ["apple", "banana", "cherry", "date"]
sorted_strings = sorted(strings, key=lambda x: (len(x), x))
print(sorted_strings)  # 输出: ['date', 'apple', 'banana', 'cherry']

使用cmp_to_key将传统比较函数转换为key函数:

from functools import cmp_to_key

def compare(x, y):
    if x < y:
        return -1
    elif x > y:
        return 1
    else:
        return 0

numbers = [3, 2, 5, 4, 1]
sorted_numbers = sorted(numbers, key=cmp_to_key(compare))
print(sorted_numbers)  # 输出: [1, 2, 3, 4, 5]

优化条目显示

添加一个标题布局,显示列表的标题 => 放一个水平布局在qlistwidget上对齐就可以

分离显示与数据(qlistwidget):

  • 不再直接使用 qlistwidgetitem(text),而是通过 setitemwidget 绑定自定义widget
  • 数据仍存储在 todoitem 对象中,界面仅负责展示

自定义widget布局控制:

  • 使用 qhboxlayout 实现水平分列
  • setalignment 控制对齐方向
  • setcontentsmargins 调整内容间距

bug解析

文字出现了上下截断的情况,尝试过设置延伸策略,给item设置固定宽高都不能根治

发现随着高度的变大,显示的内容越来越多,所以猜测是qlabel有默认的padding,所以截断了文字

最后设置qstylesheet成功解决

# todo 优化时间显示居右
# 创建 todoitem 实例
todo_item = todoitem(title, description,deadline_time,is_completed)
# 创建新的列表项  创建自定义widget
item_widget = qwidget()
layout = qhboxlayout()

# 标题部分
title_label = qlabel(todo_item.title)
title_label.setstylesheet("qlabel{padding:0px}")
title_label.setalignment(qt.alignmentflag.alignleft| qt.alignmentflag.alignvcenter)

# 时间部分
time_label = qlabel(todo_item.deadline_time)
time_label.setstylesheet("qlabel{padding:0px}") # 添加padding设置,qlabel有默认padding,不设置话,会将文字截断
time_label.setalignment(qt.alignmentflag.alignright | qt.alignmentflag.alignvcenter)

# 添加控件到布局
layout.addwidget(title_label)
layout.addwidget(time_label)
item_widget.setlayout(layout)

# 创建listwidgetitem
item = qlistwidgetitem()
item.setsizehint(item_widget.sizehint())  # 设置每一项的宽高
item.settooltip(todo_item.description) # 设置悬浮提示
item.setdata(qt.userrole, todo_item)  # 保存任务对象
item.setflags(item.flags() | qt.itemisselectable | qt.itemisenabled |qt.itemisusercheckable)
if todo_item.is_completed:
    item.setcheckstate(qt.checkstate.checked)  
else:
    item.setcheckstate(qt.checkstate.unchecked)
    self.to_do_list.additem(item)
    self.to_do_list.setitemwidget(item, item_widget)

    # 清空输入框
    self.title_input.clear()
    self.description_input.clear()
    self.deadline_input.clear()

绑定自定义widget后,点击无法改变itemcheckstate

解决方法有很多种,这里采用连接父listwidget的双击信号

self.to_do_list.doubleclicked.connect(self.on_double_clicked)

def on_double_clicked(self, index: qmodelindex):
    print(index.row())  # 打印行号
    print(index.column())  # 打印列号(通常为 0)
    item = self.to_do_list.itemfromindex(index)  # 获取 qlistwidgetitem
    if item.checkstate() == qt.checkstate.unchecked:
        item.setcheckstate(qt.checkstate.checked)
    elif item.checkstate() == qt.checkstate.checked :
        item.setcheckstate(qt.checkstate.unchecked)
    print(item.text())  # 打印项的文本

最终代码

https://github.com/0zxm/todoapp/tree/master

以上就是使用pyqt编写一个简单的待办程序的详细内容,更多关于pyqt待办程序的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com