学生成绩管理系统 ——grade.py年级修改、student.py学生信息管理、result.py学生成绩管理、

哈哈、、
年级设置界面

image

 隐藏表格垂直序号

设置垂直标题即隐藏左侧123序号。

image

 

年级设置模块

image

 数据库建表语句

学生信息管理系统附带的数据库建表语句

/*
Navicat MySQL Data Transfer

Source Server         : mr
Source Server Version : 80019
Source Host           : 127.0.0.1:3306
Source Database       : db_student

Target Server Type    : MYSQL
Target Server Version : 80019
File Encoding         : 65001

Date: 2020-04-21 13:54:22
*/

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for `tb_class`
-- ----------------------------
DROP TABLE IF EXISTS `tb_class`;
CREATE TABLE `tb_class` (
  `classID` int NOT NULL,
  `gradeID` int NOT NULL,
  `className` varchar(20) DEFAULT NULL,
  PRIMARY KEY (`classID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of tb_class
-- ----------------------------
INSERT INTO `tb_class` VALUES ('1', '1', '一班');
INSERT INTO `tb_class` VALUES ('2', '1', '二班');
INSERT INTO `tb_class` VALUES ('3', '1', '三班');
INSERT INTO `tb_class` VALUES ('4', '2', '一班');
INSERT INTO `tb_class` VALUES ('5', '2', '二班');

-- ----------------------------
-- Table structure for `tb_examkinds`
-- ----------------------------
DROP TABLE IF EXISTS `tb_examkinds`;
CREATE TABLE `tb_examkinds` (
  `kindID` int NOT NULL,
  `kindName` varchar(40) DEFAULT NULL,
  PRIMARY KEY (`kindID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of tb_examkinds
-- ----------------------------
INSERT INTO `tb_examkinds` VALUES ('1', '期中考试');
INSERT INTO `tb_examkinds` VALUES ('2', '期末考试');

-- ----------------------------
-- Table structure for `tb_grade`
-- ----------------------------
DROP TABLE IF EXISTS `tb_grade`;
CREATE TABLE `tb_grade` (
  `gradeID` int NOT NULL DEFAULT '1',
  `gradeName` varchar(20) DEFAULT NULL,
  PRIMARY KEY (`gradeID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of tb_grade
-- ----------------------------
INSERT INTO `tb_grade` VALUES ('1', '初一');
INSERT INTO `tb_grade` VALUES ('2', '初二');
INSERT INTO `tb_grade` VALUES ('3', '初三');

-- ----------------------------
-- Table structure for `tb_result`
-- ----------------------------
DROP TABLE IF EXISTS `tb_result`;
CREATE TABLE `tb_result` (
  `ID` int NOT NULL AUTO_INCREMENT,
  `stuID` varchar(20) DEFAULT NULL,
  `kindID` int DEFAULT NULL,
  `subID` int DEFAULT NULL,
  `result` double DEFAULT '0',
  PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of tb_result
-- ----------------------------
INSERT INTO `tb_result` VALUES ('1', 'BS0101001', '1', '1', '80');
INSERT INTO `tb_result` VALUES ('2', 'BS0101001', '1', '2', '85');
INSERT INTO `tb_result` VALUES ('3', 'BS0101001', '1', '3', '100');
INSERT INTO `tb_result` VALUES ('4', 'BS0101002', '1', '3', '100');
INSERT INTO `tb_result` VALUES ('5', 'BS0101002', '1', '1', '90');
INSERT INTO `tb_result` VALUES ('6', 'BS0101002', '1', '2', '98');

-- ----------------------------
-- Table structure for `tb_student`
-- ----------------------------
DROP TABLE IF EXISTS `tb_student`;
CREATE TABLE `tb_student` (
  `stuID` varchar(20) NOT NULL DEFAULT 'SID00101001',
  `stuName` varchar(20) DEFAULT NULL,
  `classID` int DEFAULT NULL,
  `gradeID` int DEFAULT NULL,
  `age` int DEFAULT NULL,
  `sex` char(4) DEFAULT NULL,
  `phone` char(20) DEFAULT NULL,
  `address` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`stuID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of tb_student
-- ----------------------------
INSERT INTO `tb_student` VALUES ('BS0101001', '小王', '1', '1', '20', '', '13610780204', '北京市朝阳区');
INSERT INTO `tb_student` VALUES ('BS0101002', '小科', '1', '1', '21', '', '1300000000', '山西省长治市');
INSERT INTO `tb_student` VALUES ('BS0102001', '小科', '2', '1', '21', '', '1300000000', '山西省长治市');
INSERT INTO `tb_student` VALUES ('BS0201001', '王子', '4', '2', '19', '', '15500000000', '吉林省长春市');

-- ----------------------------
-- Table structure for `tb_subject`
-- ----------------------------
DROP TABLE IF EXISTS `tb_subject`;
CREATE TABLE `tb_subject` (
  `subID` int NOT NULL,
  `subName` varchar(50) DEFAULT NULL,
  PRIMARY KEY (`subID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of tb_subject
-- ----------------------------
INSERT INTO `tb_subject` VALUES ('1', '数学');
INSERT INTO `tb_subject` VALUES ('2', '语文');
INSERT INTO `tb_subject` VALUES ('3', '编程');

-- ----------------------------
-- Table structure for `tb_user`
-- ----------------------------
DROP TABLE IF EXISTS `tb_user`;
CREATE TABLE `tb_user` (
  `userName` varchar(20) NOT NULL,
  `userPwd` varchar(50) DEFAULT NULL,
  PRIMARY KEY (`userName`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of tb_user
-- ----------------------------
INSERT INTO `tb_user` VALUES ('mr', 'mrsoft');
INSERT INTO `tb_user` VALUES ('小科', '111');

-- ----------------------------
-- View structure for `v_classinfo`
-- ----------------------------
DROP VIEW IF EXISTS `v_classinfo`;
CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v_classinfo` AS select `tb_class`.`classID` AS `classID`,`tb_grade`.`gradeID` AS `gradeID`,`tb_grade`.`gradeName` AS `gradeName`,`tb_class`.`className` AS `className` from (`tb_class` join `tb_grade`) where (`tb_class`.`gradeID` = `tb_grade`.`gradeID`) ;

-- ----------------------------
-- View structure for `v_studentinfo`
-- ----------------------------
DROP VIEW IF EXISTS `v_studentinfo`;
CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v_studentinfo` AS select `tb_student`.`stuID` AS `stuID`,`tb_student`.`stuName` AS `stuName`,`tb_student`.`age` AS `age`,`tb_student`.`sex` AS `sex`,`tb_student`.`phone` AS `phone`,`tb_student`.`address` AS `address`,`tb_class`.`className` AS `className`,`tb_grade`.`gradeName` AS `gradeName` from ((`tb_student` join `tb_class`) join `tb_grade`) where ((`tb_student`.`classID` = `tb_class`.`classID`) and (`tb_student`.`gradeID` = `tb_grade`.`gradeID`)) ;

-- ----------------------------
-- View structure for `v_resultinfo`
-- ----------------------------
DROP VIEW IF EXISTS `v_resultinfo`;
CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v_resultinfo` AS select `tb_result`.`ID` AS `ID`,`tb_result`.`stuID` AS `stuID`,`v_studentinfo`.`stuName` AS `stuName`,`tb_examkinds`.`kindName` AS `kindName`,`tb_subject`.`subName` AS `subName`,`v_studentinfo`.`className` AS `className`,`v_studentinfo`.`gradeName` AS `gradeName`,`tb_result`.`result` AS `result` from (((`tb_subject` join `tb_result`) join `tb_examkinds`) join `v_studentinfo`) where ((`tb_result`.`stuID` = `v_studentinfo`.`stuID`) and (`tb_result`.`kindID` = `tb_examkinds`.`kindID`) and (`tb_result`.`subID` = `tb_subject`.`subID`)) ;

组件取名,见名知意的问题

可改进的地方,组件取名,见名知意的问题。

在creator右侧给组件改名后,再生成py文件。

image

image

 

 性别多选框添加男和女两个选项

image

 

image

 tuple类型怎么能赋值给select语句了呢

看下边tuple在sql语句中正常查询成功了。

 查询返回值

 

image

 

image

 

image

 

连接槽函数的时候不能add(),为什么

 

 

image

 学生成绩管理模块

image

 kindName后边用了中文逗号

image

 错误:Unknown column 'kindName,subName' in 'field list',因为kindName后边用了中文逗号

把成绩记录的id也作为一列查询出来,展示在表格里

image

 在成绩记录tableWiget里,选中编号后,把该条记录填充考试类别,年级,班级,姓名,科目,成绩。选中的编号作为在v_resultinfo里的编号,也插入到tableWidget里作为一列。

image

 为什么要str(result) 

从数据库查出来的有int,float

(1, 'BS0101001', '小王', '初一一班', '数学', '期中考试', 98.0)

<class 'int'>

1
<class 'str'>
BS0101001
<class 'str'>
小王
<class 'str'>
初一一班
<class 'str'>
数学
<class 'str'>
期中考试
<class 'float'>
98.0

image

 

第一次打开表格时多选框的默认值

image

 第一次打开时,考试类别多选框已经有了“所有”,“期中考试”,“期末考试”,默认显示了第一个“所有”;年级也是同理;班级和年级联动,年级没选,他现在为空;学生姓名和班级联动,也为空;

为什么我用distinct,他没有用distinct

因为他是从v_studentinfo查的,我从v_resultinfo查的。

从哪个里边查好呢?从初一一班中查出所有的同学姓名,从v_studentinfo里查好。

bindName函数:
result = service.query("select distinct stuName from v_resultinfo where gradeName = %s and className = %s", curGrade,curClass)
result = service.query("select stuName from v_studentinfo where gradeName=%s and className=%s",
                               self.cboxGrade.currentText(), self.cboxClass.currentText())

写一个python测试sql各种返回值,错误

写一个python测试sql各种返回值,错误的测试程序。sql语句执行分几种情况?

select参数多加了图中黄色括号

导致学生姓名查不出来的原因,多加了图中黄色括号。【不去掉括号,只在curClass后边加一个逗号也出错】

image

 下边是我写的:

增  result = service.exec("insert into tb_result(stuID,kindID,subID,result) values (%s,%s,%s,%s)",(stuID, kindID, subID, score))

删  result = service.exec("DELETE FROM tb_result WHERE id = %s",id)
改  result = service.exec("UPDATE tb_result SET result = %s WHERE id = %s",(edited_score,self.select))
查  
result = service.query("SELECT ID,stuID,stuName,CONCAT(gradeName,className),subName,kindName,result FROM v_resultinfo WHERE 
gradeName = %s AND className = %s AND kindName = %s",curGrade,curClass,curExamKind)

实例写的,【不管几个参数,都括起来写】。【并不是,他也写的比较乱。】

 result = service.exec("delete from tb_result where ID= %s", (self.select,))

 

为什么我用result【0】【0】,他用result[0]

因为result【0】作为一个tuple,作为参数在sql语句中仍然正常查询成功了。

image

 

     subname = "语文"
        result = service.query("select subID from tb_subject where subName=%s", subname)
        print(result)  # 输出结果:((2,),)
        subID = result[0]
        print(subID)  # 输出结果:(2,) 用这个元组去sql语句查询,仍查出来了
        result = service.query("select subName from tb_subject where subID=%s",subID)
        print(result) # 输出结果:(('语文',),)

 

python等号的判断:

java有讲过,判断地址,判断内容,equals

image

 

image

 

type edit_score <class 'str'>
type result[0][0]<class 'float'>

修改成绩,和原来一样会显示修改成功

修改成绩,和原来一样会显示修改成功,result = service.exec("UPDATE tb_result SET result = %s WHERE id = %s",(edited_score,self.select)),result等于1

在sqlyog中不是1

image

 抛异常的使用

  def edit(self):
        try:
            if self.select != "":  # 判断是否选择了要修改的数据
                ID = self.select  # 记录要修改的编号
                score = self.editResult.text()  # 记录成绩
                # 执行修改操作
                result = service.exec("update tb_result set result=%s where ID=%s", (score, ID))
                if result > 0:  # 如果结果大于0,说明修改成功
                    self.query()  # 在表格中显示最新数据
                    QMessageBox.information(None, '提示', '信息修改成功!', QMessageBox.Ok)
        except:
            QMessageBox.warning(None, '警告', '请先选择要修改的数据!', QMessageBox.Ok)

我的写法。self.select是在getItem中定义的,如果不点击一列,直接点击修改,程序崩溃。因为没有调用getItem,self.select不存在

    def edit(self):
        # 一种方式:是否点击了第一列item
        # 第二种方式:各个框的currenttext是否符合规范
        # 应该用第一种方式
        # 选中了就只能改成绩这一项,修改tb_result表(stuID, kindID, subID, score)
        if self.select != "":
            # 从v_resultinfo中获取了记录的id,这个id和tb_result表里的id是一样的
            # 获取成绩

            edited_score = self.lineEdit_score.text()
            # 根据id从v_resultinfo查出考试类别,年级,班级,姓名,科目与currentTtext比较,不能改,成绩不能为空,不能和原先一样
            # 这个比较没有写,也没有判空,和原来一样的成绩会修改成功


            result = service.exec("UPDATE tb_result SET result = %s WHERE id = %s",(edited_score,self.select))
            print("修改成功,%s",result)
            if result > 0:
                QMessageBox.information(None,"提示","信息修改成功",QMessageBox.Ok)
                self.query()
        else:
            QMessageBox.information(None, "提示", "请选择一条记录", QMessageBox.Ok)

getItem函数在哪里调用的,item参数谁赋值的?

从信号与槽函数理解。

def getItem(self, item):
self.tbResult.itemClicked.connect(self.getItem)
# 获取选中的单元格数据

 itemClickedQTableWidget 的信号处理函数声明

Qt 框架中 QTableWidget 的信号处理函数声明。在 Qt 框架中,itemClicked 是 QTableWidget 类的一个信号(signal),而非普通成员函数。信号的实现是由 Qt 框架内部完成的(通常在 C++ 层面),并不需要开发者自己实现,也不会暴露在 Python 绑定的代码中。

    def itemClicked(self, item): # real signature unknown; restored from __doc__
        """ itemClicked(self, item: QTableWidgetItem) [signal] """
        pass
在 Qt 中,itemClicked 是 QTableWidget 的一个信号,当用户点击表格中的项目时会触发这个信号。代码中的注释表明这是一个信号([signal]),参数是一个 QTableWidgetItem 对象,表示被点击的表格项。通常,你需要将这个信号连接到一个槽函数来处理点击事件
self.table.itemClicked.connect(self.handle_item_click)

def handle_item_click(self, item):
    # 处理点击事件的逻辑
    print(f"点击了单元格: 行 {item.row()}, 列 {item.column()}")
    print(f"单元格内容: {item.text()}")
呃呃

real signature unknown; restored from __doc__

Qt 框架本身是用 C++ 编写的,而 PyQt/PySide 等工具会将 C++ 代码 “翻译” 成 Python 可调用的接口。但由于 C++ 和 Python 的底层机制不同:
 
  • C++ 的函数签名(参数类型、返回值等)无法被 Python 直接识别。
  • 绑定工具会从 C++ 代码的文档(注释)中提取这些信息,生成一个 “模拟” 的 Python 函数签名,并存放在函数的 __doc__ 属性中。
  • 最终在 Python 中显示的函数签名,就是从这个 __doc__ 里 “恢复” 出来的。

关闭按钮MainWindow.close

 

MainWindow是什么?close函数哪里来的

 self.pushButton_exit.clicked.connect(MainWindow.close)

 

为什么返回值是类似矩阵的嵌套元组

查询初一一班的所有同学,有两人,小王和小科。

(('小王',), ('小科',))

一个最简洁的qt程序

一个简洁的qt程序,可以直接运行的

import sys
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout,
                             QGridLayout, QPushButton, QLineEdit)
from PyQt5.QtCore import Qt


class Calculator(QMainWindow):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        # 设置窗口标题和大小
        self.setWindowTitle('简易计算器')
        self.setGeometry(300, 300, 300, 400)

        # 创建中央部件和布局
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        main_layout = QVBoxLayout(central_widget)

        # 创建显示框
        self.display = QLineEdit()
        self.display.setAlignment(Qt.AlignRight)
        self.display.setReadOnly(True)
        self.display.setStyleSheet("font-size: 24px; padding: 10px;")
        main_layout.addWidget(self.display)

        # 创建按钮布局
        button_layout = QGridLayout()

        # 按钮文本和位置
        buttons = [
            ('7', 0, 0), ('8', 0, 1), ('9', 0, 2), ('/', 0, 3),
            ('4', 1, 0), ('5', 1, 1), ('6', 1, 2), ('*', 1, 3),
            ('1', 2, 0), ('2', 2, 1), ('3', 2, 2), ('-', 2, 3),
            ('0', 3, 0), ('.', 3, 1), ('=', 3, 2), ('+', 3, 3),
            ('C', 4, 0), ('', 4, 1)
        ]

        # 创建按钮并添加到布局
        for text, row, col in buttons:
            button = QPushButton(text)
            button.setStyleSheet("font-size: 18px; padding: 15px;")
            button.clicked.connect(lambda checked, t=text: self.on_button_click(t))
            button_layout.addWidget(button, row, col)

        main_layout.addLayout(button_layout)

        # 显示窗口
        self.show()

    def on_button_click(self, text):
        """处理按钮点击事件"""
        if text == '=':
            try:
                # 计算表达式结果
                result = str(eval(self.display.text()))
                self.display.setText(result)
            except Exception as e:
                self.display.setText("错误")
        elif text == 'C':
            # 清除显示
            self.display.clear()
        elif text == '':
            # 删除最后一个字符
            current = self.display.text()
            self.display.setText(current[:-1])
        else:
            # 添加数字或运算符
            self.display.setText(self.display.text() + text)


if __name__ == '__main__':
    # 创建应用实例
    app = QApplication(sys.argv)
    # 创建并显示计算器窗口
    calculator = Calculator()
    # 进入应用主循环
    sys.exit(app.exec_())

central_widget = QWidget()中央部件

# 创建中央部件和布局
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        main_layout = QVBoxLayout(central_widget)

 

这段代码是 Qt 中用于设置窗口内部布局和内容的核心步骤,主要作用是:
 
  1. 创建中央部件(central_widget = QWidget()
     
    Qt 的 QMainWindow(主窗口)有固定的结构(标题栏、菜单栏、工具栏等),其中专门用于放置用户自定义内容的区域需要通过「中央部件」来实现。
     
    这里创建了一个基础的 QWidget 作为中央部件,后续所有的按钮、文本框等控件都会放在这个部件上。
  2. 设置中央部件(self.setCentralWidget(central_widget)
     
    通过这个方法将上面创建的 central_widget 绑定到主窗口,告诉主窗口:「这个部件是我要显示的主要内容区域」。
     
    QMainWindow 要求必须设置中央部件,否则内容无法显示
  3. 创建布局管理器(main_layout = QVBoxLayout(central_widget)
     
    布局管理器用于自动排列部件中的子控件(如按钮、输入框等)。
     
    这里创建的 QVBoxLayout 是「垂直布局」,意味着后续添加的控件会从上到下依次排列。
     
    括号中的 central_widget 表示这个布局要应用到中央部件上。

简单说:

这三行代码的目的是给主窗口「搭好舞台」:
 
  • 先创建一个「舞台」(central_widget
  • 告诉主窗口「这个舞台要用」(setCentralWidget
  • 规定舞台上的元素要「垂直排列」(QVBoxLayout
 
之后就可以往这个布局里添加按钮、文本框等控件,它们会自动按照垂直方向排列,不需要手动计算每个控件的位置。
 

main函数

这部分代码是 Qt 应用程序的启动和运行核心,负责初始化应用、创建窗口并启动事件循环,具体作用如下:
 
  1. app = QApplication(sys.argv)
    • 创建 Qt 应用程序的核心实例 QApplication,这是所有 Qt 程序的起点。
    • sys.argv 是命令行参数列表,Qt 需要它来处理一些系统级别的配置(比如窗口样式、命令行参数传递等)。
    • 一个 Qt 程序必须有且仅有一个 QApplication 实例
  2. calculator = Calculator()
    • 创建自定义窗口实例(这里是之前定义的 Calculator 类,继承自 QMainWindow)。
    • 这行代码会触发窗口的初始化(调用 __init__ 方法),完成窗口标题、大小、控件布局等设置。
    • 如果你的窗口类中包含 show() 方法(如之前的计算器示例),此时窗口会被显示出来。
  3. sys.exit(app.exec_())
    • app.exec_() 启动 Qt 的事件循环(Event Loop),这是 Qt 程序运行的核心机制。
       
      事件循环会持续监听用户操作(如点击按钮、移动鼠标、关闭窗口等),并将这些操作分发给对应的处理函数。
    • sys.exit() 确保程序退出时能正确清理资源,返回合适的退出状态码。
    • 当用户关闭窗口时,事件循环会结束,app.exec_() 返回退出码,程序正常终止。

简单总结:

这三行代码构成了 Qt 程序的「生命周期骨架」:
 
  • 先初始化应用(QApplication
  • 再创建并显示窗口(Calculator()
  • 最后启动事件循环,让程序「活起来」,能够响应用户操作(app.exec_()

qtdesigner生成的代码结构

image

 运行效果

image

 

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file '原始Mainwindow.ui'
#
# Created by: PyQt5 UI code generator 5.15.9
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again.  Do not edit this file unless you know what you are doing.


from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(800, 600)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 23))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))


# 书里附带的启动代码,这里边有哪些是冗余的呢?  
import sys
# 主方法,程序从此处启动PyQt设计的窗体
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
app.setStyle("Fusion") # 设置窗口风格
MainWindow = QtWidgets.QMainWindow() # 创建窗体对象
ui = Ui_MainWindow() # 自己写的的主窗体类
ui.setupUi(MainWindow) # 调用主窗体类里的方法对窗体对象进行初始化设置
MainWindow.show() # 显示窗体
sys.exit(app.exec_()) # 程序关闭时退出进程

上述代码解析:

  1. 类定义 My_Ui_MainWindow
    • 这是从 .ui 文件生成的界面类,包含了 setupUi 和 retranslateUi 两个核心方法
    • setupUi负责初始化窗口的各种属性和部件(设置窗口大小、创建中央部件、菜单栏、状态栏等)
    • retranslateUi:用于支持界面国际化,处理文本翻译(这里主要设置了窗口标题)
  2. 主程序入口
    • 创建了 QApplication 实例(应用程序核心)
    • 创建了 QMainWindow 实例(主窗口对象)
    • 通过 ui.setupUi(MainWindow) 将界面设置应用到主窗口
    • 显示窗口并启动事件循环

界面和业务代码分离

这种结构通常建议作为界面模板,业务逻辑应写在其他文件中

对于qtdesigner自动生成的文件结构,如果需要添加功能,建议创建一个新的类继承自 QMainWindow 和这个界面类,而不是直接修改此文件

书4.5节展示的分离代码:

from PyQt5 import QtWidgets,QtGui,QtCore
from uisplit import My_Ui_MainWindow

class MainWindow(QtWidgets.QMainWindow,My_Ui_MainWindow):
    def __init__(self,parent = None):
        super(MainWindow,self).__init__(parent)
        self.setupUi(self)

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    mainWindow = MainWindow()  # 创建窗体对象
    mainWindow.show()
    sys.exit(app.exec_())

uu

def __init__(self,parent = None):
        super(MainWindow,self).__init__(parent)
        self.setupUi(self)

 

1. 方法定义:def __init__(self, parent=None):

  • self:代表类的实例本身(当前创建的窗口对象),所有成员变量和方法都需要通过self访问。
  • parent=None:指定当前窗口的父对象,默认值为None(表示这是一个顶级窗口,没有父窗口)。父对象的作用:当父窗口关闭时,子窗口会自动关闭;子窗口会跟随父窗口移动(如果设置了相关属性)。

2. 调用父类构造函数:super(MainWindow, self).__init__(parent)

这行代码的核心作用是初始化所有父类的功能,确保继承的基类能正常工作。
  • super(MainWindow, self):在多继承场景下,用于找到当前类的父类(按继承顺序)并返回一个临时对象,代表父类的上下文。
  • __init__(parent):调用父类的构造函数,将 parent 参数传递给父类,完成父类的初始化。
    由于当前类 MainWindow 同时继承了 QMainWindow 和 My_Ui_MainWindow
    • 首先会初始化 QMainWindow(Qt 自带的主窗口基类),确保窗口的基本功能(如标题栏、大小调整、关闭按钮等)可用。
    • 其次会初始化 My_Ui_MainWindow(从 .ui 文件生成的界面类),确保界面定义的资源(如中央部件、菜单栏等)被正确加载。

 

 

 parent=None不写会怎样

等用到了再说吧......

在 Qt(PyQt 基于 Qt 框架)中,根据「是否有父对象(parent)」,窗口 / 控件主要分为 顶级窗口(Top-level Window) 和 子控件(Child Widget/Sub-widget) 两大类。二者在功能、显示行为、生命周期等方面有本质区别,下面结合具体场景详细说明:

 

super(MainWindow,self)什么意思

super(MainWindow, self) 的完整作用是:
  1. 告诉 Python 解释器:“我要查找 MainWindow 类的父类”
  2. 通过 self 明确指定:“以当前这个实例的上下文去查找父类”
这样做的目的是确保在多继承场景下(比如 MainWindow 同时继承 QMainWindow 和 My_Ui_MainWindow),能正确找到父类的构造函数并初始化。
 
super(MainWindow, self) 相当于 “以当前窗口实例(self)为参照,找到它的父类(MainWindow 的父类)”,后续调用 __init__ 就是执行父类的初始化逻辑,让父类的功能在当前实例上生效。
在 Python 3 中,这行代码可以简化为 super().__init__(parent),解释器会自动推断 MainWindow 和 self 的含义,效果完全相同。

QMainWindow类

继承自QWidget
class
QMainWindow(QWidget):

QWidget有show方法

ww

import关于导入的几种写法

from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout,
                             QGridLayout, QPushButton, QLineEdit)
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QApplication

发发发

sipPyTypeDict() is deprecated

将sip包降级

解决办法,在pycharm下载pyqt5-sip包

ERROR: Could not find a version that satisfies the requirement pyqt5-sip==12.7.1 (from versions: none) ERROR: No matching distribution found for pyqt5-sip==12.7.1

是我的梯子有问题,代理有问题。

pip install --index-url https://mirrors.aliyun.com/pypi/simple/ pyqt5-sip==12.11.1

把pyqt5sip包降级到12.11.1就不报警告了。

# UI和逻辑代码分离
#
#

from PyQt5 import QtWidgets,QtGui,QtCore
from uisplit import My_Ui_MainWindow

class MainWindow(QtWidgets.QMainWindow,My_Ui_MainWindow):
    def __init__(self):
        super().__init__()
        self.setupUi(self)

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    mainWindow = MainWindow()  # 创建窗体对象
    mainWindow.show()
    sys.exit(app.exec_())

报错:

DeprecationWarning: sipPyTypeDict() is deprecated, the extension module should use sipPyTypeDictRef() instead class MainWindow(QtWidgets.QMainWindow,My_Ui_MainWindow):

class MainWindow(QtWidgets.QMainWindow):
    def __init__(self,parent=None):
        super().__init__()
        self.ui = My_Ui_MainWindow()
        self.ui.setupUi(self)

按AI推荐的办法改了还是报错。

DeprecationWarning: sipPyTypeDict() is deprecated, the extension module should use sipPyTypeDictRef() instead class MainWindow(QtWidgets.QMainWindow):

 

SIP 绑定(PyQt5 底层用于连接 Python 和 C++ 的工具)

 

pycharm快速入门指南

pycharm的快速入门指导有用,好好看看。

https://www.jetbrains.com/zh-cn/help/pycharm/quick-start-guide.html

 

 

hhh

posted on 2025-09-13 15:55  无名高地  阅读(5)  评论(0)    收藏  举报